From 03a59a24ab80c4522890fd7ef4467d11cbc5c27b Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Tue, 6 Jun 2023 17:06:24 +0800 Subject: [PATCH 001/476] fix read config bug --- .../db-resource/internal/config/config.go | 10 +++---- .../internal/controller/apply/apply.go | 26 +++++++++---------- .../db-resource/internal/lock/redis_lock.go | 5 ++-- .../db-resource/internal/lock/spinlock.go | 8 +++--- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/dbm-services/common/db-resource/internal/config/config.go b/dbm-services/common/db-resource/internal/config/config.go index ccd74a58ca..ae6fccd3f3 100644 --- a/dbm-services/common/db-resource/internal/config/config.go +++ b/dbm-services/common/db-resource/internal/config/config.go @@ -20,7 +20,7 @@ type Config struct { CmdbDb Db `yaml:"cmdb_db" mapstructure:"cmdb_db"` LoggerConfig LoggerConfig `yaml:"loggerConfig"` BkSecretConfig BkSecretConfig `yaml:"bkSecretConfig"` - RedisDb RedisDb `yaml:"redis"` + Redis Redis `yaml:"redis"` CloudCertificate *CloudCertificate `yaml:"cloudCertificate"` // dbmeta: http://bk-dbm DbMeta string `json:"dbmeta"` @@ -49,10 +49,10 @@ type BkSecretConfig struct { BkBaseUrl string `yaml:"bk_base_url" mapstructure:"bk_base_url"` } -// RedisDb TODO -type RedisDb struct { - Addr string `yaml:"addr"` - Pwd string `yaml:"password"` +// Redis TODO +type Redis struct { + Addr string `yaml:"addr"` + Password string `yaml:"password"` } // CloudCertificate TODO diff --git a/dbm-services/common/db-resource/internal/controller/apply/apply.go b/dbm-services/common/db-resource/internal/controller/apply/apply.go index f14a6491ad..2d0c0eda11 100644 --- a/dbm-services/common/db-resource/internal/controller/apply/apply.go +++ b/dbm-services/common/db-resource/internal/controller/apply/apply.go @@ -34,11 +34,6 @@ func (c *ApplyHandler) RegisterRouter(engine *gin.Engine) { } } -func newLocker(key string, requestId string) *lock.SpinLock { - return lock.NewSpinLock(&lock.RedisLock{Name: key, RandKey: requestId, Expiry: 120 * time.Second}, 60, - 350*time.Millisecond) -} - // ConfirmApplyParam TODO type ConfirmApplyParam struct { RequestId string `json:"request_id" binding:"required"` @@ -57,7 +52,7 @@ func (c *ApplyHandler) ConfirmApply(r *gin.Context) { err := model.DB.Self.Table(model.TbRpApplyDetailLogName()).Where("request_id = ?", param.RequestId).Count(&cnt).Error if err != nil { logger.Error("use request id %s,query apply resouece failed %s", param.RequestId, err.Error()) - c.SendResponse(r, fmt.Errorf("%w", err), requestId, "use request id search applyed resource failed") + c.SendResponse(r, fmt.Errorf("%w", err), "use request id search applyed resource failed", requestId) return } if len(hostIds) != int(cnt) { @@ -69,7 +64,7 @@ func (c *ApplyHandler) ConfirmApply(r *gin.Context) { err = model.DB.Self.Table(model.TbRpDetailName()).Where(" bk_host_id in (?) and status != ? ", hostIds, model.Prepoccupied).Find(&rs).Error if err != nil { - c.SendResponse(r, err, requestId, err.Error()) + c.SendResponse(r, err, err.Error(), requestId) return } if len(rs) > 0 { @@ -77,7 +72,7 @@ func (c *ApplyHandler) ConfirmApply(r *gin.Context) { for _, v := range rs { errMsg += fmt.Sprintf("%s:%s\n", v.IP, v.Status) } - c.SendResponse(r, fmt.Errorf("the following example:%s,abnormal state", errMsg), requestId, "") + c.SendResponse(r, fmt.Errorf("the following example:%s,abnormal state", errMsg), "", requestId) return } // update to used status @@ -89,10 +84,10 @@ func (c *ApplyHandler) ConfirmApply(r *gin.Context) { }, ) if err != nil { - c.SendResponse(r, err, requestId, err.Error()) + c.SendResponse(r, err, err.Error(), requestId) return } - c.SendResponse(r, nil, requestId, "successful") + c.SendResponse(r, nil, "successful", requestId) } // ApplyResource TODO @@ -105,6 +100,11 @@ func (c *ApplyHandler) PreApplyResource(r *gin.Context) { c.ApplyBase(r, model.Prepoccupied) } +func newLocker(key string, requestId string) *lock.SpinLock { + return lock.NewSpinLock(&lock.RedisLock{Name: key, RandKey: requestId, Expiry: 120 * time.Second}, 60, + 350*time.Millisecond) +} + // ApplyBase TODO func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { task.RuningTask <- struct{}{} @@ -118,14 +118,14 @@ func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { } requestId = r.GetString("request_id") if err := param.ParamCheck(); err != nil { - c.SendResponse(r, err, requestId, err.Error()) + c.SendResponse(r, err, err.Error(), requestId) return } // get the resource lock if it is dry run you do not need to acquire it if !param.DryRun { lock := newLocker(param.LockKey(), requestId) if err := lock.Lock(); err != nil { - c.SendResponse(r, err, requestId, err.Error()) + c.SendResponse(r, err, err.Error(), requestId) return } defer func() { @@ -141,7 +141,7 @@ func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { pickers, err = apply.CycleApply(param) if err != nil { logger.Error("apply machine failed %s", err.Error()) - c.SendResponse(r, err, requestId, err.Error()) + c.SendResponse(r, err, err.Error(), requestId) return } if !param.DryRun { diff --git a/dbm-services/common/db-resource/internal/lock/redis_lock.go b/dbm-services/common/db-resource/internal/lock/redis_lock.go index e0e0b6b217..31384fe689 100644 --- a/dbm-services/common/db-resource/internal/lock/redis_lock.go +++ b/dbm-services/common/db-resource/internal/lock/redis_lock.go @@ -15,9 +15,10 @@ var rdb *redis.Client // init TODO func init() { + logger.Info("redis addr %s", config.AppConfig.Redis.Addr) rdb = redis.NewClient(&redis.Options{ - Addr: config.AppConfig.RedisDb.Addr, - Password: config.AppConfig.RedisDb.Pwd, + Addr: config.AppConfig.Redis.Addr, + Password: config.AppConfig.Redis.Password, DB: 0, }) } diff --git a/dbm-services/common/db-resource/internal/lock/spinlock.go b/dbm-services/common/db-resource/internal/lock/spinlock.go index d0dfe63851..9962dff02f 100644 --- a/dbm-services/common/db-resource/internal/lock/spinlock.go +++ b/dbm-services/common/db-resource/internal/lock/spinlock.go @@ -4,6 +4,8 @@ import ( "fmt" "math/rand" "time" + + "dbm-services/common/go-pubpkg/logger" ) // TryLocker TODO @@ -29,16 +31,16 @@ type SpinLock struct { } // Lock TODO -func (l *SpinLock) Lock() error { +func (l *SpinLock) Lock() (err error) { for i := 0; i < l.spinTries; i++ { - var err error if err = l.lock.TryLock(); err == nil { return nil } + logger.Warn("%d: lock %s failed %s", i, err.Error()) time.Sleep(l.spinInterval) time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) } - return fmt.Errorf("spin lock failed after %f seconds", float64(l.spinTries)*l.spinInterval.Seconds()) + return fmt.Errorf("spin lock failed:%s ,after %f seconds", err.Error(), float64(l.spinTries)*l.spinInterval.Seconds()) } // Unlock TODO From 91e5e17e1f62aa5d3f854143588328822290069a Mon Sep 17 00:00:00 2001 From: hailinxiao Date: Tue, 6 Jun 2023 19:49:15 +0800 Subject: [PATCH 002/476] =?UTF-8?q?feat(frontend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=20#71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cluster-common/HostAgentStatus.vue} | 37 +- dbm-ui/frontend/src/hooks/index.ts | 1 + dbm-ui/frontend/src/hooks/useProps.ts | 20 + dbm-ui/frontend/src/services/dbResource.ts | 85 ++++- dbm-ui/frontend/src/services/infras.ts | 5 + .../services/model/db-resource/DbResource.ts | 74 ++++ .../services/model/db-resource/DeployPlan.ts | 29 ++ .../services/model/db-resource/Operation.ts | 67 ++++ .../src/views/main-views/pages/Platform.vue | 4 +- .../src/views/resource-pool/list/Index.vue | 172 +++++++-- .../list/components/BatchSetting.vue | 62 +++ .../list/components/DiskPopInfo.vue | 57 +++ .../list/components/ExportHostBtn.vue | 65 ++++ .../list/components/export-host/Index.vue | 130 ++++++- .../export-host/components/FormPanel.vue | 357 ++++++++++++++++++ .../components/select-host-panel/Index.vue | 167 ++++++++ .../components/HostEmpty.vue | 70 ++++ .../list/components/search-box/Index.vue | 74 +++- .../components/com-factory/DeviceClass.vue | 28 -- .../components/com-factory/Hosts.vue | 24 -- .../components/com-factory/Index.vue | 141 +++++-- .../components/com-factory/ResourceTypes.vue | 24 -- .../AgentStatus.vue} | 47 ++- .../com-factory/{ => components}/City.vue | 20 +- .../components/com-factory/components/Cpu.vue | 68 ++++ .../DeviceClass.vue} | 31 +- .../com-factory/{ => components}/Disk.vue | 39 +- .../com-factory/components/DiskType.vue | 60 +++ .../com-factory/components/ForBizs.vue | 85 +++++ .../{AgentStatus.vue => components/Hosts.vue} | 26 +- .../com-factory/{ => components}/Mem.vue | 39 +- .../{ => components}/MountPoint.vue | 26 +- .../com-factory/components/ResourceTypes.vue | 85 +++++ .../com-factory/{ => components}/Subzones.vue | 20 +- .../search-box/components/field-config.ts | 88 ++++- .../components/field-input/Index.vue | 154 +++++--- .../components/CollectSearchParams.vue | 258 +++++++++++++ .../field-input/components/SearchItem.vue | 78 ---- .../search-box/components/field-tag/Index.vue | 24 +- .../components/field-tag/ValueTag.vue | 194 +++++++++- .../components/search-box/components/utils.ts | 2 + .../src/views/resource-pool/record/Index.vue | 76 ++++ .../src/views/resource-pool/routes.ts | 11 + 43 files changed, 2782 insertions(+), 342 deletions(-) rename dbm-ui/frontend/src/{views/resource-pool/list/components/search-box/components/com-factory/Cpu.vue => components/cluster-common/HostAgentStatus.vue} (57%) create mode 100644 dbm-ui/frontend/src/hooks/useProps.ts create mode 100644 dbm-ui/frontend/src/services/infras.ts create mode 100644 dbm-ui/frontend/src/services/model/db-resource/DbResource.ts create mode 100644 dbm-ui/frontend/src/services/model/db-resource/DeployPlan.ts create mode 100644 dbm-ui/frontend/src/services/model/db-resource/Operation.ts create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/BatchSetting.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/DiskPopInfo.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/ExportHostBtn.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/FormPanel.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/components/HostEmpty.vue delete mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/DeviceClass.vue delete mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Hosts.vue delete mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ResourceTypes.vue rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ForBizs.vue => components/AgentStatus.vue} (52%) rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ => components}/City.vue (77%) create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Cpu.vue rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{DiskType.vue => components/DeviceClass.vue} (63%) rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ => components}/Disk.vue (57%) create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/DiskType.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/ForBizs.vue rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{AgentStatus.vue => components/Hosts.vue} (70%) rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ => components}/Mem.vue (57%) rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ => components}/MountPoint.vue (66%) create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/ResourceTypes.vue rename dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/{ => components}/Subzones.vue (78%) create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/CollectSearchParams.vue delete mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/SearchItem.vue create mode 100644 dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/utils.ts create mode 100644 dbm-ui/frontend/src/views/resource-pool/record/Index.vue diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Cpu.vue b/dbm-ui/frontend/src/components/cluster-common/HostAgentStatus.vue similarity index 57% rename from dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Cpu.vue rename to dbm-ui/frontend/src/components/cluster-common/HostAgentStatus.vue index e0cf23cf90..711daa63dc 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Cpu.vue +++ b/dbm-ui/frontend/src/components/cluster-common/HostAgentStatus.vue @@ -12,21 +12,40 @@ --> diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/FormPanel.vue new file mode 100644 index 0000000000..0ff7e83c81 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/FormPanel.vue @@ -0,0 +1,357 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/Index.vue new file mode 100644 index 0000000000..1dcab26ad1 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/Index.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/components/HostEmpty.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/components/HostEmpty.vue new file mode 100644 index 0000000000..4f84136e4f --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/components/select-host-panel/components/HostEmpty.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue index 827ecb2e60..8c91b63594 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue @@ -22,22 +22,30 @@
- +
diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Hosts.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Hosts.vue deleted file mode 100644 index a1adebf9ff..0000000000 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Hosts.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue index 9d0f932853..8e529a1969 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue @@ -12,42 +12,69 @@ --> + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ResourceTypes.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ResourceTypes.vue deleted file mode 100644 index d24d5a2f94..0000000000 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ResourceTypes.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ForBizs.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/AgentStatus.vue similarity index 52% rename from dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ForBizs.vue rename to dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/AgentStatus.vue index e48f6e8efa..54766050a6 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/ForBizs.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/AgentStatus.vue @@ -12,15 +12,48 @@ --> - + + withDefaults(defineProps(), { + defaultValue: undefined, + simple: false, + }); + + const emits = defineEmits(); + + defineOptions({ + inheritAttrs: false, + }); + + const { t } = useI18n(); + + + const handleChange = (value: number) => { + emits('change', value); + }; + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/City.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/City.vue similarity index 77% rename from dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/City.vue rename to dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/City.vue index 96e45fb1aa..faac51fab1 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/City.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/City.vue @@ -13,16 +13,21 @@ + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/DiskType.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/DeviceClass.vue similarity index 63% rename from dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/DiskType.vue rename to dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/DeviceClass.vue index 759bdab450..366b6f8091 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/DiskType.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/DeviceClass.vue @@ -12,7 +12,13 @@ --> diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Disk.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue similarity index 57% rename from dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Disk.vue rename to dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue index 2e73864d66..22a5a25a4f 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Disk.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue @@ -14,16 +14,51 @@ diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/CollectSearchParams.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/CollectSearchParams.vue new file mode 100644 index 0000000000..5b175e8ca5 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/CollectSearchParams.vue @@ -0,0 +1,258 @@ + + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/SearchItem.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/SearchItem.vue deleted file mode 100644 index 491604dfe9..0000000000 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/components/SearchItem.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-tag/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-tag/Index.vue index 82a701da4d..af1b029dc5 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-tag/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-tag/Index.vue @@ -16,20 +16,27 @@
+ type="funnel" />
搜索项:
diff --git a/dbm-ui/frontend/src/views/resource-pool/routes.ts b/dbm-ui/frontend/src/views/resource-pool/routes.ts index e006418ed1..cf767379fd 100644 --- a/dbm-ui/frontend/src/views/resource-pool/routes.ts +++ b/dbm-ui/frontend/src/views/resource-pool/routes.ts @@ -40,6 +40,17 @@ const routes: RouteRecordRaw[] = [ }, component: () => import('@views/resource-pool/list/Index.vue'), }, + { + name: 'resourcePoolOperationRecord', + path: 'record', + meta: { + routeParentName: MainViewRouteNames.Platform, + navName: t('操作记录'), + isMenu: true, + activeMenu: 'resourcePoolManage', + }, + component: () => import('@views/resource-pool/record/Index.vue'), + }, ], }, ]; From 2a3a67cef82b39a41df3f27cdf9da4f5cbcaac5f Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Tue, 6 Jun 2023 20:29:14 +0800 Subject: [PATCH 003/476] =?UTF-8?q?feat(frontend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=20#71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/db-table/index.vue | 277 ++++++++++++++++-- dbm-ui/frontend/src/locales/zh-cn.json | 24 +- dbm-ui/frontend/src/services/dbResource.ts | 13 + .../src/views/deployment-plan/list/Index.vue | 34 ++- .../src/views/resource-pool/record/Index.vue | 47 ++- 5 files changed, 359 insertions(+), 36 deletions(-) diff --git a/dbm-ui/frontend/src/components/db-table/index.vue b/dbm-ui/frontend/src/components/db-table/index.vue index 658748531e..11ddf384b8 100644 --- a/dbm-ui/frontend/src/components/db-table/index.vue +++ b/dbm-ui/frontend/src/components/db-table/index.vue @@ -14,23 +14,24 @@ - - + diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 54b9d38598..823f4910df 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1376,5 +1376,27 @@ "确认重启该实例?": "确认重启该实例?", "连接将会断开,请谨慎操作!": "连接将会断开,请谨慎操作!", "确认重启": "确认重启", - "8088为服务内部占用端口": "8088 为服务内部占用端口" + "8088为服务内部占用端口": "8088 为服务内部占用端口", + "请输入操作人或选择条件搜索": "请输入操作人或选择条件搜索", + "操作记录": "操作记录", + "操作状态": "操作状态", + "操作时间": "操作时间", + "操作主机明细(台)": "操作主机明细(台)", + "关联任务": "关联任务", + "请选择专用业务": "请选择专用业务", + "请选择专用 DB": "请选择专用 DB", + "请输入 IP 用,分割": "请输入 IP 用,分割", + "请选择 Agent 状态": "请选择 Agent 状态", + "请选择机型": "请选择机型", + "请选择城市": "请选择城市", + "请选择磁盘挂载点": "请选择磁盘挂载点", + "确认删除该收藏?": "确认删除该收藏?", + "删除后将不可恢复,请谨慎操作!": "删除后将不可恢复,请谨慎操作!", + "设置为收藏条件": "设置为收藏条件", + "条件名称": "条件名称", + "条件名称已存在": "条件名称已存在", + "更多条件": "更多条件", + "设置业务专用": "设置业务专用", + "搜索条件为空": "搜索条件为空", + "容量(G)": "容量(G)" } diff --git a/dbm-ui/frontend/src/services/dbResource.ts b/dbm-ui/frontend/src/services/dbResource.ts index 554938a420..e691dcdc7d 100644 --- a/dbm-ui/frontend/src/services/dbResource.ts +++ b/dbm-ui/frontend/src/services/dbResource.ts @@ -39,6 +39,18 @@ export function createDeployPlan(params: Record) { return http.post<{ count: number, results: DbResourceModel[] }>('/apis/dbresource/deploy_plan/', params); } +// 批量删除部署方案 +export function batchRemoveDeployPlan(params: { spec_ids: number[] }) { + return http.delete('/apis/dbresource/deploy_plan/batch_delete/', params); +} +// 更新部署方案 +export function updateDeployPlan(params: { id: number }) { + return http.delete(`/apis/dbresource/deploy_plan/${params.id}/`); +} +// 删除部署方案 +export function removeDeployPlan(params: { id: number }) { + return http.delete(`/apis/dbresource/deploy_plan/${params.id}/`); +} // 资源池列表 export function fetchList(params: Record) { return http.post<{ count: number, results: DbResourceModel[] }>('/apis/dbresource/resource/list/', params) @@ -109,6 +121,7 @@ export function fetchResourceImportUrls() { }>('/apis/dbresource/resource/resource_import_urls/'); } +// 查询资源操作记录 export function fetchOperationList() { return http.get<{ count: number, results: OperationModel[] }>('/apis/dbresource/resource/query_operation_list/') .then(data => ({ diff --git a/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue b/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue index de3c7e1a3e..96aa9aaca1 100644 --- a/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue +++ b/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue @@ -14,9 +14,10 @@ From 50faf60df52a4e1b547cf3b9b4278112367bfc19 Mon Sep 17 00:00:00 2001 From: daryl Date: Thu, 8 Jun 2023 10:04:26 +0800 Subject: [PATCH 004/476] =?UTF-8?q?feat(frontend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=E8=A7=84=E6=A0=BC=20&=20=E9=83=A8=E7=BD=B2=E5=8D=95?= =?UTF-8?q?=E6=8D=AE=E6=94=B9=E9=80=A0=20#113?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply-items/SpecSelector.vue | 154 +++++++ .../frontend/src/components/db-form/index.vue | 15 +- dbm-ui/frontend/src/locales/en.json | 2 +- dbm-ui/frontend/src/locales/zh-cn.json | 3 +- dbm-ui/frontend/src/services/resourceSpec.ts | 5 +- dbm-ui/frontend/src/styles/common.less | 10 + .../influxdb-manage/apply/common/base.ts | 6 + .../src/views/influxdb-manage/apply/index.vue | 105 ++++- .../views/pulsar-manage/apply/common/base.ts | 14 + .../src/views/pulsar-manage/apply/index.vue | 413 ++++++++++++------ .../src/views/resource-spec/pages/Index.vue | 6 +- .../views/tickets/components/SpecInfos.vue | 101 +++++ .../components/bigdata/DetailsInfluxDB.vue | 31 +- .../components/bigdata/DetailsPulsar.vue | 68 ++- .../tickets/components/ticketDetails.less | 5 + 15 files changed, 770 insertions(+), 168 deletions(-) create mode 100644 dbm-ui/frontend/src/components/apply-items/SpecSelector.vue create mode 100644 dbm-ui/frontend/src/views/tickets/components/SpecInfos.vue diff --git a/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue b/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue new file mode 100644 index 0000000000..48b85503f1 --- /dev/null +++ b/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/dbm-ui/frontend/src/components/db-form/index.vue b/dbm-ui/frontend/src/components/db-form/index.vue index 64fbf24d7c..cb045ab9b1 100644 --- a/dbm-ui/frontend/src/components/db-form/index.vue +++ b/dbm-ui/frontend/src/components/db-form/index.vue @@ -22,6 +22,8 @@ + + diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue index c2b024330a..7b63f4e982 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue +++ b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue @@ -60,15 +60,33 @@ +
{{ $t('访问端口') }}: {{ ticketDetails?.details?.port || '--' }}
{{ $t('备注') }}: - {{ ticketDetails?.remark || '--' }} + {{ ticketDetails?.remark || '--' }}
@@ -88,6 +106,8 @@ import { redisIpSources } from '@views/redis/apply/common/const'; + import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + interface TicketDetails { id: number, bk_biz_id: number, @@ -107,6 +127,9 @@ nodes: { influxdb: [], }, + resource_spec: { + influxdb: SpecInfo, + }, }, } @@ -119,6 +142,8 @@ const { t } = useI18n(); + const influxdbSpec = computed(() => props.ticketDetails?.details?.resource_spec?.influxdb || {}); + /** * 获取服务器数量 */ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue index 677f2f5f9f..8baac7cdf9 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue +++ b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue @@ -90,6 +90,59 @@ +
{{ $t('Partition数量') }}: {{ ticketDetails?.details?.partition_num || '--' }} @@ -112,9 +165,7 @@
{{ $t('备注') }}: - {{ ticketDetails?.remark || '--' }} + {{ ticketDetails?.remark || '--' }}
@@ -134,6 +185,8 @@ import { redisIpSources } from '@views/redis/apply/common/const'; + import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + type ServiceKeys = 'bookkeeper' | 'zookeeper' | 'broker'; interface TicketDetails { @@ -162,6 +215,11 @@ broker: [], bookkeeper: [], }, + resource_spec: { + zookeeper: SpecInfo, + broker: SpecInfo, + bookkeeper: SpecInfo, + }, }, } @@ -174,6 +232,10 @@ const { t } = useI18n(); + const zookeeperSpec = computed(() => props.ticketDetails?.details?.resource_spec?.zookeeper || {}); + const bookkeeperSpec = computed(() => props.ticketDetails?.details?.resource_spec?.bookkeeper || {}); + const brokerSpec = computed(() => props.ticketDetails?.details?.resource_spec?.broker || {}); + /** * 获取服务器数量 */ diff --git a/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less b/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less index 66b0a349b7..16698db100 100644 --- a/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less +++ b/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less @@ -59,6 +59,11 @@ } } } + + &.whole { + align-items: flex-start; + flex: 0 0 100%; + } &.table { align-items: flex-start; From 4761f48ff77f9fa46f2f233d5a43c1ea7412e1dc Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Thu, 8 Jun 2023 16:08:06 +0800 Subject: [PATCH 005/476] =?UTF-8?q?feat:=E5=85=BC=E5=AE=B9=E5=A4=9A?= =?UTF-8?q?=E4=BA=91=E5=8C=BA=E5=9F=9F=E7=94=B3=E8=AF=B7=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/controller/manage/rs_import.go | 25 +++++++++++++----- .../internal/model/TbRpOperatorInfo.go | 26 +++++++++++-------- .../db-resource/internal/svr/apply/api.go | 3 ++- .../db-resource/internal/svr/apply/apply.go | 8 ++++-- .../db-resource/internal/svr/bk/cc_test.go | 2 +- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go index d32c86b695..9be123ffdc 100644 --- a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go +++ b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go @@ -30,7 +30,7 @@ type ImportMachParam struct { apply.ActionInfo } -func (p ImportMachParam) getOperationInfo(requestId string) model.TbRpOperationInfo { +func (p ImportMachParam) getOperationInfo(requestId string, hostIds json.RawMessage) model.TbRpOperationInfo { return model.TbRpOperationInfo{ RequestID: requestId, OperationType: model.Imported, @@ -39,6 +39,7 @@ func (p ImportMachParam) getOperationInfo(requestId string) model.TbRpOperationI BillId: p.BillId, Operator: p.Operator, CreateTime: time.Now(), + BkHostIds: hostIds, UpdateTime: time.Now(), } } @@ -51,6 +52,14 @@ func (p ImportMachParam) getIps() (ips []string) { } return } +func (p ImportMachParam) getHostIds() (hostIds []int) { + for _, v := range p.Hosts { + if v.HostId > 0 { + hostIds = append(hostIds, v.HostId) + } + } + return +} // HostBase TODO type HostBase struct { @@ -87,7 +96,7 @@ func (c *MachineResourceHandler) Import(r *rf.Context) { c.SendResponse(r, err, requestId, err.Error()) return } - resp, err := ImportByListHostBiz(input) + resp, err := Doimport(input) if err != nil { logger.Error(fmt.Sprintf("ImportByIps failed %s", err.Error())) c.SendResponse(r, err, requestId, err.Error()) @@ -97,7 +106,12 @@ func (c *MachineResourceHandler) Import(r *rf.Context) { c.SendResponse(r, fmt.Errorf("all machines failed to query cmdb information"), resp, requestId) return } - task.RecordRsOperatorInfoChan <- input.getOperationInfo(requestId) + hostIds, err := json.Marshal(input.getHostIds()) + if err != nil { + c.SendResponse(r, fmt.Errorf("fail marshal bkhostIds"), resp, requestId) + return + } + task.RecordRsOperatorInfoChan <- input.getOperationInfo(requestId, hostIds) c.SendResponse(r, err, resp, requestId) } @@ -107,8 +121,8 @@ type ImportHostResp struct { NotFoundInCCHosts []string `json:"not_found_in_cc_hosts"` } -// ImportByListHostBiz TODO -func ImportByListHostBiz(param ImportMachParam) (resp *ImportHostResp, err error) { +// Doimport TODO +func Doimport(param ImportMachParam) (resp *ImportHostResp, err error) { var ccHostsInfo []*cc.Host var berr, derr error var failedHostInfo map[string]string @@ -117,7 +131,6 @@ func ImportByListHostBiz(param ImportMachParam) (resp *ImportHostResp, err error resp = &ImportHostResp{} wg := sync.WaitGroup{} diskMap := make(map[string]*bk.ShellResCollection) - lableJson, err := cmutil.ConverMapToJsonStr(cmutil.CleanStrMap(param.Labels)) if err != nil { logger.Error(fmt.Sprintf("ConverLableToJsonStr Failed,Error:%s", err.Error())) diff --git a/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go b/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go index 1da16c17da..48dd7865d6 100644 --- a/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go +++ b/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go @@ -1,6 +1,9 @@ package model -import "time" +import ( + "encoding/json" + "time" +) const ( // Consumed TODO @@ -11,16 +14,17 @@ const ( // TbRpOperationInfo TODO type TbRpOperationInfo struct { - ID int `gorm:"primaryKey;auto_increment;not null" json:"-"` - RequestID string `gorm:"index:idx_request_id;column:request_id;type:varchar(64);not null" json:"request_id"` - TotalCount int `gorm:"column:total_count;type:int(11);comment:'task Id'" json:"total_count"` - OperationType string `gorm:"column:operation_type;type:varchar(64);not null;comment:'operation type'" json:"operation_type"` - Operator string `gorm:"column:operator;type:varchar(64);not null;comment:'operator user'" json:"operator"` - Status string `gorm:"column:status;type:varchar(64);not null;comment:'operator user'" json:"-"` - TaskId string `gorm:"column:task_id;type:varchar(128);not null;comment:'task Id'" json:"task_id"` - BillId string `gorm:"column:bill_id;type:varchar(128);not null;comment:'bill Id'" json:"bill_id"` - UpdateTime time.Time `gorm:"column:update_time;type:timestamp" json:"update_time"` // 最后修改时间 - CreateTime time.Time `gorm:"column:create_time;type:datetime" json:"create_time"` // 创建时间 + ID int `gorm:"primaryKey;auto_increment;not null" json:"-"` + RequestID string `gorm:"index:idx_request_id;column:request_id;type:varchar(64);not null" json:"request_id"` + TotalCount int `gorm:"column:total_count;type:int(11);comment:'task Id'" json:"total_count"` + BkHostIds json.RawMessage `gorm:"column:bk_host_ids;type:json;comment:'主机Id'" json:"bk_host_ids"` + OperationType string `gorm:"column:operation_type;type:varchar(64);not null;comment:'operation type'" json:"operation_type"` + Operator string `gorm:"column:operator;type:varchar(64);not null;comment:'operator user'" json:"operator"` + Status string `gorm:"column:status;type:varchar(64);not null;comment:'operator user'" json:"-"` + TaskId string `gorm:"column:task_id;type:varchar(128);not null;comment:'task Id'" json:"task_id"` + BillId string `gorm:"column:bill_id;type:varchar(128);not null;comment:'bill Id'" json:"bill_id"` + UpdateTime time.Time `gorm:"column:update_time;type:timestamp" json:"update_time"` // 最后修改时间 + CreateTime time.Time `gorm:"column:create_time;type:datetime" json:"create_time"` // 创建时间 } // TableName TODO diff --git a/dbm-services/common/db-resource/internal/svr/apply/api.go b/dbm-services/common/db-resource/internal/svr/apply/api.go index 8814298e79..1f340edf45 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/api.go +++ b/dbm-services/common/db-resource/internal/svr/apply/api.go @@ -51,7 +51,7 @@ type ActionInfo struct { type ApplyRequestInputParam struct { ResourceType string `json:"resource_type"` // 申请的资源用作的用途 Redis|MySQL|Proxy DryRun bool `json:"dry_run"` - BkCloudId int `json:"bk_cloud_id" binding:"number"` + BkCloudId int `json:"bk_cloud_id"` ForbizId int `json:"for_biz_id"` Details []ApplyObjectDetail `json:"details" binding:"required,gt=0,dive"` ActionInfo @@ -96,6 +96,7 @@ const ( // ApplyObjectDetail TODO type ApplyObjectDetail struct { + BkCloudId int `json:"bk_cloud_id"` GroupMark string `json:"group_mark" binding:"required" ` // 资源组标记 Labels map[string]string `json:"labels"` // 标签 // 通过机型规格 或者 资源规格描述来匹配资源 diff --git a/dbm-services/common/db-resource/internal/svr/apply/apply.go b/dbm-services/common/db-resource/internal/svr/apply/apply.go index 3bca53598a..381a4f9a56 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/apply.go +++ b/dbm-services/common/db-resource/internal/svr/apply/apply.go @@ -107,7 +107,11 @@ func (o *SearchContext) Matcher() (fns []func(db *gorm.DB)) { } func (o *SearchContext) pickBase(db *gorm.DB) (err error) { - db.Where(" bk_cloud_id = ? and status = ? ", o.BkCloudId, model.Unused) + if o.BkCloudId <= 0 { + db.Where(" bk_cloud_id = ? and status = ? ", o.ApplyObjectDetail.BkCloudId, model.Unused) + } else { + db.Where(" bk_cloud_id = ? and status = ? ", o.BkCloudId, model.Unused) + } // 如果没有指定资源类型,表示只能选择无资源类型标签的资源 // 没有资源类型标签的资源可以被所有其他类型使用 if cmutil.IsEmpty(o.RsType) { @@ -132,7 +136,7 @@ func (o *SearchContext) pickBase(db *gorm.DB) (err error) { if o.Affinity == SAME_SUBZONE_CROSS_SWTICH { o.UseNetDeviceIsNotEmpty(db) } - return + return nil } // PickCheck TODO diff --git a/dbm-services/common/db-resource/internal/svr/bk/cc_test.go b/dbm-services/common/db-resource/internal/svr/bk/cc_test.go index 6f66453bc2..be740211d8 100644 --- a/dbm-services/common/db-resource/internal/svr/bk/cc_test.go +++ b/dbm-services/common/db-resource/internal/svr/bk/cc_test.go @@ -66,7 +66,7 @@ func TestReserverCC(t *testing.T) { RsTypes: []string{"MySQL", "Redis"}, Hosts: hosts, } - importResp, err := manage.ImportByListHostBiz(param) + importResp, err := manage.Doimport(param) if err != nil { t.Fatal(err) } From ccd1e307a4b5f1759c887c4c9721acf23f87bf04 Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Fri, 9 Jun 2023 16:21:11 +0800 Subject: [PATCH 006/476] =?UTF-8?q?feat:=20add=E8=BF=94=E5=9B=9E=E6=89=80?= =?UTF-8?q?=E6=9C=89unused=E6=88=96=E4=BD=BF=E7=94=A8=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/controller/manage/rs.go | 20 +++++++ .../internal/controller/manage/rs_import.go | 55 ++++++++++--------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/dbm-services/common/db-resource/internal/controller/manage/rs.go b/dbm-services/common/db-resource/internal/controller/manage/rs.go index 4e3a2ccffd..d397a4cf75 100644 --- a/dbm-services/common/db-resource/internal/controller/manage/rs.go +++ b/dbm-services/common/db-resource/internal/controller/manage/rs.go @@ -25,6 +25,7 @@ func (c *MachineResourceHandler) RegisterRouter(engine *rf.Engine) { r := engine.Group("resource") { r.POST("/list", c.List) + r.POST("/list/all", c.ListAll) r.POST("/update", c.Update) r.POST("/delete", c.Delete) r.POST("/import", c.Import) @@ -56,6 +57,25 @@ type MachineResourceGetterInputParam struct { Offset int `json:"offset"` } +// ListAll TODO +func (c *MachineResourceHandler) ListAll(r *rf.Context) { + requestId := r.GetString("request_id") + var data []model.TbRpDetail + db := model.DB.Self.Table(model.TbRpDetailName()).Where("status in (?)", []string{model.Unused, model.Prepoccupied, + model.Preselected}) + err := db.Scan(&data).Error + if err != nil { + c.SendResponse(r, err, requestId, err.Error()) + return + } + var count int64 + if err := db.Count(&count).Error; err != nil { + c.SendResponse(r, err, requestId, err.Error()) + return + } + c.SendResponse(r, nil, map[string]interface{}{"details": data, "count": count}, requestId) +} + // List TODO func (c *MachineResourceHandler) List(r *rf.Context) { var input MachineResourceGetterInputParam diff --git a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go index 9be123ffdc..238d064611 100644 --- a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go +++ b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go @@ -173,7 +173,6 @@ func Doimport(param ImportMachParam) (resp *ImportHostResp, err error) { if len(notFoundHosts) >= len(param.Hosts) { return resp, fmt.Errorf("all hosts query empty in cc") } - if derr != nil { logger.Error("search disk info by job failed %s", derr.Error()) // return @@ -190,31 +189,7 @@ func Doimport(param ImportMachParam) (resp *ImportHostResp, err error) { logger.Info("more info %v", ccHostsInfo) for _, h := range ccHostsInfo { delete(hostsMap, h.InnerIP) - el := model.TbRpDetail{ - RsTypes: rstypes, - DedicatedBizs: bizJson, - BkCloudID: param.BkCloudId, - BkBizId: param.BkBizId, - AssetID: h.AssetID, - BkHostID: h.BKHostId, - IP: h.InnerIP, - Label: lableJson, - DeviceClass: h.DeviceClass, - DramCap: h.BkMem, - CPUNum: h.BkCpu, - City: h.IdcCityName, - CityID: h.IdcCityId, - SubZone: h.SZone, - SubZoneID: h.SZoneID, - RackID: h.Equipment, - SvrTypeName: h.SvrTypeName, - Status: model.Unused, - NetDeviceID: h.LinkNetdeviceId, - StorageDevice: []byte("{}"), - TotalStorageCap: h.BkDisk, - UpdateTime: time.Now(), - CreateTime: time.Now(), - } + el := transHostInfoToDbModule(h, param.BkCloudId, param.BkBizId, rstypes, bizJson, lableJson) el.SetMore(h.InnerIP, diskMap) elems = append(elems, el) } @@ -226,6 +201,34 @@ func Doimport(param ImportMachParam) (resp *ImportHostResp, err error) { return resp, err } +func transHostInfoToDbModule(h *cc.Host, bkCloudId, bkBizId int, rstp, biz []byte, label string) model.TbRpDetail { + return model.TbRpDetail{ + RsTypes: rstp, + DedicatedBizs: biz, + BkCloudID: bkCloudId, + BkBizId: bkBizId, + AssetID: h.AssetID, + BkHostID: h.BKHostId, + IP: h.InnerIP, + Label: label, + DeviceClass: h.DeviceClass, + DramCap: h.BkMem, + CPUNum: h.BkCpu, + City: h.IdcCityName, + CityID: h.IdcCityId, + SubZone: h.SZone, + SubZoneID: h.SZoneID, + RackID: h.Equipment, + SvrTypeName: h.SvrTypeName, + Status: model.Unused, + NetDeviceID: h.LinkNetdeviceId, + StorageDevice: []byte("{}"), + TotalStorageCap: h.BkDisk, + UpdateTime: time.Now(), + CreateTime: time.Now(), + } +} + // probeFromCloud Detect The Disk Type Again Through The Cloud Interface func probeFromCloud(diskMap map[string]*bk.ShellResCollection) { var clouder cloud.Disker From deaaa8a37d41455e6a8f6c5df3bff7d5f49b60fa Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Thu, 8 Jun 2023 17:42:15 +0800 Subject: [PATCH 007/476] =?UTF-8?q?feat(frontend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=20#71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 1 + dbm-ui/frontend/src/locales/zh-cn.json | 11 +- dbm-ui/frontend/src/services/dbResource.ts | 2 +- .../services/model/db-resource/DbResource.ts | 11 +- .../services/model/db-resource/DeployPlan.ts | 6 +- .../services/model/db-resource/Operation.ts | 4 + .../src/views/deployment-plan/list/Index.vue | 182 ++++++++++++++---- .../list/components/Operation.vue | 127 +++++++++--- .../src/views/resource-pool/list/Index.vue | 14 +- .../list/components/ExportHostBtn.vue | 3 +- .../com-factory/components/ForBizs.vue | 3 +- .../com-factory/components/Hosts.vue | 2 +- .../com-factory/components/ResourceTypes.vue | 3 +- .../src/views/resource-pool/record/Index.vue | 59 +++++- .../record/components/HostDetail.vue | 82 ++++++++ 15 files changed, 427 insertions(+), 83 deletions(-) create mode 100644 dbm-ui/frontend/src/views/resource-pool/record/components/HostDetail.vue diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index e156793fe6..1510fa5e96 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -7,6 +7,7 @@ "dev-https": "vite --https", "build": "rimraf dist && vite build --mode production", "preview": "vite preview", + "type-check": "vue-tsc --noEmit", "prepare": "cd ../.. && husky install dbm-ui/frontend/.husky", "lint:lint-staged": "lint-staged", "lint:script": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx --fix", diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 430aeef7aa..24637812ec 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1401,5 +1401,14 @@ "设置业务专用": "设置业务专用", "搜索条件为空": "搜索条件为空", "容量(G)": "容量(G)", - "DataNodes节点规格": "DataNodes 节点规格" + "DataNodes节点规格": "DataNodes 节点规格", + "本页全选": "本页全选", + "跨页全选": "跨页全选", + "请输入 IP/IPv6/主机名称 或 选择条件搜索": "请输入 IP/IPv6/主机名称 或 选择条件搜索", + "(从 CMDB 的 DBA 业务空闲机导入)": "(从 CMDB 的 DBA 业务空闲机导入)", + "暂无数据,请从左侧添加对象": "暂无数据,请从左侧添加对象", + "导入主机": "导入主机", + "选择磁盘类型": "选择磁盘类型", + "该方案已被使用,无法删除": "该方案已被使用,无法删除", + "部署方案克隆成功": "部署方案克隆成功" } diff --git a/dbm-ui/frontend/src/services/dbResource.ts b/dbm-ui/frontend/src/services/dbResource.ts index e691dcdc7d..9c7666fc07 100644 --- a/dbm-ui/frontend/src/services/dbResource.ts +++ b/dbm-ui/frontend/src/services/dbResource.ts @@ -36,7 +36,7 @@ export function fetchDeployPlan(params: { // 新建部署方案 export function createDeployPlan(params: Record) { - return http.post<{ count: number, results: DbResourceModel[] }>('/apis/dbresource/deploy_plan/', params); + return http.post('/apis/dbresource/deploy_plan/', params); } // 批量删除部署方案 diff --git a/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts b/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts index 0adac4987e..7495cec0d8 100644 --- a/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts +++ b/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts @@ -35,7 +35,14 @@ export default class DbResource { raid: string; resource_types: string[]; status: string; - storage_device: Record; + storage_device: { + [key: string]: { + size: number; + disk_id: string; + disk_type: string; + file_type: string; + } + }; sub_zone: string; sub_zone_id: string; svr_type_name: string; @@ -65,7 +72,7 @@ export default class DbResource { this.raid = payload.raid; this.resource_types = payload.resource_types || []; this.status = payload.status; - this.storage_device = payload.storage_device; + this.storage_device = payload.storage_device || {}; this.sub_zone = payload.sub_zone; this.sub_zone_id = payload.sub_zone_id; this.svr_type_name = payload.svr_type_name; diff --git a/dbm-ui/frontend/src/services/model/db-resource/DeployPlan.ts b/dbm-ui/frontend/src/services/model/db-resource/DeployPlan.ts index ca1f24c95e..bfdc01d5d3 100644 --- a/dbm-ui/frontend/src/services/model/db-resource/DeployPlan.ts +++ b/dbm-ui/frontend/src/services/model/db-resource/DeployPlan.ts @@ -1,10 +1,11 @@ export default class DeployPlan { - id: number; capacity: number; cluster_type: string; creator: string; create_at: string; desc: string; + id: number; + is_refer: boolean; machine_pair_cnt: number; name: string; shard_cnt: number; @@ -13,12 +14,13 @@ export default class DeployPlan { update_at: string; constructor(payload = {} as DeployPlan) { - this.id = payload.id; this.capacity = payload.capacity; this.cluster_type = payload.cluster_type; this.creator = payload.creator; this.create_at = payload.create_at; this.desc = payload.desc; + this.id = payload.id; + this.is_refer = Boolean(payload.is_refer); this.machine_pair_cnt = payload.machine_pair_cnt; this.name = payload.name; this.shard_cnt = payload.shard_cnt; diff --git a/dbm-ui/frontend/src/services/model/db-resource/Operation.ts b/dbm-ui/frontend/src/services/model/db-resource/Operation.ts index f8e42cde75..571ef549bf 100644 --- a/dbm-ui/frontend/src/services/model/db-resource/Operation.ts +++ b/dbm-ui/frontend/src/services/model/db-resource/Operation.ts @@ -11,6 +11,8 @@ export default class Operation { static STATUS_FAILED = STATUS_FAILED; static STATUS_REVOKED = STATUS_REVOKED; + bk_biz_id: number; + bk_host_ids: number[]; create_time: string; operation_type: string; operator: string; @@ -22,6 +24,8 @@ export default class Operation { update_time: string; constructor(payload = {} as Operation) { + this.bk_biz_id = payload.bk_biz_id || 0; + this.bk_host_ids = payload.bk_host_ids || []; this.create_time = payload.create_time; this.operation_type = payload.operation_type; this.operator = payload.operator; diff --git a/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue b/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue index 96aa9aaca1..8eade537c7 100644 --- a/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue +++ b/dbm-ui/frontend/src/views/deployment-plan/list/Index.vue @@ -14,87 +14,109 @@ diff --git a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue index c94948fdf5..966e31d444 100644 --- a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue @@ -60,9 +60,7 @@ {{ $t('自动从资源池匹配') }} @@ -73,118 +71,226 @@ - + + + {{ $t('1_3台_小于3时从Namenode节点复用') }} + + + + + + +
+ + + + + + + {{ $t('至少n台', { n: 2 }) }} + + +
+
+ + + G + + + @@ -239,6 +345,7 @@ import CloudItem from '@components/apply-items/CloudItem.vue'; import ClusterAlias from '@components/apply-items/ClusterAlias.vue'; import ClusterName from '@components/apply-items/ClusterName.vue'; + import SpecSelector from '@components/apply-items/SpecSelector.vue'; import HdfsHostTable, { type IHostTableData, } from '@components/cluster-common/big-data-host-table/HdfsHostTable.vue'; @@ -262,6 +369,20 @@ zookeeper: [] as Array, datanode: [] as Array, }, + resource_spec: { + zookeeper: { + spec_id: '', + count: 3, + }, + datanode: { + spec_id: '', + count: 2, + }, + namenode: { + spec_id: '', + count: 2, + }, + }, http_port: 50070, rpc_port: 9000, }, @@ -271,6 +392,9 @@ const getSmartActionOffsetTarget = () => document.querySelector('.bk-form-content'); const formRef = ref(); + const specDatanodeRef = ref(); + const specNamenodeRef = ref(); + const specZookeeperRef = ref(); const isDbVersionLoading = ref(true); const dbVersionList = shallowRef>([]); const formData = reactive(genDefaultFormData()); @@ -279,6 +403,7 @@ id: '' as number | string, name: '', }); + const totalCapacity = ref(0); const rules = { 'details.nodes.namenode': [ @@ -326,6 +451,15 @@ ], }; + watch(() => formData.details.resource_spec.datanode, () => { + const count = Number(formData.details.resource_spec.datanode.count); + if (specDatanodeRef.value) { + const { storage_spec: storageSpec = [] } = specDatanodeRef.value.getData(); + const disk = storageSpec.reduce((total: number, item: { size: number }) => total + Number(item.size || 0), 0); + totalCapacity.value = disk * count; + } + }, { flush: 'post', deep: true }); + // 获取 DB 版本列表 getVersions({ query_key: 'hdfs', @@ -416,16 +550,48 @@ bk_cloud_id: item.cloud_area.id, bk_biz_id: item.biz.id, })); - const params = { - ...formData, - details: { - ...formData.details, + + const getDetails = () => { + const details: Record = { ...markRaw(formData.details) }; + + if (formData.details.ip_source === 'resource_pool') { + delete details.nodes; + return { + ...details, + resource_spec: { + zookeeper: { + ...details.resource_spec.zookeeper, + ...specZookeeperRef.value.getData(), + count: Number(details.resource_spec.zookeeper.count), + }, + namenode: { + ...details.resource_spec.namenode, + ...specNamenodeRef.value.getData(), + count: Number(details.resource_spec.namenode.count), + }, + datanode: { + ...details.resource_spec.datanode, + ...specDatanodeRef.value.getData(), + count: Number(details.resource_spec.datanode.count), + }, + }, + }; + } + + delete details.resource_spec; + return { + ...details, nodes: { zookeeper: mapIpField(formData.details.nodes.zookeeper), namenode: mapIpField(formData.details.nodes.namenode), datanode: mapIpField(formData.details.nodes.datanode), }, - }, + }; + }; + + const params = { + ...formData, + details: getDetails(), }; // 若业务没有英文名称则先创建业务英文名称再创建单据,否则直接创建单据 bizState.hasEnglishName ? handleCreateTicket(params) : handleCreateAppAbbr(params); @@ -469,6 +635,28 @@ color: #63656e; } + .resource-pool-item { + width: 655px; + padding: 24px 0; + background-color: #F5F7FA; + border-radius: 2px; + + .bk-form-item { + .bk-form-label { + width: 120px !important; + } + + .bk-form-content { + margin-left: 120px !important; + + .bk-select, + .bk-input { + width: 314px; + } + } + } + } + .access-port-box { padding: 16px 10px; font-size: 12px; diff --git a/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue b/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue index fc62cfeea8..e170b28fba 100644 --- a/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue +++ b/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue @@ -281,6 +281,7 @@ influxdb: { ...details.resource_spec.influxdb, ...specRef.value.getData(), + count: Number(details.resource_spec.influxdb.count), }, }, }; diff --git a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue index 1486f1b87a..bca9ed2fe3 100644 --- a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue @@ -59,9 +59,7 @@ {{ $t('自动从资源池匹配') }} @@ -72,121 +70,191 @@ - + +
+ +
+ + + + +
+ +
+ +
+ + + +
+ +
+
+
+ +
+ + + + + + {{ $t('至少3台_且为奇数') }} + +
+
+ +
+ + + + + + +
+
+ + + G + +
+
+ + + + {{ $t('范围1025_65535') }} + + + + + + + + + {{ $t('小时') }} + + + + + + {{ $t('需小于等于broker数量') }} + + @@ -241,6 +309,7 @@ import CloudItem from '@components/apply-items/CloudItem.vue'; import ClusterAlias from '@components/apply-items/ClusterAlias.vue'; import ClusterName from '@components/apply-items/ClusterName.vue'; + import SpecSelector from '@components/apply-items/SpecSelector.vue'; import RenderHostTable, { type IHostTableData, } from '@components/cluster-common/big-data-host-table/RenderHostTable.vue'; @@ -268,6 +337,16 @@ zookeeper: [] as Array, broker: [] as Array, }, + resource_spec: { + zookeeper: { + spec_id: '', + count: 3, + }, + broker: { + spec_id: '', + count: 1, + }, + }, port: 5000, partition_num: 1, retention_hours: 1, @@ -305,16 +384,40 @@ ], 'details.replication_num': [ { - validator: (value: number) => value <= formData.details.nodes.broker.length, + validator: (value: number) => { + if (formData.details.ip_source === 'resource_pool') { + return value <= formData.details.resource_spec.broker.count; + } + return value <= formData.details.nodes.broker.length; + }, message: t('副本数需小于等于Broker数量'), trigger: 'change', }, ], + 'details.resource_spec.zookeeper.count': [ + { + validator: (value: number) => value % 2 === 1, + message: t('至少3台_且为奇数'), + trigger: 'change', + }, + ], }; const formRef = ref(); + const specZookeeperRef = ref(); + const specBrokerRef = ref(); const isDbVersionLoading = ref(true); const dbVersionList = shallowRef>([]); const formData = reactive(genDefaultFormData()); + const totalCapacity = ref(0); + + watch(() => formData.details.resource_spec.broker, () => { + const count = Number(formData.details.resource_spec.broker.count); + if (specBrokerRef.value) { + const { storage_spec: storageSpec = [] } = specBrokerRef.value.getData(); + const disk = storageSpec.reduce((total: number, item: { size: number }) => total + Number(item.size || 0), 0); + totalCapacity.value = disk * count; + } + }, { flush: 'post', deep: true }); // 获取 DB 版本列表 getVersions({ @@ -391,15 +494,42 @@ bk_cloud_id: item.cloud_area.id, bk_biz_id: item.biz.id, })); - const params = { - ...formData, - details: { - ...formData.details, + + const getDetails = () => { + const details: Record = { ...markRaw(formData.details) }; + + if (formData.details.ip_source === 'resource_pool') { + delete details.nodes; + return { + ...details, + resource_spec: { + zookeeper: { + ...details.resource_spec.zookeeper, + ...specZookeeperRef.value.getData(), + count: Number(details.resource_spec.zookeeper.count), + }, + broker: { + ...details.resource_spec.broker, + ...specBrokerRef.value.getData(), + count: Number(details.resource_spec.broker.count), + }, + }, + }; + } + + delete details.resource_spec; + return { + ...details, nodes: { zookeeper: mapIpField(formData.details.nodes.zookeeper), broker: mapIpField(formData.details.nodes.broker), }, - }, + }; + }; + + const params = { + ...formData, + details: getDetails(), }; // 若业务没有英文名称则先创建业务英文名称再创建单据,否则直接创建单据 bizState.hasEnglishName ? handleCreateTicket(params) : handleCreateAppAbbr(params); @@ -442,5 +572,27 @@ line-height: 20px; color: #63656e; } + + .resource-pool-item { + width: 655px; + padding: 24px 0; + background-color: #F5F7FA; + border-radius: 2px; + + .bk-form-item { + .bk-form-label { + width: 120px !important; + } + + .bk-form-content { + margin-left: 120px !important; + + .bk-select, + .bk-input { + width: 314px; + } + } + } + } } diff --git a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue index aec03baaf2..e2e4f1eaba 100644 --- a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue +++ b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue @@ -189,6 +189,16 @@ type="number" @blur="handleCalcIps" /> + + + {{ $t('自动从资源池匹配') }} @@ -209,69 +217,107 @@ - - - - - - - - - - +
{{ $t('备注') }}: >, + interface Details extends TicketDetailsHDFS { + ip_source: string, + resource_spec: { + namenode: SpecInfo, + zookeeper: SpecInfo, + datanode: SpecInfo, }, - }); + } + + interface Props{ + ticketDetails: TicketDetails
+ } + + const props = defineProps(); const { t } = useI18n(); + const zookeeperSpec = computed(() => props.ticketDetails?.details?.resource_spec?.zookeeper || {}); + const namenodeSpec = computed(() => props.ticketDetails?.details?.resource_spec?.namenode || {}); + const datanodeSpec = computed(() => props.ticketDetails?.details?.resource_spec?.datanode || {}); + /** * 获取服务器数量 */ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue index 7b63f4e982..f1e0cd5852 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue +++ b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue @@ -29,15 +29,6 @@
-
- {{ $t('地域要求') }} -
-
- {{ $t('数据库部署地域') }}: - {{ ticketDetails?.details?.city_code || '--' }} -
-
-
{{ $t('部署需求') }}
diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue index f990246b83..4c6b7d6c23 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue +++ b/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue @@ -33,15 +33,6 @@
-
- {{ $t('地域要求') }} -
-
- {{ $t('数据库部署地域') }}: - {{ ticketDetails?.details?.city_code || '--' }} -
-
-
{{ $t('部署需求') }}
@@ -77,6 +68,42 @@
+
{{ $t('备注') }}: diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue index 8c91b63594..22fe2996cc 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/Index.vue @@ -78,7 +78,7 @@ searchParams.value[fieldName] = urlSearchParams[fieldName]; } }); - console.log('print searchParams = ', searchParams); + // 切换搜索展示样式 const handleToggle = () => { renderStatus.value = renderStatus.value === 'input' ? 'tag' : 'input'; @@ -98,7 +98,7 @@ [key]: value.join(','), }; } - if (config.type === 'rang', value.length > 0) { + if (config.type === 'rang' && value.length > 0) { return { ...result, [key]: `${value[0]}-${value[1]}`, @@ -106,9 +106,10 @@ } return { ...result, - [key]: value.join(','), + [key]: value, }; }, {} as Record); + emits('change', result); }; diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue index 8e529a1969..3ebd5e879c 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/Index.vue @@ -110,11 +110,13 @@ return Promise.resolve(true); } const result = config.validator(props.model[props.name]); - + console.log('getValuegetValuegetValue = ', props.name, props.model[props.name], result); if (_.isString(result)) { errorMessage.value = result; return Promise.reject(false); } + + errorMessage.value = ''; return Promise.resolve(true); }, }); diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Cpu.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Cpu.vue index b67d195ff4..b951e3e7cf 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Cpu.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Cpu.vue @@ -51,6 +51,9 @@ watch(() => props.defaultValue, () => { if (props.defaultValue) { [min.value, max.value] = props.defaultValue; + } else { + min.value = ''; + max.value = ''; } }, { immediate: true, diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue index 22a5a25a4f..4f2f3cf6b1 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Disk.vue @@ -51,6 +51,9 @@ watch(() => props.defaultValue, () => { if (props.defaultValue) { [min.value, max.value] = props.defaultValue; + } else { + min.value = ''; + max.value = ''; } }, { immediate: true, diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Mem.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Mem.vue index f552bed094..a0a3344566 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Mem.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/com-factory/components/Mem.vue @@ -51,6 +51,9 @@ watch(() => props.defaultValue, () => { if (props.defaultValue) { [min.value, max.value] = props.defaultValue; + } else { + min.value = ''; + max.value = ''; } }, { immediate: true, diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-config.ts b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-config.ts index 705a0c2238..3a3d0e307a 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-config.ts +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-config.ts @@ -63,7 +63,7 @@ export default { hosts: { label: 'IP', component: 'hosts', - type: 'array', + type: 'string', flex: 2, validator: (value: string) => { if (!value) { diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/Index.vue index 322ce70e84..5adb5082b3 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/search-box/components/field-input/Index.vue @@ -113,10 +113,10 @@ diff --git a/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue b/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue index 48b85503f1..19c2f8e9a2 100644 --- a/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue +++ b/dbm-ui/frontend/src/components/apply-items/SpecSelector.vue @@ -74,7 +74,7 @@ const list = computed(() => data.value?.results || []); - watch([props.clusterType, props.machineType], () => { + watch([() => props.clusterType, () => props.machineType], () => { if (props.clusterType && props.machineType) { fetchData({ limit: -1, diff --git a/dbm-ui/frontend/src/locales/en.json b/dbm-ui/frontend/src/locales/en.json index ad3aa4dcbc..0f1686fe35 100644 --- a/dbm-ui/frontend/src/locales/en.json +++ b/dbm-ui/frontend/src/locales/en.json @@ -1384,7 +1384,6 @@ "DataNodes节点规格": "DataNodes node specification", "Proxy存储资源规格": "Proxy storage resource specification", "n台": "{0} units", - "以下Client_冷_热节点任意一台即可": "Any one of the following clients, cold or hot, is fine", "关联任务": "Associated tasks", "冷节点规格": "Cold Node Specifications", "删除后将不可恢复,请谨慎操作!": "It cannot be restored after deletion, please operate with caution!", diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 2d4ce94091..1287be8d77 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1413,8 +1413,11 @@ "至少3台_且为奇数": "至少 3 台,且为奇数", "1_3台_小于3时从Namenode节点复用": "1-3 台,小于 3 时从 Namenode 节点复用", "n台": "{0} 台", - "以下Client_冷_热节点任意一台即可": "以下 Client,冷,热 节点任意一台即可", + "请保证冷热节点至少存在一台": "请保证冷/热节点至少存在一台", "热节点规格": "热节点规格", "冷节点规格": "冷节点规格", - "管理": "管理" + "管理": "管理", + "挂载点name重复": "挂载点({name})重复", + "Proxy规格": "Proxy 规格", + "机器组数": "机器组数" } diff --git a/dbm-ui/frontend/src/views/es-manage/apply/Index.vue b/dbm-ui/frontend/src/views/es-manage/apply/Index.vue index 143b6a1765..1e2771826b 100644 --- a/dbm-ui/frontend/src/views/es-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/es-manage/apply/Index.vue @@ -199,12 +199,6 @@
- - -
@@ -231,6 +225,12 @@
+ + +
@@ -378,7 +378,7 @@ cluster_alias: '', city_code: '', db_version: '', - ip_source: 'manual_input', + ip_source: 'resource_pool', nodes: { master: [] as Array, client: [] as Array, @@ -432,13 +432,10 @@ if (isClickSubmit.value === false) return 'info'; const { - client, hot, cold, } = formData.details.resource_spec; - const isPass = Boolean(client.spec_id && client.count) - || Boolean(hot.spec_id && hot.count) - || Boolean(cold.spec_id && cold.count); + const isPass = Boolean(hot.spec_id && hot.count) || Boolean(cold.spec_id && cold.count); return (isPass ? 'info' : 'error'); }); @@ -639,7 +636,7 @@ formRef.value.validate() .then(() => { if (tipTheme.value === 'error') { - return Promise.reject(t('以下Client_冷_热节点任意一台即可')); + return Promise.reject(t('请保证冷热节点至少存在一台')); } baseState.isSubmitting = true; @@ -662,7 +659,8 @@ if (formData.details.ip_source === 'resource_pool') { delete details.nodes; - return { + + const result: Record = { ...details, resource_spec: { master: { @@ -670,23 +668,34 @@ ...specMasterRef.value.getData(), count: Number(details.resource_spec.master.count), }, - client: { - ...details.resource_spec.client, - ...specClientRef.value.getData(), - count: Number(details.resource_spec.client.count), - }, - hot: { - ...details.resource_spec.hot, - ...specHotRef.value.getData(), - count: Number(details.resource_spec.hot.count), - }, - cold: { - ...details.resource_spec.cold, - ...specColdRef.value.getData(), - count: Number(details.resource_spec.cold.count), - }, }, }; + + const clientCount = Number(details.resource_spec.client.count); + const hotCount = Number(details.resource_spec.hot.count); + const coldCount = Number(details.resource_spec.cold.count); + if (clientCount > 0) { + result.resource_spec.client = { + ...details.resource_spec.client, + ...specClientRef.value.getData(), + count: clientCount, + }; + } + if (hotCount > 0) { + result.resource_spec.hot = { + ...details.resource_spec.hot, + ...specHotRef.value.getData(), + count: hotCount, + }; + } + if (coldCount > 0) { + result.resource_spec.cold = { + ...details.resource_spec.cold, + ...specColdRef.value.getData(), + count: coldCount, + }; + } + return result; } delete details.resource_spec; diff --git a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue index 5b5d0d5ede..e1355cfb8b 100644 --- a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue @@ -363,7 +363,7 @@ cluster_alias: '', city_code: '', db_version: '', - ip_source: 'manual_input', + ip_source: 'resource_pool', nodes: { namenode: [] as Array, zookeeper: [] as Array, diff --git a/dbm-ui/frontend/src/views/influxdb-manage/apply/common/base.ts b/dbm-ui/frontend/src/views/influxdb-manage/apply/common/base.ts index 4e432fb931..eefc8311b2 100644 --- a/dbm-ui/frontend/src/views/influxdb-manage/apply/common/base.ts +++ b/dbm-ui/frontend/src/views/influxdb-manage/apply/common/base.ts @@ -23,7 +23,7 @@ export const getInitFormdata = () => ({ remark: '', details: { bk_cloud_id: '', - ip_source: 'manual_input', + ip_source: 'resource_pool', db_app_abbr: '', city_code: '', db_version: '', diff --git a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue index 0b69675efd..66031d8a1c 100644 --- a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue @@ -332,7 +332,7 @@ cluster_alias: '', city_code: '', db_version: '', - ip_source: 'manual_input', + ip_source: 'resource_pool', nodes: { zookeeper: [] as Array, broker: [] as Array, diff --git a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue index 0ac193e13f..12a38059d2 100644 --- a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue +++ b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue @@ -283,11 +283,11 @@ @@ -421,6 +421,7 @@ const specProxyRef = ref(); const specBackendRef = ref(); + const specSingleRef = ref(); const backendRef = ref(); const proxyRef = ref(); const moduleRef = ref(); @@ -674,9 +675,9 @@ return { ...details, resource_spec: { - backend: { - ...details.resource_spec.broker, - ...specBackendRef.value.getData(), + single: { + ...details.resource_spec.single, + ...specSingleRef.value.getData(), count: hostNums.value, }, }, @@ -692,7 +693,7 @@ count: hostNums.value, }, backend: { - ...details.resource_spec.broker, + ...details.resource_spec.backend, ...specBackendRef.value.getData(), count: hostNums.value, }, diff --git a/dbm-ui/frontend/src/views/mysql/apply/hooks/useMysqlData.ts b/dbm-ui/frontend/src/views/mysql/apply/hooks/useMysqlData.ts index b509958566..097cfe59e3 100644 --- a/dbm-ui/frontend/src/views/mysql/apply/hooks/useMysqlData.ts +++ b/dbm-ui/frontend/src/views/mysql/apply/hooks/useMysqlData.ts @@ -52,12 +52,16 @@ const getFormData = (type: string) => ({ start_proxy_port: 10000, domains: [{ key: '' }], disaster_tolerance_level: 'same_city_cross_zone', - ip_source: 'manual_input', + ip_source: 'resource_pool', nodes: { backend: [] as HostDetails[], proxy: [] as HostDetails[], }, resource_spec: { + single: { + count: 0, + spec_id: '', + }, backend: { count: 0, spec_id: '', diff --git a/dbm-ui/frontend/src/views/pulsar-manage/apply/common/base.ts b/dbm-ui/frontend/src/views/pulsar-manage/apply/common/base.ts index 9be524afde..c41e2e6832 100644 --- a/dbm-ui/frontend/src/views/pulsar-manage/apply/common/base.ts +++ b/dbm-ui/frontend/src/views/pulsar-manage/apply/common/base.ts @@ -24,7 +24,7 @@ export const getInitFormdata = () => ({ details: { username: '', password: '', - ip_source: 'manual_input', + ip_source: 'resource_pool', db_version: '', bk_cloud_id: '', retention_hours: 1, diff --git a/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue b/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue index 87af0eec79..e2126508bf 100644 --- a/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue +++ b/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue @@ -87,146 +87,187 @@ {{ item.text }} - - +
- - - -
-

- {{ $t('单实例容量x分片数_根据选择的主机自动计算所有的组合') }} -

-
+ class="mb-24"> + + + + + + + +
+ + + {{ $t('从n起', { n: state.formdata.details.proxy_port }) }} + +
+
+ + + + + + + + + + + + + + +
+ + + +
+

+ {{ $t('单实例容量x分片数_根据选择的主机自动计算所有的组合') }} +

+
+
+
+ +
+ + + + + + {{ $t('至少n台', {n: 2}) }} + +
+
+ + + +
+ { + const types = { + [ClusterTypes.TWEMPROXY_REDIS_INSTANCE]: { + cluster_type: ClusterTypes.TWEMPROXY_REDIS_INSTANCE, + machine_type: 'twemproxy', + backend_machine_type: 'tendiscache', + }, + [ClusterTypes.TWEMPROXY_TENDIS_SSD_INSTANCE]: { + cluster_type: ClusterTypes.TWEMPROXY_TENDIS_SSD_INSTANCE, + machine_type: 'twemproxy', + backend_machine_type: 'tendisssd', + }, + [ClusterTypes.PREDIXY_TENDISPLUS_CLUSTER]: { + cluster_type: ClusterTypes.PREDIXY_TENDISPLUS_CLUSTER, + machine_type: 'predixy', + backend_machine_type: 'tendisplus', + }, + }; + return types[state.formdata.details.cluster_type as keyof typeof types]; + }); /** 初始化数据 */ function initData() { @@ -370,12 +434,22 @@ city_code: '', db_version: '', cap_key: '', - ip_source: redisIpSources.manual_input.id, + ip_source: redisIpSources.resource_pool.id, nodes: { proxy: [] as HostDetails[], master: [] as HostDetails[], slave: [] as HostDetails[], }, + resource_spec: { + proxy: { + spec_id: '', + count: 2, + }, + }, + resource_plan: { + resource_plan_name: '', + resource_plan_id: '', + }, }, }; } @@ -426,7 +500,6 @@ master: formatNodes(master), slave: formatNodes(slave), }, - cluster_type: state.formdata.details.cluster_type, }) .then((res) => { state.capSpecs = res; @@ -444,8 +517,9 @@ function handleChangeClusterType(value: string) { state.formdata.details.db_version = ''; + state.formdata.details.resource_spec.proxy.spec_id = ''; fetchVersions(value); - fetchCapSpecs(''); + isManualInput.value && fetchCapSpecs(''); } /** @@ -590,16 +664,41 @@ await formRef.value?.validate(); baseState.isSubmitting = true; - const params = { - ...state.formdata, - details: { - ...state.formdata.details, + + const getDetails = () => { + const details: Record = { ...markRaw(state.formdata.details) }; + + if (state.formdata.details.ip_source === 'resource_pool') { + delete details.nodes; + + return { + ...details, + resource_spec: { + proxy: { + ...details.resource_spec.proxy, + ...specProxyRef.value.getData(), + count: Number(details.resource_spec.proxy.count), + spec_cluster_type: typeInfos.value.cluster_type, + spec_machine_type: typeInfos.value.machine_type, + }, + }, + }; + } + + delete details.resource_spec; + delete details.resource_plan; + return { + ...details, nodes: { proxy: formatNodes(state.formdata.details.nodes.proxy), master: formatNodes(state.formdata.details.nodes.master), slave: formatNodes(state.formdata.details.nodes.slave), }, - }, + }; + }; + const params = { + ...state.formdata, + details: getDetails(), }; // 若业务没有英文名称则先创建业务英文名称再创建单据,反正直接创建单据 bizState.hasEnglishName ? handleCreateTicket(params) : handleCreateAppAbbr(params); @@ -628,6 +727,35 @@ font-size: @font-size-mini; background-color: #f5f7fa; } + + .input-desc { + padding-left: 12px; + font-size: 12px; + line-height: 20px; + color: #63656e; + } + + .resource-pool-item { + width: 655px; + padding: 24px 0; + background-color: #F5F7FA; + border-radius: 2px; + + .bk-form-item { + .bk-form-label { + width: 120px !important; + } + + .bk-form-content { + margin-left: 120px !important; + + .bk-select, + .bk-input { + width: 314px; + } + } + } + } } .apply-instance__content { diff --git a/dbm-ui/frontend/src/views/redis/apply/common/const.ts b/dbm-ui/frontend/src/views/redis/apply/common/const.ts index 9a2a5e88d6..41471a32bb 100644 --- a/dbm-ui/frontend/src/views/redis/apply/common/const.ts +++ b/dbm-ui/frontend/src/views/redis/apply/common/const.ts @@ -24,12 +24,10 @@ export const redisIpSources = { resource_pool: { id: 'resource_pool', text: t('自动从资源池匹配'), - disabled: true, }, manual_input: { id: 'manual_input', text: t('手动录入IP'), - disabled: false, }, }; export type RedisIpSources = keyof typeof redisIpSources; diff --git a/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue b/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue index e41e534154..bba22fcc8f 100644 --- a/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue +++ b/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue @@ -121,7 +121,11 @@ const initFormdata = () => { if (props.data) { - return { ...props.data }; + const baseData = { ...props.data }; + if (baseData.device_class.length === 0) { + baseData.device_class = ['']; + } + return baseData; } return { diff --git a/dbm-ui/frontend/src/views/resource-spec/components/SpecList.vue b/dbm-ui/frontend/src/views/resource-spec/components/SpecList.vue index 6bc07c550d..d8828a44a0 100644 --- a/dbm-ui/frontend/src/views/resource-spec/components/SpecList.vue +++ b/dbm-ui/frontend/src/views/resource-spec/components/SpecList.vue @@ -172,7 +172,11 @@ {t('磁盘')}:
{ - data.storage_spec.map(item => {`(${t('挂载点')}: ${item.mount_point}, ${t('最小容量')}: ${item.size} G, ${item.type})`}) + data.storage_spec.map(item => ( +

+ {`(${t('挂载点')}: ${item.mount_point}, ${t('最小容量')}: ${item.size} G, ${item.type})`} +

+ )) }
@@ -333,13 +337,10 @@ diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue index 6ea29416c0..db5dadba75 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue @@ -78,6 +78,25 @@ {{ $t(StatusTypes[item.status as StatusTypesStrings]) }} +
+ + {{ item.related_object.title }}: + + + + {{ $t('业务') }}: + {{ item.bk_biz_name }} + +
{{ $t('申请人') }}: {{ item.creator }} {{ getDate(item.create_at) }} @@ -110,6 +129,7 @@ } from '@stores'; import EmptyStatus from '@components/empty-status/EmptyStatus.vue'; + import RenderRow from '@components/render-row/index.vue'; import { getSearchSelectorParams } from '@utils'; @@ -469,6 +489,25 @@ .flex-center(); justify-content: space-between; + + .info-item { + display: flex; + max-width: 50%; + overflow: hidden; + align-items: center; + + &.is-whole { + max-width: 100%; + } + + .info-item-label { + flex-shrink: 0; + } + + .info-item-value { + flex-grow: 1; + } + } } } From e9eb0f63325e3196c843b6c5dc8589a7c6c2e64a Mon Sep 17 00:00:00 2001 From: fanfanyangyang Date: Mon, 5 Jun 2023 15:30:28 +0800 Subject: [PATCH 037/476] feat(backend): riak_apply_cluster_flow #51 --- .../riak/db-tools/dbactuator/.gitignore | 27 +++ .../riak/db-tools/dbactuator/Makefile | 35 ++++ .../riak/db-tools/dbactuator/build.sh | 9 + .../riak/db-tools/dbactuator/build_doc.sh | 10 + .../dbactuator/pkg/components/base.go | 21 ++ dbm-ui/backend/configuration/constants.py | 1 + .../backend/db_meta/api/cluster/__init__.py | 1 + .../db_meta/api/cluster/riak/__init__.py | 11 + .../db_meta/api/cluster/riak/create.py | 84 ++++++++ dbm-ui/backend/db_meta/enums/cluster_type.py | 2 + dbm-ui/backend/db_meta/enums/instance_role.py | 2 + dbm-ui/backend/db_meta/enums/machine_type.py | 2 + dbm-ui/backend/db_meta/enums/type_maps.py | 7 + dbm-ui/backend/flow/consts.py | 27 +++ .../bamboo/scene/common/get_file_list.py | 16 ++ .../flow/engine/bamboo/scene/riak/__init__.py | 10 + .../scene/riak/riak_cluster_apply_flow.py | 195 ++++++++++++++++++ dbm-ui/backend/flow/engine/controller/riak.py | 25 +++ .../components/collections/riak/__init__.py | 10 + .../collections/riak/exec_actuator_script.py | 140 +++++++++++++ .../collections/riak/get_riak_payload.py | 54 +++++ .../collections/riak/get_riak_resource.py | 63 ++++++ .../collections/riak/riak_db_meta.py | 46 +++++ .../collections/riak/trans_files.py | 88 ++++++++ dbm-ui/backend/flow/urls.py | 3 + .../flow/utils/riak/riak_act_dataclass.py | 76 +++++++ .../flow/utils/riak/riak_act_payload.py | 94 +++++++++ .../flow/utils/riak/riak_context_dataclass.py | 49 +++++ .../backend/flow/utils/riak/riak_db_meta.py | 71 +++++++ dbm-ui/backend/flow/views/riak_apply.py | 24 +++ 30 files changed, 1203 insertions(+) create mode 100644 dbm-services/riak/db-tools/dbactuator/.gitignore create mode 100644 dbm-services/riak/db-tools/dbactuator/Makefile create mode 100755 dbm-services/riak/db-tools/dbactuator/build.sh create mode 100755 dbm-services/riak/db-tools/dbactuator/build_doc.sh create mode 100644 dbm-services/riak/db-tools/dbactuator/pkg/components/base.go create mode 100644 dbm-ui/backend/db_meta/api/cluster/riak/__init__.py create mode 100644 dbm-ui/backend/db_meta/api/cluster/riak/create.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/riak/__init__.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/riak/riak_cluster_apply_flow.py create mode 100644 dbm-ui/backend/flow/engine/controller/riak.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/__init__.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/exec_actuator_script.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_payload.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_resource.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/riak_db_meta.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/riak/trans_files.py create mode 100644 dbm-ui/backend/flow/utils/riak/riak_act_dataclass.py create mode 100644 dbm-ui/backend/flow/utils/riak/riak_act_payload.py create mode 100644 dbm-ui/backend/flow/utils/riak/riak_context_dataclass.py create mode 100644 dbm-ui/backend/flow/utils/riak/riak_db_meta.py create mode 100644 dbm-ui/backend/flow/views/riak_apply.py diff --git a/dbm-services/riak/db-tools/dbactuator/.gitignore b/dbm-services/riak/db-tools/dbactuator/.gitignore new file mode 100644 index 0000000000..1a34a6ea74 --- /dev/null +++ b/dbm-services/riak/db-tools/dbactuator/.gitignore @@ -0,0 +1,27 @@ +!.gitkeep +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +# Test binary, built with `go test -c` +*.test +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +# Dependency directories (remove the comment below to include it) +vendor/ +# Go workspace file +go.work +configs/* +log/ +build/ +conf/ +*exe +*.log +.idea/ +.DS_Store +sync_test.sh +.vscode/ +scripts/upload_media.sh +scripts/upload.sh \ No newline at end of file diff --git a/dbm-services/riak/db-tools/dbactuator/Makefile b/dbm-services/riak/db-tools/dbactuator/Makefile new file mode 100644 index 0000000000..dcca994de4 --- /dev/null +++ b/dbm-services/riak/db-tools/dbactuator/Makefile @@ -0,0 +1,35 @@ +SHELL := /bin/bash +BASE_DIR = $(shell pwd) +VERSION = 0.0.1 +APPNAME = dbactuator +GOOS ?= linux +BUILD_FLAG = " -X main.version=${VERSION} -X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git rev-parse HEAD` " +BUILD_EXTERNAL_FLAG = " -X main.external=ON -X main.version=${VERSION} -X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git rev-parse HEAD` " +BUILD_MINI_FLAG = " -s -w -X main.version=${VERSION} -X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git rev-parse HEAD` " + +.PHONY: all build clean + +build: + cd ${BASE_DIR}/cmd && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=amd64 go build -gcflags=-trimpath=${PWD} -asmflags=-trimpath=${PWD} -ldflags ${BUILD_FLAG} -o $(BASE_DIR)/build/$(APPNAME) -v . + +external : + cd ${BASE_DIR}/cmd && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=amd64 go build -gcflags=-trimpath=${PWD} -asmflags=-trimpath=${PWD} -ldflags ${BUILD_EXTERNAL_FLAG} -o $(BASE_DIR)/build/$(APPNAME) -v . + +mini: + cd ${BASE_DIR}/cmd && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=amd64 go build -gcflags=-trimpath=${PWD} -asmflags=-trimpath=${PWD} -ldflags ${BUILD_MINI_FLAG} -o $(BASE_DIR)/build/$(APPNAME) -v . + # need install upx + upx $(BASE_DIR)/build/$(APPNAME) + +clean: + cd ${BASE_DIR}/build && rm -rf ${APPNAME} + +rotatebinlog: + cd ${BASE_DIR}/cmd/rotatebinlog && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=amd64 go build -ldflags ${BUILD_FLAG} -o $(BASE_DIR)/build/rotatebinlog -v . + +gotool: + @-gofmt -w . + +help: + @echo "make - compile go source" + @echo "make gotool - run gofmt" + @echo "make clean - do some clean job" \ No newline at end of file diff --git a/dbm-services/riak/db-tools/dbactuator/build.sh b/dbm-services/riak/db-tools/dbactuator/build.sh new file mode 100755 index 0000000000..499fb68a77 --- /dev/null +++ b/dbm-services/riak/db-tools/dbactuator/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +workDir=`pwd` + +# unit test +cd $workDir +chmod +x *.sh +./build_doc.sh +make \ No newline at end of file diff --git a/dbm-services/riak/db-tools/dbactuator/build_doc.sh b/dbm-services/riak/db-tools/dbactuator/build_doc.sh new file mode 100755 index 0000000000..78bea6292e --- /dev/null +++ b/dbm-services/riak/db-tools/dbactuator/build_doc.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# https://github.com/swaggo/swag +# --parseDependency to avoid: ParseComment ... cannot find type definition: json.RawMessage +swag init -g cmd/cmd.go --o docs/ --ot json,yaml --parseDependency +if [ $? -gt 0 ];then + echo "generate swagger api docs failed" + exit 1 +fi +tree docs/ \ No newline at end of file diff --git a/dbm-services/riak/db-tools/dbactuator/pkg/components/base.go b/dbm-services/riak/db-tools/dbactuator/pkg/components/base.go new file mode 100644 index 0000000000..c966746468 --- /dev/null +++ b/dbm-services/riak/db-tools/dbactuator/pkg/components/base.go @@ -0,0 +1,21 @@ +package components + +// BaseInputParam TODO +type BaseInputParam struct { + GeneralParam *GeneralParam `json:"general"` + ExtendParam interface{} `json:"extend"` +} + +// GeneralParam TODO +type GeneralParam struct { + RuntimeAccountParam RuntimeAccountParam `json:"runtime_account"` + RuntimeExtend RuntimeExtend `json:"runtime_extend"` +} + +// RuntimeExtend TODO +type RuntimeExtend struct { +} + +// RuntimeAccountParam TODO +type RuntimeAccountParam struct { +} diff --git a/dbm-ui/backend/configuration/constants.py b/dbm-ui/backend/configuration/constants.py index 8ebab0f044..4851c767bb 100644 --- a/dbm-ui/backend/configuration/constants.py +++ b/dbm-ui/backend/configuration/constants.py @@ -26,6 +26,7 @@ class DBType(str, StructuredEnum): Es = EnumField("es", _("ElasticSearch")) Pulsar = EnumField("pulsar", _("Pulsar")) InfluxDB = EnumField("influxdb", _("InfluxDB")) + Riak = EnumField("riak", _("Riak")) # 不属于DB类型,仅用于云区域组件的单据部署的分组 Cloud = EnumField("cloud", _("Cloud")) diff --git a/dbm-ui/backend/db_meta/api/cluster/__init__.py b/dbm-ui/backend/db_meta/api/cluster/__init__.py index 66d5e3a2e7..f7f5487559 100644 --- a/dbm-ui/backend/db_meta/api/cluster/__init__.py +++ b/dbm-ui/backend/db_meta/api/cluster/__init__.py @@ -24,5 +24,6 @@ tendispluscluster, tendissingle, tendisssd, + riak, ) from .apis import domain_exists, query_instances diff --git a/dbm-ui/backend/db_meta/api/cluster/riak/__init__.py b/dbm-ui/backend/db_meta/api/cluster/riak/__init__.py new file mode 100644 index 0000000000..4385787926 --- /dev/null +++ b/dbm-ui/backend/db_meta/api/cluster/riak/__init__.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from .create import create diff --git a/dbm-ui/backend/db_meta/api/cluster/riak/create.py b/dbm-ui/backend/db_meta/api/cluster/riak/create.py new file mode 100644 index 0000000000..1e43e14d2b --- /dev/null +++ b/dbm-ui/backend/db_meta/api/cluster/riak/create.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import logging +from typing import Optional, List + +from django.db import transaction +from django.utils.translation import ugettext as _ + +from backend.db_meta import request_validator +from backend.db_meta.api import common +from backend.db_meta.enums import ClusterEntryType, ClusterPhase, ClusterStatus, ClusterType +from backend.db_meta.exceptions import DBMetaException +from backend.db_meta.models import Cluster, ClusterEntry, StorageInstance + +logger = logging.getLogger("root") + + +@transaction.atomic +def create_precheck(bk_biz_id: int, name: str, immute_domain: str): + precheck_errors = [] + + if Cluster.objects.filter(bk_biz_id=bk_biz_id, name=name, cluster_type=ClusterType.Riak.value).exists(): + precheck_errors.append(_("集群名 {} 在 bk_biz_id:{} 已存在").format(name, bk_biz_id)) + + if ClusterEntry.objects.filter(cluster_entry_type=ClusterEntryType.DNS.value, entry=immute_domain).exists(): + precheck_errors.append(_("域名 {} 已存在").format(immute_domain)) + + if precheck_errors: + raise DBMetaException(message=", ".join(precheck_errors)) + + +@transaction.atomic +def create( + bk_cloud_id: int, + bk_biz_id: int, + name: str, + alias: str, + immute_domain: str, + major_version: str, + db_module_id: int, + storages: Optional[List], + creator: str = "", +): + bk_biz_id = request_validator.validated_integer(bk_biz_id) + immute_domain = request_validator.validated_domain(immute_domain) + db_module_id = request_validator.validated_integer(db_module_id) + cluster = Cluster.objects.create( + bk_cloud_id=bk_cloud_id, + bk_biz_id=bk_biz_id, + name=name, + alias=alias, + cluster_type=ClusterType.Riak.value, + immute_domain=immute_domain, + creator=creator, + phase=ClusterPhase.ONLINE.value, + status=ClusterStatus.NORMAL.value, + major_version=major_version, + ) + + storages = request_validator.validated_storage_list(storages, allow_empty=False, allow_null=False) + storage_objs = common.filter_out_instance_obj(storages, StorageInstance.objects.all()) + cluster.storageinstance_set.add(*storage_objs) + + cluster_entry = ClusterEntry.objects.create( + cluster=cluster, cluster_entry_type=ClusterEntryType.DNS, entry=immute_domain, creator=creator + ) + cluster_entry.storageinstance_set.add(*storage_objs) + + for ins in storage_objs: + m = ins.machine + ins.db_module_id = db_module_id + m.db_module_id = db_module_id + ins.save(update_fields=["db_module_id"]) + m.save(update_fields=["db_module_id"]) + + return cluster.id diff --git a/dbm-ui/backend/db_meta/enums/cluster_type.py b/dbm-ui/backend/db_meta/enums/cluster_type.py index 72bc88e956..3de40c0b03 100644 --- a/dbm-ui/backend/db_meta/enums/cluster_type.py +++ b/dbm-ui/backend/db_meta/enums/cluster_type.py @@ -37,3 +37,5 @@ class ClusterType(str, StructuredEnum): MongoReplicaSet = EnumField("MongoReplicaSet", _("Mongo副本集")) MongoShardedCluster = EnumField("MongoShardedCluster", _("Mongo分片集群")) + + Riak = EnumField("riak", _("Riak集群")) diff --git a/dbm-ui/backend/db_meta/enums/instance_role.py b/dbm-ui/backend/db_meta/enums/instance_role.py index 98eac5a4d7..4d8a51583e 100644 --- a/dbm-ui/backend/db_meta/enums/instance_role.py +++ b/dbm-ui/backend/db_meta/enums/instance_role.py @@ -62,6 +62,8 @@ class InstanceRole(str, StructuredEnum): MONGO_M10 = EnumField("mongo_m10", _("mongo_m10")) MONGO_BACKUP = EnumField("mongo_backup", _("mongo_backup")) + RIAK_NODE = EnumField("riak_node", _("riak_node")) + class TenDBClusterSpiderRole(str, StructuredEnum): # 主集群的接入层 diff --git a/dbm-ui/backend/db_meta/enums/machine_type.py b/dbm-ui/backend/db_meta/enums/machine_type.py index d3de00a915..1bf37603a5 100644 --- a/dbm-ui/backend/db_meta/enums/machine_type.py +++ b/dbm-ui/backend/db_meta/enums/machine_type.py @@ -44,3 +44,5 @@ class MachineType(str, StructuredEnum): PULSAR_ZOOKEEPER = EnumField("pulsar_zookeeper", _("pulsar_zookeeper")) PULSAR_BOOKKEEPER = EnumField("pulsar_bookkeeper", _("pulsar_bookkeeper")) PULSAR_BROKER = EnumField("pulsar_broker", _("pulsar_broker")) + + RIAK = EnumField("riak", _("riak")) diff --git a/dbm-ui/backend/db_meta/enums/type_maps.py b/dbm-ui/backend/db_meta/enums/type_maps.py index 6cd390f536..543c784672 100644 --- a/dbm-ui/backend/db_meta/enums/type_maps.py +++ b/dbm-ui/backend/db_meta/enums/type_maps.py @@ -36,6 +36,7 @@ MachineType.PULSAR_BOOKKEEPER: AccessLayer.STORAGE, MachineType.PULSAR_ZOOKEEPER: AccessLayer.STORAGE, MachineType.INFLUXDB: AccessLayer.STORAGE, + MachineType.RIAK: AccessLayer.STORAGE, } ClusterTypeMachineTypeDefine = { @@ -59,6 +60,7 @@ ClusterType.MongoShardedCluster: [MachineType.MONGODB, MachineType.MONGOS, MachineType.MONOG_CONFIG], ClusterType.Pulsar: [MachineType.PULSAR_BROKER, MachineType.PULSAR_BOOKKEEPER, MachineType.PULSAR_ZOOKEEPER], ClusterType.Influxdb: [MachineType.INFLUXDB], + ClusterType.Riak: [MachineType.RIAK], } ClusterMachineAccessTypeDefine = { @@ -113,6 +115,9 @@ AccessLayer.PROXY: MachineType.SINGLE, AccessLayer.STORAGE: MachineType.REMOTE, }, + ClusterType.Riak: { + AccessLayer.STORAGE: MachineType.RIAK, + }, } MachineTypeInstanceRoleMap = { @@ -182,6 +187,7 @@ MachineType.PULSAR_BOOKKEEPER: [InstanceRole.PULSAR_BOOKKEEPER], MachineType.PULSAR_BROKER: [InstanceRole.PULSAR_BROKER], MachineType.INFLUXDB: [InstanceRole.INFLUXDB], + MachineType.RIAK: [InstanceRole.RIAK_NODE], # MachineType.SPIDER: [InstanceRole.SPIDER_MASTER,InstanceRole.SPIDER_SLAVE] } @@ -220,6 +226,7 @@ InstanceRole.PULSAR_BOOKKEEPER: InstanceInnerRole.ORPHAN, InstanceRole.PULSAR_ZOOKEEPER: InstanceInnerRole.ORPHAN, InstanceRole.INFLUXDB: InstanceInnerRole.ORPHAN, + InstanceRole.RIAK_NODE: InstanceInnerRole.ORPHAN, } diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index ad035de24c..27fef9d63c 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -201,6 +201,7 @@ class MediumEnum(str, StructuredEnum): CloudDRSTymsqlParse = EnumField("cloud-drs-tmysqlparse", _("cloud-drs-tmysqlparse服务")) Spider = EnumField("spider", _("spider节点名称")) tdbCtl = EnumField("tdbctl", _("spider中控节点名称")) + Riak = EnumField("riak", _("riak")) class CloudServiceName(str, StructuredEnum): @@ -263,6 +264,7 @@ class DBActuatorTypeEnum(str, StructuredEnum): Download = EnumField("download", _("download")) Spider = EnumField("spider", _("spider")) SpiderCtl = EnumField("spiderctl", _("spiderctl")) + Riak = EnumField("riak", _("riak")) class DBActuatorActionEnum(str, StructuredEnum): @@ -412,6 +414,31 @@ class PulsarActuatorActionEnum(str, StructuredEnum): ModifyHosts = EnumField("modify_hosts", _("modify_hosts")) +class RiakActuatorActionEnum(str, StructuredEnum): + SysinitRiak = EnumField("sysinit-riak", _("sysinit-riak")) + Deploy = EnumField("deploy", _("deploy")) + JoinCluster = EnumField("join-cluster", _("join-cluster")) + CommitClusterChange = EnumField("commit-cluster-change", _("commit-cluster-change")) + InitBucketType = EnumField("init-bucket-type", _("init-bucket-type")) + RemoveNode = EnumField("remove-node", _("remove-node")) + InstallMonitor = EnumField("install-monitor", _("install-monitor")) + DeployRiakCrond = EnumField("deploy-riak-crond", _("deploy-riak-crond")) + ClearCrontab = EnumField("clear-crontab", _("clear-crontab")) + UnInstall = EnumField("uninstall", _("uninstall")) + + +class RiakModuleId(int, StructuredEnum): + """ + Riak模块id + """ + + mhs = EnumField(0, _("聊天历史记录")) + legs = EnumField(1, _("用户战绩数据")) + pp = EnumField(2, _("玩家按键快捷键信息")) + test = EnumField(3, _("test")) + mixed = EnumField(4, _("mixed")) + + class JobStatusEnum(int, StructuredEnum): NOT_RUNNING = EnumField(1, _("NOT_RUNNING")) RUNNING = EnumField(2, _("RUNNING")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py b/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py index d8b263fb23..4c581d6302 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py @@ -111,6 +111,22 @@ def mysql_proxy_install_package(self) -> list: f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{mysql_monitor_pkg.path}", ] + def riak_install_package(self) -> list: + """ + riak安装需要的安装包列表 + """ + riak_pkg = Package.get_latest_package(version="2.2.1", pkg_type=MediumEnum.Riak, db_type=DBType.Riak) + # riak_crond_pkg = Package.get_latest_package(version=MediumEnum.Latest, + # pkg_type=MediumEnum.RiakCrond, db_type=DBType.Riak) + # riak_monitor_pkg = Package.get_latest_package(version=MediumEnum.Latest, + # pkg_type=MediumEnum.RiakMonitor, db_type=DBType.Riak) + return [ + f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{self.actuator_pkg.path}", + f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{riak_pkg.path}", + # f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{riak_crond_pkg.path}", + # f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{riak_monitor_pkg.path}", + ] + def redis_cluster_apply_proxy(self, cluster_type) -> list: """ 部署redis,所有节点需要的proxy pkg包 diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/riak/__init__.py b/dbm-ui/backend/flow/engine/bamboo/scene/riak/__init__.py new file mode 100644 index 0000000000..aa5085c628 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/riak/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/riak/riak_cluster_apply_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/riak/riak_cluster_apply_flow.py new file mode 100644 index 0000000000..b1a7f7d7f3 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/riak/riak_cluster_apply_flow.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging.config +from unittest import case + +from dataclasses import asdict +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.configuration.constants import DBType +from backend.flow.consts import DBA_ROOT_USER +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList +from backend.flow.plugins.components.collections.riak.exec_actuator_script import ExecuteRiakActuatorScriptComponent +from backend.flow.plugins.components.collections.riak.get_riak_resource import GetRiakResourceComponent +from backend.flow.plugins.components.collections.riak.riak_db_meta import RiakDBMetaComponent +from backend.flow.utils.riak.riak_act_payload import RiakActPayload +from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent +from backend.flow.utils.riak.riak_act_dataclass import DownloadMediaKwargs, ExecActuatorKwargs, DBMetaFuncKwargs +from backend.flow.plugins.components.collections.mysql.trans_flies import TransFileComponent +from backend.flow.utils.riak.riak_context_dataclass import ApplyManualContext, RiakActKwargs +from backend.flow.utils.riak.riak_db_meta import RiakDBMeta + +logger = logging.getLogger("flow") + + +class RiakClusterApplyFlow(object): + """ + 构建Riak集群申请流程的抽象类 + { + "uid": "2022111212001000", + "root_id": 123, + "created_by": "admin", + "bk_biz_id": 0, + "ticket_type": "RIAK_APPLY", + "timing": "2022-11-21 12:04:10", + "bk_app_abbr": "testtest", + "ip_source": "manual_input", + "zone": "hh", + "db_module_id": 0, + "major_version": "0-0", + "cluster_alias": "测试集群", + "city_code": "深圳", + "bk_cloud_id": 0, + "nodes": [ + { + "ip": "127.0.0.1", + "bk_host_id": 0 + } + ] + } + """ + + def __init__(self, root_id: str, data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param data : 单据传递过来的参数列表,是dict格式 + """ + self.root_id = root_id + self.data = data + + def deploy_riak_cluster_flow(self): + """ + 部署Riak集群 + """ + riak_pipeline = Builder(root_id=self.root_id, data=self.data) + sub_pipeline = SubBuilder(root_id=self.root_id, data=self.data) + + # 获取机器资源 done + sub_pipeline.add_act(act_name=_("获取机器信息"), act_component_code=GetRiakResourceComponent.code, kwargs={}) + ips = [ip for ip in self.data["nodes"]] + sub_pipeline.add_act( + act_name=_("下发actuator以及riak介质"), + act_component_code=TransFileComponent.code, + kwargs=asdict( + DownloadMediaKwargs( + bk_cloud_id=self.data["bk_cloud_id"], + exec_ip=ips, + file_list=GetFileList(db_type=DBType.Riak).riak_install_package(), + ) + ), + ) + sub_pipeline.add_act( + act_name=_("actuator_riak系统配置初始化"), + act_component_code=ExecuteRiakActuatorScriptComponent.code, + kwargs=asdict( + RiakActKwargs( + exec_ip=ips, + bk_cloud_id=self.data["bk_cloud_id"], + run_as_system_user=DBA_ROOT_USER, + get_riak_payload_func=RiakActPayload.get_sysinit_payload.__name__, + ) + ), + ) + + cluster = self._get_riak_config() + sub_pipeline.add_act( + act_name=_("actuator_riak部署节点"), + act_component_code=ExecuteRiakActuatorScriptComponent.code, + kwargs=asdict( + RiakActKwargs( + exec_ip=ips, + bk_cloud_id=self.data["bk_cloud_id"], + run_as_system_user=DBA_ROOT_USER, + get_riak_payload_func=RiakActPayload.get_deploy_payload.__name__, + cluster=cluster, + ) + ), + ) + + sub_pipeline.add_act( + act_name=_("actuator_riak节点加入集群"), + act_component_code=ExecuteRiakActuatorScriptComponent.code, + kwargs=asdict( + RiakActKwargs( + exec_ip=ips[1:], + bk_cloud_id=self.data["bk_cloud_id"], + run_as_system_user=DBA_ROOT_USER, + get_riak_payload_func=RiakActPayload.get_join_cluster_payload.__name__, + cluster=cluster, + ) + ), + ) + + sub_pipeline.add_act( + act_name=_("actuator_集群变更生效"), + act_component_code=ExecuteRiakActuatorScriptComponent.code, + kwargs=asdict( + RiakActKwargs( + exec_ip=ips[0], + bk_cloud_id=self.data["bk_cloud_id"], + run_as_system_user=DBA_ROOT_USER, + get_riak_payload_func=RiakActPayload.get_commit_cluster_change_payload.__name__, + cluster=cluster, + ) + ), + ) + + sub_pipeline.add_act( + act_name=_("actuator_初始化bucket_type"), + act_component_code=ExecuteRiakActuatorScriptComponent.code, + kwargs=asdict( + RiakActKwargs( + exec_ip=ips[0], + bk_cloud_id=self.data["bk_cloud_id"], + run_as_system_user=DBA_ROOT_USER, + get_riak_payload_func=RiakActPayload.get_commit_cluster_change_payload.__name__, + cluster=cluster, + ) + ), + ) + sub_pipeline.add_act( + act_name=_("riak修改元数据"), + act_component_code=RiakDBMetaComponent.code, + kwargs=asdict( + DBMetaFuncKwargs( + db_meta_class_func=RiakDBMeta.riak_deploy_node.__name__, + cluster={"nodes": ips}, + is_update_trans_data=True, + ) + ), + ) + riak_pipeline.add_sub_pipeline(sub_pipeline.build_sub_process(sub_name=_("部署Riak集群"))) + riak_pipeline.run_pipeline(init_trans_data_class=ApplyManualContext()) + + def _get_riak_config(self): + bucket_types = [] + if self.data["db_module_id"] == 0: + distributed_cookie = "mhsriak" + elif self.data["db_module_id"] == 1: + distributed_cookie = "legsriak" + elif self.data["db_module_id"] == 2: + distributed_cookie = "ppriak" + bucket_types = ["player_preferences"] + elif self.data["db_module_id"] == 3: + distributed_cookie = "testriak" + bucket_types = ["player_preferences"] + elif self.data["db_module_id"] == 4: + distributed_cookie = "mixedtriak" + bucket_types = ["player_preferences"] + else: + logger.error("「 db_module_id = {} 」 not exists".format(self.data["db_module_id"])) + raise Exception("「 db_module_id = {} 」 not exists".format(self.data["db_module_id"])) + cluster = {"distributed_cookie": distributed_cookie, "bucket_types": bucket_types, "ring_size": 256} + return cluster diff --git a/dbm-ui/backend/flow/engine/controller/riak.py b/dbm-ui/backend/flow/engine/controller/riak.py new file mode 100644 index 0000000000..d42d3c38e9 --- /dev/null +++ b/dbm-ui/backend/flow/engine/controller/riak.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from backend.flow.engine.bamboo.scene.riak.riak_cluster_apply_flow import RiakClusterApplyFlow +from backend.flow.engine.controller.base import BaseController + + +class RiakController(BaseController): + """ + riak实例相关调用 + """ + + def riak_cluster_apply_scene(self): + """ + riak集群部署场景 + """ + flow = RiakClusterApplyFlow(root_id=self.root_id, data=self.ticket_data) + flow.deploy_riak_cluster_flow() diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/__init__.py b/dbm-ui/backend/flow/plugins/components/collections/riak/__init__.py new file mode 100644 index 0000000000..aa5085c628 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/exec_actuator_script.py b/dbm-ui/backend/flow/plugins/components/collections/riak/exec_actuator_script.py new file mode 100644 index 0000000000..7b62a8da8e --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/exec_actuator_script.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import base64 +import copy +import json +import logging +import re +from dataclasses import asdict, is_dataclass + +from django.utils.translation import ugettext as _ +from jinja2 import Environment +from pipeline.component_framework.component import Component + +from backend import env +from backend.components import JobApi +from backend.flow.consts import DBA_ROOT_USER +from backend.flow.models import FlowNode +from backend.flow.plugins.components.collections.common.base_service import BkJobService +from backend.flow.utils.riak.riak_act_payload import RiakActPayload +from backend.flow.utils.script_template import actuator_template, fast_execute_script_common_kwargs + +logger = logging.getLogger("json") +cpl = re.compile("(?P.+?)") # 非贪婪模式,只匹配第一次出现的自定义tag + + +class ExecuteRiakActuatorScriptService(BkJobService): + """ + 根据db-actuator组件,绑定fast_execute_script api接口访问。 + 目前只能兼容传入一个ip执行,如果传入多ip列表模块,会有可能影响payload的拼接情况 + 同时支持跨云管理,根据传入的 kwargs["bk_cloud_id"]来执行 + """ + + def __get_exec_ips(self, kwargs, trans_data) -> list: + """ + 获取需要执行的ip list + """ + # 拼接节点执行ip所需要的信息,ip信息统一用list处理拼接 + if kwargs.get("get_trans_data_ip_var"): + exec_ips = self.splice_exec_ips_list(pool_ips=getattr(trans_data, kwargs["get_trans_data_ip_var"])) + else: + exec_ips = self.splice_exec_ips_list(ticket_ips=kwargs["exec_ip"]) + + return exec_ips + + def _execute(self, data, parent_data) -> bool: + """ + 执行fast_execute_script脚本 + global_data 单据全局变量,格式字典 + trans_data 单据上下文 + kwargs 字典传入格式: + { + root_id: db-actuator任务必须参数,做录入日志平台的条件 + node_id: db-actuator任务必须参数,做录入日志平台的条件 + node_name: db-actuator任务必须参数,做录入日志平台的条件 + get_riak_payload_func : 表示获取执行 riak的db-actuator 参数方法名称,对应RiakActPayload类 + exec_ip: 表示执行的ip节点 + get_trans_data_ip_name: 表示从上下文获取到执行ip的变量名,对应单据的获取到上下文dataclass类 + cluster: 操作的集群名称 + + } + """ + global_data = data.get_one_of_inputs("global_data") + trans_data = data.get_one_of_inputs("trans_data") + kwargs = data.get_one_of_inputs("kwargs") + + root_id = kwargs["root_id"] + node_name = kwargs["node_name"] + node_id = kwargs["node_id"] + + exec_ips = self.__get_exec_ips(kwargs=kwargs, trans_data=trans_data) + if not exec_ips: + self.log_error(_("该节点获取到执行ip信息为空,请联系系统管理员{}").format(exec_ips)) + return False + + target_ip_info = [{"bk_cloud_id": kwargs["bk_cloud_id"], "ip": ip} for ip in exec_ips] + + # 获取riak actuator 组件所需要执行的参数 + riak_act_payload = RiakActPayload( + ticket_data=global_data, + cluster=kwargs.get("cluster", None), + ) + if is_dataclass(trans_data): + trans_data = asdict(trans_data) + + db_act_template = getattr(riak_act_payload, kwargs["get_riak_payload_func"])( + ip=exec_ips[0], trans_data=trans_data + ) + db_act_template["root_id"] = root_id + db_act_template["node_id"] = node_id + db_act_template["version_id"] = self._runtime_attrs.get("version") + db_act_template["uid"] = global_data["uid"] + + # payload参数转换base64格式 + db_act_template["payload"] = str( + base64.b64encode(json.dumps(db_act_template["payload"]).encode("utf-8")), "utf-8" + ) + FlowNode.objects.filter(root_id=kwargs["root_id"], node_id=node_id).update(hosts=exec_ips) + + # 脚本内容 + jinja_env = Environment() + template = jinja_env.from_string(actuator_template) + + body = { + "bk_biz_id": env.JOB_BLUEKING_BIZ_ID, + "task_name": f"DBM_{node_name}_{node_id}", + "script_content": str(base64.b64encode(template.render(db_act_template).encode("utf-8")), "utf-8"), + "script_language": 1, + "target_server": {"ip_list": target_ip_info}, + } + self.log_info("[{}] ready start task with body {}".format(node_name, body)) + + common_kwargs = copy.deepcopy(fast_execute_script_common_kwargs) + if kwargs.get("run_as_system_user"): + common_kwargs["account_alias"] = kwargs["run_as_system_user"] + else: + # 现在默认使用root账号来执行 + common_kwargs["account_alias"] = DBA_ROOT_USER + + resp = JobApi.fast_execute_script({**common_kwargs, **body}, raw=True) + self.log_info(f"{node_name} fast execute script response: {resp}") + self.log_info(f"job url:{env.BK_JOB_URL}/api_execute/{resp['data']['job_instance_id']}") + + # 传入调用结果,并单调监听任务状态 + data.outputs.ext_result = resp + data.outputs.exec_ips = exec_ips + return True + + +class ExecuteRiakActuatorScriptComponent(Component): + name = __name__ + code = "riak_actuator_execute" + bound_service = ExecuteRiakActuatorScriptService diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_payload.py b/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_payload.py new file mode 100644 index 0000000000..b338a67a65 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_payload.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import logging +from typing import List + +from pipeline.component_framework.component import Component +from pipeline.core.flow.activity import Service + +from backend.flow.plugins.components.collections.common.base_service import BaseService +from backend.flow.utils.riak import riak_context_dataclass +from backend.flow.utils.riak.riak_act_payload import RiakActPayload + +logger = logging.getLogger("flow") + + +class GetRiakActPayloadService(BaseService): + """ + 获取riak_act_payload类,存入到流程上下文中 + """ + + def _execute(self, data, parent_data) -> bool: + global_data = data.get_one_of_inputs("global_data") + trans_data = data.get_one_of_inputs("trans_data") + kwargs = data.get_one_of_inputs("kwargs") + + if trans_data is None or trans_data == "${trans_data}": + # 表示没有加载上下文内容, 则在此添加 + trans_data = getattr(riak_context_dataclass, kwargs["set_trans_data_dataclass"])() + + trans_data.riak_act_payload = RiakActPayload(ticket_data=global_data) + + self.log_info("successfully") + data.outputs["trans_data"] = trans_data + return True + + def inputs_format(self) -> List: + return [ + Service.InputItem(name="kwargs", key="kwargs", type="dict", required=True), + Service.InputItem(name="global_data", key="global_data", type="dict", required=True), + ] + + +class GetRiakActPayloadComponent(Component): + name = __name__ + code = "get_riak_act_payload" + bound_service = GetRiakActPayloadService diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_resource.py b/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_resource.py new file mode 100644 index 0000000000..79b4b9c51e --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/get_riak_resource.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import logging +from typing import List + +from django.utils.translation import ugettext as _ +from pipeline.component_framework.component import Component +from pipeline.core.flow.activity import Service + +from backend.flow.plugins.components.collections.common.base_service import BaseService + +logger = logging.getLogger("flow") + + +class GetRiakResourceService(BaseService): + """ + 根据Riak单据获取DB资源,在资源池获取节点资源,并根据单据类型拼接对应的参数 + """ + + def _execute(self, data, parent_data) -> bool: + global_data = data.get_one_of_inputs("global_data") + trans_data = data.get_one_of_inputs("trans_data") + kwargs = data.get_one_of_inputs("kwargs") + + if global_data["ip_source"] == "manual_input": + ips = [node["ip"] for node in global_data["nodes"]] + if global_data["ticket_type"] == "RIAK_APPLY" and len(ips) >= 3: + trans_data.ips = ips + trans_data.base_node = trans_data.ips[0] + trans_data.operate_nodes = trans_data.ips[1:] + elif global_data["ticket_type"] == "RIAK_ADD_NODE" and len(ips) >= 0: + trans_data.base_node = kwargs["base_node"] + trans_data.operate_nodes = ips + else: + self.log_error(_("获取机器资源失败,新建集群至少3台机器,添加节点至少1台机器")) + return False + elif self.data["ip_source"] == "resource_pool": + pass + + self.log_info(_("获取机器资源成功。 {}").format(trans_data)) + data.outputs["trans_data"] = trans_data + return True + + def inputs_format(self) -> List: + return [ + Service.InputItem(name="global_data", key="global_data", type="dict", required=True), + Service.InputItem(name="trans_data", key="trans_data", type="dict", required=True), + Service.InputItem(name="kwargs", key="kwargs", type="dict", required=True), + ] + + +class GetRiakResourceComponent(Component): + name = __name__ + code = "get_riak_resource" + bound_service = GetRiakResourceService diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/riak_db_meta.py b/dbm-ui/backend/flow/plugins/components/collections/riak/riak_db_meta.py new file mode 100644 index 0000000000..9ac6173e90 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/riak_db_meta.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging +from dataclasses import asdict + +from django.utils.translation import ugettext as _ +from pipeline.component_framework.component import Component + +from backend.flow.plugins.components.collections.common.base_service import BaseService +from backend.flow.utils.riak.riak_db_meta import RiakDBMeta + +logger = logging.getLogger("flow") + + +class RiakDBMetaService(BaseService): + """ + 根据Riak单据类型来更新cmdb + """ + + def _execute(self, data, parent_data) -> bool: + kwargs = data.get_one_of_inputs("kwargs") + global_data = data.get_one_of_inputs("global_data") + trans_data = data.get_one_of_inputs("trans_data") + + riak_meta = RiakDBMeta(ticket_data=global_data, cluster=trans_data) + + result = getattr(riak_meta, kwargs.get("db_meta_class_func"))() + + self.log_info("DBMata re successfully") + data.outputs.ext_result = result + return result + + +class RiakDBMetaComponent(Component): + name = __name__ + code = "riak_db_meta" + bound_service = RiakDBMetaService diff --git a/dbm-ui/backend/flow/plugins/components/collections/riak/trans_files.py b/dbm-ui/backend/flow/plugins/components/collections/riak/trans_files.py new file mode 100644 index 0000000000..26f769e342 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/riak/trans_files.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging +from typing import List + +from django.utils.translation import ugettext as _ +from pipeline.component_framework.component import Component +from pipeline.core.flow.activity import Service + +from backend import env +from backend.components import JobApi +from backend.core import consts +from backend.flow.consts import MediumFileTypeEnum +from backend.flow.models import FlowNode +from backend.flow.plugins.components.collections.common.base_service import BkJobService + +logger = logging.getLogger("flow") + + +class TransFileService(BkJobService): + """ + 下载介质文件包到目标机器 + """ + + def _execute(self, data, parent_data) -> bool: + """ + 执行传输文件的原子任务 + """ + kwargs = data.get_one_of_inputs("kwargs") + + root_id = kwargs["root_id"] + node_name = kwargs["node_name"] + node_id = kwargs["node_id"] + + exec_ips = self.splice_exec_ips_list(ticket_ips=kwargs["exec_ip"]) + + if not exec_ips: + self.log_error(_("该节点获取到执行ip信息为空,请联系系统管理员{}").format(exec_ips)) + + target_ip_info = [{"bk_cloud_id": kwargs["bk_cloud_id"], "ip": ip} for ip in exec_ips] + + # 拼接fast_trans_file 接口请求参数 + payload = copy.deepcopy(consts.BK_TRANSFER_REPO_PAYLOAD) + payload["bk_biz_id"] = env.JOB_BLUEKING_BIZ_ID + payload["file_source_list"].append( + { + "file_list": kwargs["file_list"], + "file_type": MediumFileTypeEnum.Repo.value, + "file_source_code": env.APP_CODE, + } + ) + payload["target_server"]["ip_list"] = target_ip_info + + self.log_info(_("[{}] 下发介质包参数:{}").format(node_name, payload)) + FlowNode.objects.filter(root_id=root_id, node_id=node_id).update(hosts=exec_ips) + + # 请求传输 + resp = JobApi.fast_transfer_file(payload, raw=True) + if (resp.get("result") is not True) or (int(resp["code"] != 0)): + raise Exception(f"{str(resp)}") + + # 传入调用结果,并单调监听任务状态 + data.outputs.ext_result = resp + return True + + def inputs_format(self) -> List: + return [ + Service.InputItem(name="kwargs", key="kwargs", type="dict", required=True), + Service.InputItem(name="global_data", key="global_data", type="dict", required=True), + ] + + def outputs_format(self) -> List: + return [Service.OutputItem(name="exec_ips", key="exec_ips", type="list")] + + +class TransFileComponent(Component): + name = __name__ + code = "riak_exec_trans_file" + bound_service = TransFileService diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index 92408d38e8..c32d0f3d4c 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -108,6 +108,7 @@ RedisClusterSlaveCutOffSceneApiView, RedisInstallDbmonSceneApiView, ) +from backend.flow.views.riak_apply import RiakApplySceneApiView from backend.flow.views.rollback_pipeline import PipelineTreeApiView, RollbackPipelineApiView from backend.flow.views.spider_add_nodes import AddSpiderNodesSceneApiView from backend.flow.views.spider_add_tmp_node import AddTmpSpiderSceneApiView @@ -261,4 +262,6 @@ # spider 添加 url(r"^scene/add_spider_nodes$", AddSpiderNodesSceneApiView.as_view()), url(r"^scene/tendbcluster_full_backup$", TenDBClusterFullBackupView.as_view()), + # riak + url(r"^scene/riak_cluster_apply$", RiakApplySceneApiView.as_view()), ] diff --git a/dbm-ui/backend/flow/utils/riak/riak_act_dataclass.py b/dbm-ui/backend/flow/utils/riak/riak_act_dataclass.py new file mode 100644 index 0000000000..6043873ddb --- /dev/null +++ b/dbm-ui/backend/flow/utils/riak/riak_act_dataclass.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from dataclasses import dataclass, field +from typing import Any, Optional + +from backend.flow.consts import MediumFileTypeEnum + +""" +定义每个活动节点的私用变量kwargs的dataclass类型 +建议每个活动节点都需要定义,这样可以知道每个活动节点需要的私有变量的结构体都可以知道 +todo 后续慢慢定义好目前存量的活动节点的私有变量kwargs,调整所有单据入参方式 +todo 结合validator来对dataclass对数据校验 +""" + + +@dataclass() +class ExecActuatorBaseKwargs: + """ + 定义执行riak_db_actuator_executor活动节点的私用变量通用结构体 + """ + + bk_cloud_id: int # 对应的云区域ID + run_as_system_user: str = None # 表示执行job的api的操作用户, None 默认是用root用户 + get_riak_payload_func: str = None # 上下文中MysqlActPayload类的获取参数方法名称。空则传入None + cluster_type: str = None # 表示操作的集群类型,如果过程中不需要这个变量,则可以传None + cluster: dict = field(default_factory=dict) # 表示单据执行的集群信息,比如集群名称,集群域名等 + + +@dataclass() +class ExecActuatorKwargs(ExecActuatorBaseKwargs): + """ + 针对手输IP的场景 + """ + + exec_ip: Optional[Any] = None # 表示执行的ip,多个ip传入list类型,当个ip传入str类型,空则传入None,针对手输ip场景 + + +@dataclass() +class DownloadMediaBaseKwargs: + """ + 定义在介质中心下发介质的私用变量结构体 + """ + + bk_cloud_id: int # 对应的云区域ID + file_list: list # 需要传送的源文件列表 + file_type: Optional[MediumFileTypeEnum] = MediumFileTypeEnum.Repo.value + file_target_path: str = None # 表示下载到目标机器的路径,如果传None,默认则传/data/install + + +@dataclass() +class DownloadMediaKwargs(DownloadMediaBaseKwargs): + """ + 针对手输IP的场景 + """ + + exec_ip: Optional[Any] = None # 表示执行的ip,多个ip传入list类型,当个ip传入str类型,空则传入None,针对手输ip场景 + + +@dataclass() +class DBMetaFuncKwargs: + """ + 修改元数据的函数 + """ + + db_meta_class_func: str = None + cluster: dict = field(default_factory=dict) # 表示单据执行的集群信息,比如集群名称,集群域名等 + is_update_trans_data: bool = False # 表示是否把流程中上下文trans_data合并到cluster信息,默认不合并 diff --git a/dbm-ui/backend/flow/utils/riak/riak_act_payload.py b/dbm-ui/backend/flow/utils/riak/riak_act_payload.py new file mode 100644 index 0000000000..15aba997fc --- /dev/null +++ b/dbm-ui/backend/flow/utils/riak/riak_act_payload.py @@ -0,0 +1,94 @@ +from backend.configuration.constants import DBType +from backend.db_package.models import Package +from backend.flow.consts import DBActuatorTypeEnum, RiakActuatorActionEnum, MediumEnum + + +class RiakActPayload(object): + """ + 定义Riak不同的执行类型,拼接不同的payload参数,对应不同的dict结构体 + """ + + def __init__(self, ticket_data: dict, cluster: dict): + self.riak_pkg = None + self.bk_biz_id = str(ticket_data["bk_biz_id"]) + self.ticket_data = ticket_data + self.cluster = cluster + + def get_sysinit_payload(self, **kwargs) -> dict: + """ + 系统配置初始化 + """ + return { + "db_type": DBActuatorTypeEnum.Default.value, + "action": RiakActuatorActionEnum.SysinitRiak.value, + "payload": {"general": {}, "extend": {}}, + } + + def get_deploy_payload(self, **kwargs) -> dict: + """ + 部署节点 + """ + self.riak_pkg = Package.get_latest_package(version="2.2.1", pkg_type=MediumEnum.Riak, db_type=DBType.Riak) + return { + "db_type": DBActuatorTypeEnum.Riak.value, + "action": RiakActuatorActionEnum.Deploy.value, + "payload": { + "general": {}, + "extend": { + "distributed_cookie": self.cluster["distributed_cookie"], + "ring_size": self.cluster["ring_size"], + "db_module_id": self.ticket_data["db_module_id"], + "pkg": { + "name": self.riak_pkg.name, + "md5": self.riak_pkg.md5, + }, + }, + }, + } + + def get_join_cluster_payload(self, **kwargs) -> dict: + """ + 添加节点 + """ + return { + "db_type": DBActuatorTypeEnum.Riak.value, + "action": RiakActuatorActionEnum.JoinCluster.value, + "payload": { + "general": {}, + "extend": { + "distributed_cookie": self.cluster["distributed_cookie"], + "ring_size": self.cluster["ring_size"], + "base_node": kwargs["trans_data"]["base_node"], + }, + }, + } + + def get_commit_cluster_change_payload(self, **kwargs) -> dict: + """ + 集群变更生效 + """ + return { + "db_type": DBActuatorTypeEnum.Riak.value, + "action": RiakActuatorActionEnum.CommitClusterChange.value, + "payload": { + "general": {}, + "extend": { + "nodes": kwargs["trans_data"]["nodes"], + }, + }, + } + + def get_init_bucket_type_payload(self, **kwargs) -> dict: + """ + 添加节点 + """ + return { + "db_type": DBActuatorTypeEnum.Riak.value, + "action": RiakActuatorActionEnum.InitBucketType.value, + "payload": { + "general": {}, + "extend": { + "bucket_types": self.cluster["bucket_types"], + }, + }, + } diff --git a/dbm-ui/backend/flow/utils/riak/riak_context_dataclass.py b/dbm-ui/backend/flow/utils/riak/riak_context_dataclass.py new file mode 100644 index 0000000000..802062340d --- /dev/null +++ b/dbm-ui/backend/flow/utils/riak/riak_context_dataclass.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from typing import Optional, Any + +from dataclasses import dataclass, field + + +@dataclass() +class RiakActKwargs: + """ + 定义Riak活动节点的私有变量dataclass类 + """ + + bk_cloud_id: int # 对应的云区域ID + exec_ip: Optional[Any] = None # 表示执行的IP,多个IP传入list,单个IP传入str,空传入None + set_trans_data_dataclass: str = None # 加载到上下文的dataclass类的名称 + get_riak_payload_func: str = None # 上下文中RiakActPayload类的获取参数方法名称。空则传入None + file_list: list = field(default_factory=list) # 传入文件传输节点的文件名称列表,默认空字典 + cluster: dict = field(default_factory=dict) # 集群信息 + run_as_system_user: str = None # 表示执行job的api的操作用户, None 默认是用root用户 + + +@dataclass() +class ApplyManualContext: + """ + 定义单节点申请的上下文dataclass类(手输ip模式) + """ + + nodes: list = field(default_factory=list) # 手工输入的所有ip + base_node: str = None # 选取一个ip为操作节点 + operate_nodes: list = field(default_factory=list) # 除base_node外的其他ip + + +@dataclass() +class AddNodeManualContext: + """ + 定义单节点申请的上下文dataclass类(手输ip模式) + """ + + base_node: str = None # 选取集群中已存在的一个ip为操作节点 + operate_nodes: list = field(default_factory=list) # 手工输入的所有ip diff --git a/dbm-ui/backend/flow/utils/riak/riak_db_meta.py b/dbm-ui/backend/flow/utils/riak/riak_db_meta.py new file mode 100644 index 0000000000..195bfcd1a5 --- /dev/null +++ b/dbm-ui/backend/flow/utils/riak/riak_db_meta.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging + +from django.db.transaction import atomic +from backend.db_meta import api +from backend.db_meta.enums import InstanceRole, MachineType + +logger = logging.getLogger("flow") + + +class RiakDBMeta(object): + """ + 根据单据信息和集群信息,更新cmdb + 类的方法一定以单据类型的小写进行命名,否则不能根据单据类型匹配对应的方法 + """ + + def __init__(self, ticket_data: dict, cluster: dict): + """ + @param ticket_data : 单据信息 + @param cluster: 集群信息 + """ + self.ticket_data = ticket_data + self.cluster = cluster + + def riak_deploy_node(self) -> bool: + if self.ticket_data["ticket_type"] == "RIAK_APPLY": + ips = self.cluster.nodes + elif self.ticket_data["ticket_type"] == "RIAK_ADD_NODE": + ips = self.cluster.operate_nodes + else: + logger.error("not supported ticket type for adding db meta") + return False + + machines = [ + {"ip": ip, "bk_biz_id": int(self.ticket_data["bk_biz_id"]), "machine_type": MachineType.RIAK.value} + for ip in ips + ] + + instances = [{"ip": ip, "port": 8087, "instance_role": InstanceRole.RIAK_NODE.value} for ip in ips] + + cluster = { + "bk_cloud_id": self.ticket_data["bk_cloud_id"], + "bk_biz_id": int(self.ticket_data["bk_biz_id"]), + "name": self.ticket_data["cluster_name"], + "alias": self.ticket_data["cluster_alias"], + "immute_domain": self.ticket_data["domain"], + "db_module_id": self.ticket_data["db_module_id"], + "storages": instances, + "creator": self.ticket_data["created_by"], + "major_version": self.ticket_data["db_version"], + } + + with atomic(): + api.machine.create( + machines=machines, + bk_cloud_id=self.ticket_data["bk_cloud_id"], + creator=self.ticket_data["created_by"], + ) + api.storage_instance.create(instances=instances, creator=self.ticket_data["created_by"]) + api.cluster.riak.create(**cluster) + return True diff --git a/dbm-ui/backend/flow/views/riak_apply.py b/dbm-ui/backend/flow/views/riak_apply.py new file mode 100644 index 0000000000..4858fd3660 --- /dev/null +++ b/dbm-ui/backend/flow/views/riak_apply.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import uuid + +from rest_framework.response import Response + +from backend.flow.engine.controller.riak import RiakController +from backend.flow.views.base import FlowTestView + + +class RiakApplySceneApiView(FlowTestView): + def post(self, request): + root_id = uuid.uuid1().hex + flow = RiakController(root_id=root_id, ticket_data=request.data) + flow.riak_cluster_apply_scene() + return Response({"root_id": root_id}) From 317b494bd0a91a8be54426821679e8431f1baba7 Mon Sep 17 00:00:00 2001 From: zhangzhw8 <826035498@qq.com> Date: Tue, 20 Jun 2023 16:00:48 +0800 Subject: [PATCH 038/476] =?UTF-8?q?feat(backend):=20=E5=8D=95=E6=8D=AE?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=AF=A6=E6=83=85=E8=BF=94=E5=9B=9E=E9=9B=86?= =?UTF-8?q?=E7=BE=A4/=E5=AE=9E=E4=BE=8B=E4=BF=A1=E6=81=AF=20#249?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_meta/models/instance.py | 6 + .../db_services/ipchooser/query/resource.py | 2 +- dbm-ui/backend/db_services/taskflow/task.py | 2 +- dbm-ui/backend/ticket/constants.py | 16 +- dbm-ui/backend/ticket/flow_manager/base.py | 57 +- dbm-ui/backend/ticket/flow_manager/inner.py | 3 +- dbm-ui/backend/ticket/flow_manager/timer.py | 3 +- dbm-ui/backend/ticket/handler.py | 70 + dbm-ui/backend/ticket/views.py | 8 +- dbm-ui/backend/utils/basic.py | 57 +- dbm-ui/bin/environ.sh | 8 +- dbm-ui/config/default.py | 1 + dbm-ui/locale/en/LC_MESSAGES/django.mo | Bin 201470 -> 200513 bytes dbm-ui/locale/en/LC_MESSAGES/django.po | 7129 ++++++++--------- dbm-ui/locale/zh_hans/LC_MESSAGES/django.mo | Bin 200831 -> 199515 bytes dbm-ui/locale/zh_hans/LC_MESSAGES/django.po | 6810 ++++++++-------- 16 files changed, 7050 insertions(+), 7122 deletions(-) create mode 100644 dbm-ui/backend/ticket/handler.py diff --git a/dbm-ui/backend/db_meta/models/instance.py b/dbm-ui/backend/db_meta/models/instance.py index e9526986f7..365894b0c1 100644 --- a/dbm-ui/backend/db_meta/models/instance.py +++ b/dbm-ui/backend/db_meta/models/instance.py @@ -120,6 +120,12 @@ class Meta: def __str__(self): return self.ip_port + @classmethod + def get_instance_id_ip_port_map(cls, instance_id: List[int]) -> Dict[int, str]: + """查询实例 ID 和 IP:PORT 的映射关系""" + instances = cls.objects.select_related("machine").filter(id__in=instance_id) + return {instance.id: instance.ip_port for instance in instances} + @property def ip_port(self): return f"{self.machine.ip}{constants.IP_PORT_DIVIDER}{self.port}" diff --git a/dbm-ui/backend/db_services/ipchooser/query/resource.py b/dbm-ui/backend/db_services/ipchooser/query/resource.py index 7657317c98..e0026b2899 100644 --- a/dbm-ui/backend/db_services/ipchooser/query/resource.py +++ b/dbm-ui/backend/db_services/ipchooser/query/resource.py @@ -464,5 +464,5 @@ def search_cc_cloud(cls): ) cloud_id__cloud_info = {str(info["bk_cloud_id"]): info for info in resp} # 命名要求 default_area ---> Direct Mode - cloud_id__cloud_info[str(0)]["bk_cloud_name"] = _("Direct Area") + cloud_id__cloud_info[str(0)]["bk_cloud_name"] = _("直连区域") return cloud_id__cloud_info diff --git a/dbm-ui/backend/db_services/taskflow/task.py b/dbm-ui/backend/db_services/taskflow/task.py index 97b52d3ba6..4e48b7c5a6 100644 --- a/dbm-ui/backend/db_services/taskflow/task.py +++ b/dbm-ui/backend/db_services/taskflow/task.py @@ -25,8 +25,8 @@ from backend.flow.models import FlowNode from backend.flow.plugins.components.collections.common.base_service import BaseService from backend.ticket.constants import FlowRetryType -from backend.ticket.flow_manager.base import get_target_items_from_details from backend.ticket.models import Flow, Ticket +from backend.utils.basic import get_target_items_from_details logger = logging.getLogger("flow") diff --git a/dbm-ui/backend/ticket/constants.py b/dbm-ui/backend/ticket/constants.py index 3efd0c771f..6e4ce0cbd7 100644 --- a/dbm-ui/backend/ticket/constants.py +++ b/dbm-ui/backend/ticket/constants.py @@ -199,14 +199,14 @@ def get_choice_value(cls, label: str) -> str: ES_DISABLE = EnumField("ES_DISABLE", _("ES 集群禁用")) ES_DESTROY = EnumField("ES_DESTROY", _("ES 集群删除")) - PULSAR_APPLY = EnumField("PULSAR_APPLY", _("PULSAR 集群部署")) - PULSAR_SCALE_UP = EnumField("PULSAR_SCALE_UP", _("PULSAR 集群扩容")) - PULSAR_SHRINK = EnumField("PULSAR_SHRINK", _("PULSAR 集群缩容")) - PULSAR_REBOOT = EnumField("PULSAR_REBOOT", _("PULSAR 实例重启")) - PULSAR_REPLACE = EnumField("PULSAR_REPLACE", _("PULSAR 集群替换")) - PULSAR_ENABLE = EnumField("PULSAR_ENABLE", _("PULSAR 集群启用")) - PULSAR_DISABLE = EnumField("PULSAR_DISABLE", _("PULSAR 集群禁用")) - PULSAR_DESTROY = EnumField("PULSAR_DESTROY", _("PULSAR 集群删除")) + PULSAR_APPLY = EnumField("PULSAR_APPLY", _("Pulsar 集群部署")) + PULSAR_SCALE_UP = EnumField("PULSAR_SCALE_UP", _("Pulsar 集群扩容")) + PULSAR_SHRINK = EnumField("PULSAR_SHRINK", _("Pulsar 集群缩容")) + PULSAR_REBOOT = EnumField("PULSAR_REBOOT", _("Pulsar 实例重启")) + PULSAR_REPLACE = EnumField("PULSAR_REPLACE", _("Pulsar 集群替换")) + PULSAR_ENABLE = EnumField("PULSAR_ENABLE", _("Pulsar 集群启用")) + PULSAR_DISABLE = EnumField("PULSAR_DISABLE", _("Pulsar 集群禁用")) + PULSAR_DESTROY = EnumField("PULSAR_DESTROY", _("Pulsar 集群删除")) INFLUXDB_APPLY = EnumField("INFLUXDB_APPLY", _("InfluxDB 实例部署")) INFLUXDB_REBOOT = EnumField("INFLUXDB_REBOOT", _("InfluxDB 实例重启")) diff --git a/dbm-ui/backend/ticket/flow_manager/base.py b/dbm-ui/backend/ticket/flow_manager/base.py index 69817b4a72..f8896f7902 100644 --- a/dbm-ui/backend/ticket/flow_manager/base.py +++ b/dbm-ui/backend/ticket/flow_manager/base.py @@ -10,7 +10,7 @@ """ import logging from abc import ABC, abstractmethod -from typing import Any, List, Optional, Union +from typing import Any, Optional, Union from django.utils.translation import gettext as _ @@ -21,61 +21,6 @@ logger = logging.getLogger("root") -def _get_target_items_from_details( - obj: Union[dict, list], match_keys: List[str], target_items: Optional[List[Any]] = None -) -> List[Any]: - """ - 递归获取单据参数中的所有目标对象(目标对象类型为: int, str, dict。如果有后续类型需求可扩展) - 以集群位例:所有集群 cluster_ids, cluster_id 字段的值的集合,如 - { - "cluster_id": 1, - ... - "cluster_ids": [1, 2, 3] - ... - "rules": [{"cluster_id": 4, ...}, {"cluster_id": 5, ...}], - ... - "xxx_infos": [{"cluster_ids": [5, 6], ...}, {"cluster_ids": [6, 7], ...}], - } - 得到的 cluster_ids = set([1, 2, 3, 4, 5, 6, 7]) - """ - - def _union_target(_target_items: List[Any], target: Union[list, Any]): - if isinstance(target, list): - _target_items.extend(target) - if isinstance(target, (int, str, dict)): - _target_items.append(target) - return _target_items - - target_items = target_items or [] - if isinstance(obj, dict): - for key, value in obj.items(): - if key in match_keys: - target_items = _union_target(target_items, value) - if isinstance(value, (dict, list)): - target_items = _get_target_items_from_details(value, match_keys, target_items) - - if isinstance(obj, list): - for _obj in obj: - target_items = _get_target_items_from_details(_obj, match_keys, target_items) - - return target_items - - -def get_target_items_from_details( - obj: Union[dict, list], match_keys: List[str], target_items: Optional[List[Any]] = None -) -> List[Any]: - target_items = _get_target_items_from_details(obj, match_keys, target_items) - target_items_type = set([type(item) for item in target_items]) - - if len(target_items_type) != 1 or not target_items: - return target_items - - if target_items and isinstance(target_items[0], (int, str)): - return list(set(target_items)) - else: - return target_items - - class BaseTicketFlow(ABC): def __init__(self, flow_obj: Flow): self.ticket = flow_obj.ticket diff --git a/dbm-ui/backend/ticket/flow_manager/inner.py b/dbm-ui/backend/ticket/flow_manager/inner.py index df589bbed2..99f0e59c2f 100644 --- a/dbm-ui/backend/ticket/flow_manager/inner.py +++ b/dbm-ui/backend/ticket/flow_manager/inner.py @@ -22,8 +22,9 @@ from backend.flow.models import FlowTree from backend.ticket import constants from backend.ticket.constants import BAMBOO_STATE__TICKET_STATE_MAP, FlowCallbackType -from backend.ticket.flow_manager.base import BaseTicketFlow, get_target_items_from_details +from backend.ticket.flow_manager.base import BaseTicketFlow from backend.ticket.models import ClusterOperateRecord, Flow, InstanceOperateRecord +from backend.utils.basic import get_target_items_from_details from backend.utils.time import datetime2str logger = logging.getLogger("root") diff --git a/dbm-ui/backend/ticket/flow_manager/timer.py b/dbm-ui/backend/ticket/flow_manager/timer.py index db94cf66f7..708e7f1330 100644 --- a/dbm-ui/backend/ticket/flow_manager/timer.py +++ b/dbm-ui/backend/ticket/flow_manager/timer.py @@ -17,9 +17,10 @@ from backend.ticket import constants from backend.ticket.constants import TodoType -from backend.ticket.flow_manager.base import BaseTicketFlow, get_target_items_from_details +from backend.ticket.flow_manager.base import BaseTicketFlow from backend.ticket.models import Flow, Todo from backend.ticket.tasks.ticket_tasks import TicketTask, apply_ticket_task +from backend.utils.basic import get_target_items_from_details from backend.utils.time import countdown2str, datetime2str, str2datetime diff --git a/dbm-ui/backend/ticket/handler.py b/dbm-ui/backend/ticket/handler.py new file mode 100644 index 0000000000..21bd0412b7 --- /dev/null +++ b/dbm-ui/backend/ticket/handler.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from typing import Dict, List + +from django.utils.translation import ugettext as _ + +from backend.db_meta.models import Cluster, StorageInstance +from backend.ticket.models import Ticket +from backend.utils.basic import get_target_items_from_details + + +class TicketHandler: + @classmethod + def add_related_object(cls, ticket_data: List[Dict]) -> List[Dict]: + """ + 补充单据的关联对象 + - 针对集群操作,则补充集群域名 + - 针对实例操作,则补充集群 IP:PORT + - ... + """ + ticket_ids = [ticket["id"] for ticket in ticket_data] + # 这批单据所操作的集群列表 + cluster_ids = [] + # 这批单据所操作的实例列表 + instance_ids = [] + # 单据关联对象映射表 + ticket_id_obj_ids_map: Dict[int, Dict[str, List[int]]] = {} + + # 查询单据对应的集群列表、实例列表等 + for ticket in Ticket.objects.filter(id__in=ticket_ids): + _cluster_ids = get_target_items_from_details(ticket.details, match_keys=["cluster_id", "cluster_ids"]) + _instance_ids = get_target_items_from_details(ticket.details, match_keys=["instance_id", "instance_ids"]) + cluster_ids.extend(_cluster_ids) + instance_ids.extend(_instance_ids) + ticket_id_obj_ids_map[ticket.id] = {"cluster_ids": _cluster_ids, "instance_ids": _instance_ids} + cluster_id_immute_domain_map = Cluster.get_cluster_id_immute_domain_map(cluster_ids) + instance_id_ip_port_map = StorageInstance.get_instance_id_ip_port_map(instance_ids) + + # 补充关联对象信息 + for item in ticket_data: + ticket_cluster_ids = ticket_id_obj_ids_map[item["id"]]["cluster_ids"] + if ticket_cluster_ids: + item["related_object"] = { + "title": _("集群"), + "objects": [ + cluster_id_immute_domain_map.get(cluster_id) + for cluster_id in ticket_cluster_ids + if cluster_id_immute_domain_map.get(cluster_id) + ], + } + + ticket_instance_ids = ticket_id_obj_ids_map[item["id"]]["instance_ids"] + if ticket_instance_ids: + item["related_object"] = { + "title": _("实例"), + "objects": [ + instance_id_ip_port_map.get(instance_id) + for instance_id in ticket_instance_ids + if instance_id_ip_port_map.get(instance_id) + ], + } + return ticket_data diff --git a/dbm-ui/backend/ticket/views.py b/dbm-ui/backend/ticket/views.py index 28f7e1634b..d8ece63a25 100644 --- a/dbm-ui/backend/ticket/views.py +++ b/dbm-ui/backend/ticket/views.py @@ -30,8 +30,8 @@ from backend.ticket.constants import DONE_STATUS, CountType, TicketStatus, TicketType, TodoStatus from backend.ticket.contexts import TicketContext from backend.ticket.exceptions import TicketDuplicationException -from backend.ticket.flow_manager.base import get_target_items_from_details from backend.ticket.flow_manager.manager import TicketFlowManager +from backend.ticket.handler import TicketHandler from backend.ticket.models import ClusterOperateRecord, Flow, InstanceOperateRecord, Ticket, Todo from backend.ticket.serializers import ( ClusterModifyOpSerializer, @@ -48,6 +48,7 @@ TodoSerializer, ) from backend.ticket.todos import TodoActorFactory +from backend.utils.basic import get_target_items_from_details TICKET_TAG = "ticket" @@ -190,7 +191,9 @@ def retrieve(self, request, *args, **kwargs): tags=[TICKET_TAG], ) def list(self, request, *args, **kwargs): - return super().list(request, *args, **kwargs) + resp = super().list(request, *args, **kwargs) + resp.data["results"] = TicketHandler.add_related_object(resp.data["results"]) + return resp @swagger_auto_schema( operation_summary=_("创建单据"), @@ -315,6 +318,7 @@ def get_todo_tickets(self, request, *args, **kwargs): return self.get_paginated_response(serializer.data) serializer = TicketSerializer(page, many=True, context=context) + serializer.data["results"] = TicketHandler.add_related_object(serializer.data["results"]) return Response(serializer.data) @swagger_auto_schema( diff --git a/dbm-ui/backend/utils/basic.py b/dbm-ui/backend/utils/basic.py index 9a58fa9f18..ff56e0c633 100644 --- a/dbm-ui/backend/utils/basic.py +++ b/dbm-ui/backend/utils/basic.py @@ -11,7 +11,7 @@ from collections import Counter, namedtuple from copy import deepcopy -from typing import Any, Dict, Iterable, List, Set, Union +from typing import Any, Dict, Iterable, List, Optional, Set, Union def tuple_choices(tupl): @@ -179,3 +179,58 @@ def get_chr_seq(begin_chr: str, end_chr: str) -> List[str]: :return: """ return [chr(ascii_int) for ascii_int in range(ord(begin_chr), ord(end_chr) + 1)] + + +def _get_target_items_from_details( + obj: Union[dict, list], match_keys: List[str], target_items: Optional[List[Any]] = None +) -> List[Any]: + """ + 递归获取单据参数中的所有目标对象(目标对象类型为: int, str, dict。如果有后续类型需求可扩展) + 以集群位例:所有集群 cluster_ids, cluster_id 字段的值的集合,如 + { + "cluster_id": 1, + ... + "cluster_ids": [1, 2, 3] + ... + "rules": [{"cluster_id": 4, ...}, {"cluster_id": 5, ...}], + ... + "xxx_infos": [{"cluster_ids": [5, 6], ...}, {"cluster_ids": [6, 7], ...}], + } + 得到的 cluster_ids = set([1, 2, 3, 4, 5, 6, 7]) + """ + + def _union_target(_target_items: List[Any], target: Union[list, Any]): + if isinstance(target, list): + _target_items.extend(target) + if isinstance(target, (int, str, dict)): + _target_items.append(target) + return _target_items + + target_items = target_items or [] + if isinstance(obj, dict): + for key, value in obj.items(): + if key in match_keys: + target_items = _union_target(target_items, value) + if isinstance(value, (dict, list)): + target_items = _get_target_items_from_details(value, match_keys, target_items) + + if isinstance(obj, list): + for _obj in obj: + target_items = _get_target_items_from_details(_obj, match_keys, target_items) + + return target_items + + +def get_target_items_from_details( + obj: Union[dict, list], match_keys: List[str], target_items: Optional[List[Any]] = None +) -> List[Any]: + target_items = _get_target_items_from_details(obj, match_keys, target_items) + target_items_type = set([type(item) for item in target_items]) + + if len(target_items_type) != 1 or not target_items: + return target_items + + if target_items and isinstance(target_items[0], (int, str)): + return list(set(target_items)) + else: + return target_items diff --git a/dbm-ui/bin/environ.sh b/dbm-ui/bin/environ.sh index 23dc8ba9d8..0c32a68b9a 100755 --- a/dbm-ui/bin/environ.sh +++ b/dbm-ui/bin/environ.sh @@ -1,13 +1,7 @@ #!/bin/sh -export APP_ID="bk-dbm" +export APP_ID="bk_dbm" export APP_TOKEN="xxxxxx" export DJANGO_SETTINGS_MODULE=config.prod export BK_LOG_DIR=/tmp/bk-dbm export BK_IAM_SKIP=true - -export BKREPO_USERNAME="bkdbm" -export BKREPO_PASSWORD="bkdbm" -export BKREPO_PROJECT="blueking" -export BKREPO_PUBLIC_BUCKET="bkdbm" -export BKREPO_ENDPOINT_URL="http://bkrepo.example.com" \ No newline at end of file diff --git a/dbm-ui/config/default.py b/dbm-ui/config/default.py index 7c7a51f02c..23410e63cf 100644 --- a/dbm-ui/config/default.py +++ b/dbm-ui/config/default.py @@ -164,6 +164,7 @@ # blueapps BK_COMPONENT_API_URL = env.BK_COMPONENT_API_URL +IS_AJAX_PLAIN_MODE = True # init admin list INIT_SUPERUSER = ["admin"] diff --git a/dbm-ui/locale/en/LC_MESSAGES/django.mo b/dbm-ui/locale/en/LC_MESSAGES/django.mo index db02ccb9d6ce570657cd5afb3ac35e78f92694a3..b10072ff4a26c0628b70122b3b3c4106b6498a1a 100644 GIT binary patch delta 58049 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 diff --git a/dbm-ui/locale/en/LC_MESSAGES/django.po b/dbm-ui/locale/en/LC_MESSAGES/django.po index 3ce36fb55c..f476b0e5ef 100644 --- a/dbm-ui/locale/en/LC_MESSAGES/django.po +++ b/dbm-ui/locale/en/LC_MESSAGES/django.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-09 10:20+0800\n" +"POT-Creation-Date: 2023-06-20 15:59+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -63,7 +63,7 @@ msgstr "System error, please contact administrator({error})" #: backend/db_services/mysql/resources/tendbha/query.py:46 #: backend/db_services/mysql/resources/tendbsingle/query.py:42 #: backend/db_services/redis/resources/redis_cluster/query.py:61 -#: backend/redis_dts/serializers.py:17 +#: backend/db_services/redis_dts/serializers.py:17 #: backend/ticket/builders/mysql/mysql_import_sqlfile.py:66 msgid "创建人" msgstr "founder" @@ -79,11 +79,10 @@ msgstr "founder" #: backend/db_services/mysql/resources/tendbsingle/query.py:43 #: backend/db_services/mysql/sql_import/serializers.py:143 #: backend/db_services/redis/resources/redis_cluster/query.py:62 -#: backend/flow/models.py:45 -#: backend/redis_dts/models/tb_dts_distribute_lock.py:19 -#: backend/redis_dts/models/tb_tendis_dts_job.py:57 -#: backend/redis_dts/models/tb_tendis_dts_task.py:70 -#: backend/ticket/models/ticket.py:43 +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:19 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:57 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:70 +#: backend/flow/models.py:45 backend/ticket/models/ticket.py:43 msgid "创建时间" msgstr "creation time" @@ -97,9 +96,9 @@ msgstr "Edited by" #: backend/db_services/bigdata/resources/query.py:50 #: backend/db_services/dbconfig/serializers.py:66 #: backend/db_services/redis/resources/redis_cluster/query.py:64 -#: backend/flow/models.py:47 backend/redis_dts/models/tb_tendis_dts_job.py:58 -#: backend/redis_dts/models/tb_tendis_dts_task.py:71 -#: backend/ticket/models/ticket.py:44 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:58 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:71 +#: backend/flow/models.py:47 backend/ticket/models/ticket.py:44 msgid "更新时间" msgstr "update time" @@ -371,6 +370,12 @@ msgstr "" "Query the relationship between the host and the module according to the " "module ID" +#: backend/components/cc/client.py:261 +#, fuzzy +#| msgid "[dbmeta]查询entry信息" +msgid "查询主机业务关系信息" +msgstr "[dbmeta] query entry information" + #: backend/components/cmsi/client.py:19 msgid "消息管理" msgstr "message management" @@ -732,8 +737,8 @@ msgstr "Query switching details" msgid "ITSM流程管理" msgstr "ITSM process management" -#: backend/components/itsm/client.py:27 backend/ticket/views.py:174 -#: backend/ticket/views.py:176 +#: backend/components/itsm/client.py:27 backend/ticket/views.py:199 +#: backend/ticket/views.py:201 msgid "创建单据" msgstr "Create ticket" @@ -1028,7 +1033,7 @@ msgstr "Initial configuration exception, error message: {}" #: backend/configuration/constants.py:21 #: backend/db_services/mysql/permission/constants.py:47 -#: backend/flow/consts.py:239 +#: backend/flow/consts.py:245 msgid "MySQL" msgstr "MySQL" @@ -1042,7 +1047,7 @@ msgstr "tendbcluster" msgid "Redis" msgstr "Redis" -#: backend/configuration/constants.py:24 backend/flow/consts.py:124 +#: backend/configuration/constants.py:24 backend/flow/consts.py:130 msgid "Kafka" msgstr "Kafka" @@ -1054,7 +1059,7 @@ msgstr "HDFS" msgid "ElasticSearch" msgstr "ElasticSearch" -#: backend/configuration/constants.py:27 backend/flow/consts.py:126 +#: backend/configuration/constants.py:27 backend/flow/consts.py:132 msgid "Pulsar" msgstr "Pulsar" @@ -1482,7 +1487,7 @@ msgstr "public repository" msgid "私有仓库" msgstr "private warehouse" -#: backend/core/storages/constants.py:31 backend/flow/consts.py:234 +#: backend/core/storages/constants.py:31 backend/flow/consts.py:240 msgid "服务器文件" msgstr "server file" @@ -1663,7 +1668,7 @@ msgstr "log list" #: backend/db_services/ipchooser/constants.py:82 #: backend/db_services/ipchooser/mock_data.py:43 #: backend/db_services/ipchooser/mock_data.py:62 -#: backend/db_services/ipchooser/mock_data.py:98 +#: backend/db_services/ipchooser/mock_data.py:98 backend/ticket/handler.py:53 msgid "集群" msgstr "cluster" @@ -1683,7 +1688,7 @@ msgstr "instance role" #: backend/db_event/serializers.py:51 backend/db_event/serializers.py:66 #: backend/db_proxy/views/redis_dts/serializers.py:23 -#: backend/redis_dts/serializers.py:18 +#: backend/db_services/redis_dts/serializers.py:18 #: backend/ticket/builders/mysql/mysql_data_repair.py:36 #: backend/ticket/builders/mysql/mysql_flashback.py:28 #: backend/ticket/serializers.py:111 @@ -1693,7 +1698,7 @@ msgstr "Starting time" #: backend/db_event/serializers.py:52 backend/db_event/serializers.py:53 #: backend/db_event/serializers.py:67 #: backend/db_proxy/views/redis_dts/serializers.py:24 -#: backend/redis_dts/serializers.py:19 +#: backend/db_services/redis_dts/serializers.py:19 #: backend/ticket/builders/mysql/mysql_data_repair.py:37 #: backend/ticket/builders/mysql/mysql_flashback.py:29 #: backend/ticket/serializers.py:112 @@ -1918,7 +1923,7 @@ msgstr "access entrance (main)" msgid "Bookkeeper 节点" msgstr "zookeeper node" -#: backend/db_meta/api/cluster/tendbcluster/decommission.py:94 +#: backend/db_meta/api/cluster/tendbcluster/decommission.py:80 #: backend/db_meta/api/cluster/tendbha/decommission.py:79 msgid "{} 与 {} 的 {} 有同步关系" msgstr "{} has a synchronous relationship with {} of {}" @@ -2141,7 +2146,7 @@ msgid "机房 ID" msgstr "computer room ID" #: backend/db_meta/api/storage_instance/apis.py:190 -#: backend/db_meta/models/cluster.py:49 backend/db_meta/models/machine.py:46 +#: backend/db_meta/models/cluster.py:50 backend/db_meta/models/machine.py:46 #: backend/db_proxy/models.py:28 backend/db_proxy/models.py:47 #: backend/db_services/ipchooser/serializers/base.py:90 msgid "云区域 ID" @@ -2152,8 +2157,8 @@ msgid "网络设备 ID" msgstr "network device ID" #: backend/db_meta/enums/access_layer.py:16 -#: backend/db_meta/enums/machine_type.py:18 backend/flow/consts.py:246 -#: backend/flow/consts.py:507 backend/ticket/builders/common/constants.py:62 +#: backend/db_meta/enums/machine_type.py:18 backend/flow/consts.py:252 +#: backend/flow/consts.py:514 backend/ticket/builders/common/constants.py:62 #: backend/ticket/constants.py:23 msgid "proxy" msgstr "proxy" @@ -2211,7 +2216,7 @@ msgstr "destroy" msgid "normal" msgstr "normal" -#: backend/db_meta/enums/cluster_status.py:20 backend/flow/consts.py:417 +#: backend/db_meta/enums/cluster_status.py:20 backend/flow/consts.py:424 msgid "ABNORMAL" msgstr "ABNORMAL" @@ -2223,7 +2228,7 @@ msgstr "tendbsingle" msgid "tendbha" msgstr "tendbha" -#: backend/db_meta/enums/cluster_type.py:18 backend/flow/consts.py:128 +#: backend/db_meta/enums/cluster_type.py:18 backend/flow/consts.py:134 msgid "tendbcluster" msgstr "tendbcluster" @@ -2302,18 +2307,18 @@ msgstr "Mongo replica set" msgid "Mongo分片集群" msgstr "Mongo shard cluster" -#: backend/db_meta/enums/comm.py:17 backend/flow/consts.py:641 +#: backend/db_meta/enums/comm.py:17 backend/flow/consts.py:649 #, fuzzy #| msgid "msms" msgid "sms" msgstr "msms" -#: backend/db_meta/enums/comm.py:18 backend/flow/consts.py:640 +#: backend/db_meta/enums/comm.py:18 backend/flow/consts.py:648 msgid "mms" msgstr "mms" #: backend/db_meta/enums/comm.py:22 backend/db_meta/enums/machine_type.py:24 -#: backend/flow/consts.py:170 backend/flow/consts.py:247 +#: backend/flow/consts.py:176 backend/flow/consts.py:253 msgid "redis" msgstr "redis" @@ -2321,13 +2326,13 @@ msgstr "redis" msgid "mongodb" msgstr "mongodb" -#: backend/db_meta/enums/instance_inner_role.py:16 backend/flow/consts.py:508 -#: backend/flow/consts.py:520 backend/ticket/builders/common/constants.py:41 +#: backend/db_meta/enums/instance_inner_role.py:16 backend/flow/consts.py:515 +#: backend/flow/consts.py:527 backend/ticket/builders/common/constants.py:41 #: backend/ticket/builders/common/constants.py:60 msgid "master" msgstr "master" -#: backend/db_meta/enums/instance_inner_role.py:17 backend/flow/consts.py:509 +#: backend/db_meta/enums/instance_inner_role.py:17 backend/flow/consts.py:516 #: backend/ticket/builders/common/constants.py:61 msgid "slave" msgstr "slave" @@ -2396,15 +2401,15 @@ msgid "es_client" msgstr "es_client" #: backend/db_meta/enums/instance_role.py:39 -#: backend/db_meta/enums/machine_type.py:33 backend/flow/consts.py:575 +#: backend/db_meta/enums/machine_type.py:33 backend/flow/consts.py:582 #: backend/ticket/builders/common/constants.py:51 #: backend/ticket/builders/common/constants.py:56 msgid "broker" msgstr "broker" #: backend/db_meta/enums/instance_role.py:40 -#: backend/db_meta/enums/machine_type.py:34 backend/flow/consts.py:569 -#: backend/flow/consts.py:576 backend/ticket/builders/common/constants.py:47 +#: backend/db_meta/enums/machine_type.py:34 backend/flow/consts.py:576 +#: backend/flow/consts.py:583 backend/ticket/builders/common/constants.py:47 #: backend/ticket/builders/common/constants.py:50 #: backend/ticket/builders/common/constants.py:55 msgid "zookeeper" @@ -2428,8 +2433,8 @@ msgid "hdfs_datanode" msgstr "hdfs_datanode" #: backend/db_meta/enums/instance_role.py:47 -#: backend/db_meta/enums/machine_type.py:42 backend/flow/consts.py:183 -#: backend/flow/consts.py:255 +#: backend/db_meta/enums/machine_type.py:42 backend/flow/consts.py:189 +#: backend/flow/consts.py:261 #, fuzzy #| msgid "InfluxDB" msgid "influxdb" @@ -2521,12 +2526,12 @@ msgid "spider_mnt" msgstr "spider" #: backend/db_meta/enums/instance_status.py:16 backend/db_proxy/constants.py:35 -#: backend/flow/consts.py:430 +#: backend/flow/consts.py:437 msgid "running" msgstr "running" #: backend/db_meta/enums/instance_status.py:17 backend/db_proxy/constants.py:36 -#: backend/flow/consts.py:432 +#: backend/flow/consts.py:439 msgid "unavailable" msgstr "unavailable" @@ -2534,7 +2539,8 @@ msgstr "unavailable" msgid "restoring" msgstr "restoring" -#: backend/db_meta/enums/machine_type.py:16 backend/flow/consts.py:258 +#: backend/db_meta/enums/machine_type.py:16 backend/flow/consts.py:264 +#: backend/flow/consts.py:721 msgid "spider" msgstr "spider" @@ -2550,13 +2556,13 @@ msgstr "backend" msgid "single" msgstr "single" -#: backend/db_meta/enums/machine_type.py:22 backend/flow/consts.py:177 -#: backend/flow/consts.py:250 +#: backend/db_meta/enums/machine_type.py:22 backend/flow/consts.py:183 +#: backend/flow/consts.py:256 msgid "predixy" msgstr "predixy" -#: backend/db_meta/enums/machine_type.py:23 backend/flow/consts.py:176 -#: backend/flow/consts.py:249 +#: backend/db_meta/enums/machine_type.py:23 backend/flow/consts.py:182 +#: backend/flow/consts.py:255 msgid "twemproxy" msgstr "twemproxy" @@ -2564,13 +2570,13 @@ msgstr "twemproxy" msgid "tendiscache" msgstr "tend to cache" -#: backend/db_meta/enums/machine_type.py:26 backend/flow/consts.py:172 +#: backend/db_meta/enums/machine_type.py:26 backend/flow/consts.py:178 #, fuzzy #| msgid "tendis" msgid "tendisssd" msgstr "tending" -#: backend/db_meta/enums/machine_type.py:27 backend/flow/consts.py:171 +#: backend/db_meta/enums/machine_type.py:27 backend/flow/consts.py:177 msgid "tendisplus" msgstr "tend more" @@ -2598,13 +2604,19 @@ msgstr "DBMeta module exception" #: backend/db_meta/exceptions.py:23 backend/db_meta/exceptions.py:101 #: backend/flow/engine/bamboo/scene/hdfs/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:22 #: backend/flow/engine/bamboo/scene/pulsar/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:22 msgid "通用异常" msgstr "generic exception" #: backend/db_meta/exceptions.py:24 backend/db_meta/exceptions.py:102 #: backend/flow/engine/bamboo/scene/hdfs/exceptions.py:24 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:23 #: backend/flow/engine/bamboo/scene/pulsar/exceptions.py:24 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:29 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:35 #, python-brace-format msgid "{message}" msgstr "{message}" @@ -2614,8 +2626,10 @@ msgid "新建TenDBHA前置检查异常" msgstr "New TenDBHA pre-check exception" #: backend/db_meta/exceptions.py:30 backend/db_meta/exceptions.py:66 +#: backend/db_services/redis_dts/exceptions.py:24 +#: backend/db_services/redis_dts/exceptions.py:30 +#: backend/flow/engine/exceptions.py:33 #: backend/flow/utils/mysql/db_table_filter/exception.py:24 -#: backend/redis_dts/exceptions.py:24 backend/redis_dts/exceptions.py:30 #, python-brace-format msgid "{msg}" msgstr "{msg}" @@ -2818,7 +2832,9 @@ msgstr "Access entry request forwarding and IP binding are mixed" #, python-brace-format msgid "" "访问入口 {entry} 绑定到 {bind_cnt} 台机器, 转发到 {forward_to} 不能同时存在" -msgstr "The access entry {entry} is bound to {bind_cnt} machines, forwarded to {forward_to} cannot exist at the same time" +msgstr "" +"The access entry {entry} is bound to {bind_cnt} machines, forwarded to " +"{forward_to} cannot exist at the same time" #: backend/db_meta/exceptions.py:167 #, fuzzy @@ -2866,59 +2882,59 @@ msgstr "Operation and maintenance personnel" msgid "CMDB业务信息缓存表" msgstr "CMDB business information cache table" -#: backend/db_meta/models/cluster.py:40 +#: backend/db_meta/models/cluster.py:41 msgid "集群英文名" msgstr "Cluster English name" -#: backend/db_meta/models/cluster.py:41 +#: backend/db_meta/models/cluster.py:42 #: backend/db_services/bigdata/resources/query.py:41 #: backend/db_services/redis/resources/redis_cluster/query.py:55 msgid "集群别名" msgstr "cluster alias" -#: backend/db_meta/models/cluster.py:46 +#: backend/db_meta/models/cluster.py:47 msgid "主版本号" msgstr "major version number" -#: backend/db_meta/models/cluster.py:50 +#: backend/db_meta/models/cluster.py:51 msgid "地域" msgstr "region" -#: backend/db_meta/models/cluster.py:51 +#: backend/db_meta/models/cluster.py:52 msgid "集群所在的时区" msgstr "The time zone in which the cluster is located" -#: backend/db_meta/models/cluster.py:52 +#: backend/db_meta/models/cluster.py:53 msgid "部署方法ID" msgstr "Deployment Method ID" -#: backend/db_meta/models/cluster.py:94 +#: backend/db_meta/models/cluster.py:95 msgid "当前操作「{}」与集群{}的操作「{}」存在执行互斥" msgstr "" "Execution mutual exclusion exists between the current operation {} and the " "operation {} of the cluster {}" -#: backend/db_meta/models/cluster.py:102 +#: backend/db_meta/models/cluster.py:103 msgid "集群运行状态异常,请检查!" msgstr "The cluster running status is abnormal, please check!" -#: backend/db_meta/models/cluster.py:105 +#: backend/db_meta/models/cluster.py:106 msgid "集群已被禁用,请先启用!" msgstr "The cluster has been disabled, please enable it first!" -#: backend/db_meta/models/cluster.py:151 +#: backend/db_meta/models/cluster.py:152 msgid "{} 未实现 status flag" msgstr "{} unimplemented status flag" -#: backend/db_meta/models/cluster.py:171 +#: backend/db_meta/models/cluster.py:172 msgid "{} 未实现 main_storage_instance" msgstr "{} main_storage_instance is not implemented" -#: backend/db_meta/models/cluster.py:195 +#: backend/db_meta/models/cluster.py:196 msgid "{} 类型集群没有中控节点" msgstr "{} type cluster has no central control node" -#: backend/db_meta/models/cluster.py:212 +#: backend/db_meta/models/cluster.py:216 msgid "find primary show slave status failed: {}" msgstr "find primary show slave status failed: {}" @@ -2957,9 +2973,9 @@ msgid "分组ID" msgstr "Group ID" #: backend/db_meta/models/group.py:35 -#: backend/ticket/builders/common/bigdata.py:205 -#: backend/ticket/builders/common/bigdata.py:271 -#: backend/ticket/models/ticket.py:294 backend/ticket/serializers.py:225 +#: backend/ticket/builders/common/bigdata.py:209 +#: backend/ticket/builders/common/bigdata.py:275 +#: backend/ticket/models/ticket.py:300 backend/ticket/serializers.py:225 msgid "实例ID" msgstr "Instance ID" @@ -2975,26 +2991,25 @@ msgstr "Instance structure and state changes, please wait!" msgid "实例运行状态异常,请检查!" msgstr "The running status of the instance is abnormal, please check!" -#: backend/db_meta/models/instance.py:83 backend/db_meta/models/instance.py:150 +#: backend/db_meta/models/instance.py:83 backend/db_meta/models/instance.py:157 #: backend/db_package/models.py:26 -#: backend/ticket/builders/common/bigdata.py:111 +#: backend/ticket/builders/common/bigdata.py:115 #: backend/ticket/builders/influxdb/influxdb_apply.py:31 #: backend/ticket/builders/redis/redis_cluster_apply.py:37 msgid "版本号" msgstr "version number" #: backend/db_meta/models/instance.py:100 -#: backend/db_meta/models/instance.py:168 +#: backend/db_meta/models/instance.py:175 msgid "实例所在的时区" msgstr "The time zone where the instance is located" #: backend/db_meta/models/instance.py:101 -#: backend/db_meta/models/instance.py:169 +#: backend/db_meta/models/instance.py:176 msgid "对应在cc的服务实例的id" msgstr "The id corresponding to the service instance in cc" #: backend/db_meta/models/instance.py:102 -#: backend/db_meta/models/storage_instance_ext.py:27 msgid "多 slave 的备选标志" msgstr "Alternate flag for multiple slaves" @@ -3034,7 +3049,9 @@ msgstr "Actual machine type: ['class1','class2']" #: backend/db_meta/models/spec.py:34 msgid "存储磁盘需求配置:{'mount_point':'/data','size':500,'type':'ssd'}" -msgstr "Storage disk requirements configuration: {'mount_point':'/data','size':500,'type':'ssd'}" +msgstr "" +"Storage disk requirements configuration: {'mount_point':'/" +"data','size':500,'type':'ssd'}" #: backend/db_meta/models/spec.py:35 backend/db_meta/models/spec.py:97 msgid "资源规格描述" @@ -3209,7 +3226,7 @@ msgstr "dash board" #: backend/db_services/mysql/remote_service/serializers.py:36 #: backend/db_services/partition/serializers.py:44 #: backend/db_services/partition/serializers.py:98 -#: backend/ticket/builders/common/bigdata.py:66 +#: backend/ticket/builders/common/bigdata.py:70 #: backend/ticket/builders/mysql/base.py:165 #: backend/ticket/builders/mysql/mysql_checksum.py:37 #: backend/ticket/builders/mysql/mysql_data_repair.py:28 @@ -3464,9 +3481,9 @@ msgstr "cluster name" #: backend/ticket/builders/cloud/service_apply.py:40 #: backend/ticket/builders/cloud/service_apply.py:49 #: backend/ticket/builders/common/base.py:29 -#: backend/ticket/builders/common/bigdata.py:113 -#: backend/ticket/builders/common/bigdata.py:207 -#: backend/ticket/builders/common/bigdata.py:273 +#: backend/ticket/builders/common/bigdata.py:117 +#: backend/ticket/builders/common/bigdata.py:211 +#: backend/ticket/builders/common/bigdata.py:277 #: backend/ticket/builders/influxdb/influxdb_apply.py:37 #: backend/ticket/builders/mysql/mysql_partition.py:48 #: backend/ticket/builders/mysql/mysql_single_apply.py:46 @@ -3574,8 +3591,9 @@ msgstr "logical city name" #: backend/db_proxy/views/db_meta/serializers.py:92 #: backend/db_services/mysql/resources/tendbsingle/query.py:40 +#: backend/ticket/handler.py:64 msgid "实例" -msgstr "example" +msgstr "instance" #: backend/db_proxy/views/db_meta/serializers.py:93 #: backend/db_services/mysql/cluster/serializers.py:62 @@ -3692,8 +3710,8 @@ msgstr "[dbmeta] fake reset dbha cluster" #: backend/db_proxy/views/gcs_dns/serializers.py:86 #: backend/db_services/mysql/cluster/serializers.py:45 #: backend/db_services/mysql/instance/serializers.py:42 -#: backend/ticket/builders/common/bigdata.py:209 -#: backend/ticket/builders/common/bigdata.py:275 +#: backend/ticket/builders/common/bigdata.py:213 +#: backend/ticket/builders/common/bigdata.py:279 msgid "实例列表" msgstr "instance list" @@ -4109,7 +4127,7 @@ msgstr "DTS_server IP" #: backend/db_proxy/views/redis_dts/serializers.py:34 #: backend/db_proxy/views/redis_dts/serializers.py:93 #: backend/db_proxy/views/redis_dts/serializers.py:99 -#: backend/redis_dts/serializers.py:23 +#: backend/db_services/redis_dts/serializers.py:23 msgid "任务ID" msgstr "task ID" @@ -4117,9 +4135,9 @@ msgstr "task ID" #: backend/db_proxy/views/redis_dts/serializers.py:35 #: backend/db_proxy/views/redis_dts/serializers.py:94 #: backend/db_proxy/views/redis_dts/serializers.py:100 -#: backend/redis_dts/models/tb_tendis_dts_job.py:43 -#: backend/redis_dts/models/tb_tendis_dts_task.py:24 -#: backend/redis_dts/serializers.py:24 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:43 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:24 +#: backend/db_services/redis_dts/serializers.py:24 #, fuzzy #| msgid "集群" msgid "源集群" @@ -4131,14 +4149,15 @@ msgstr "cluster" #: backend/db_proxy/views/redis_dts/serializers.py:101 #: backend/db_services/mysql/permission/authorize/models.py:28 #: backend/db_services/mysql/permission/authorize/serializers.py:28 -#: backend/redis_dts/serializers.py:25 +#: backend/db_services/redis_dts/serializers.py:25 msgid "目标集群" msgstr "target cluster" #: backend/db_proxy/views/redis_dts/serializers.py:41 #: backend/db_proxy/views/redis_dts/serializers.py:47 #: backend/db_proxy/views/redis_dts/serializers.py:114 -#: backend/redis_dts/serializers.py:30 backend/redis_dts/serializers.py:36 +#: backend/db_services/redis_dts/serializers.py:30 +#: backend/db_services/redis_dts/serializers.py:36 #, fuzzy #| msgid "动作ID列表" msgid "子任务ID列表" @@ -4147,8 +4166,8 @@ msgstr "action id list" #: backend/db_proxy/views/redis_dts/serializers.py:49 #: backend/db_services/dbconfig/serializers.py:27 #: backend/db_services/dbresource/serializers.py:144 -#: backend/redis_dts/serializers.py:38 backend/ticket/serializers.py:220 -#: backend/ticket/serializers.py:228 +#: backend/db_services/redis_dts/serializers.py:38 +#: backend/ticket/serializers.py:220 backend/ticket/serializers.py:228 msgid "操作类型" msgstr "operation type" @@ -4180,7 +4199,7 @@ msgid "task类型列表" msgstr "Get a list of ticket types" #: backend/db_proxy/views/redis_dts/serializers.py:80 -#: backend/redis_dts/models/tb_tendis_dts_task.py:52 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:52 msgid "task类型" msgstr "task type" @@ -4189,8 +4208,8 @@ msgid "限制条数" msgstr "limit number" #: backend/db_proxy/views/redis_dts/serializers.py:82 -#: backend/redis_dts/models/tb_tendis_dts_job.py:55 -#: backend/redis_dts/models/tb_tendis_dts_task.py:65 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:55 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:65 #, fuzzy #| msgid "查询任务状态" msgid "任务状态" @@ -4221,7 +4240,8 @@ msgstr "Subtask ID" msgid "dtsserver是否在黑名单中" msgstr "Is dtsserver in the blacklist" -#: backend/db_proxy/views/redis_dts/views.py:77 backend/redis_dts/views.py:32 +#: backend/db_proxy/views/redis_dts/views.py:77 +#: backend/db_services/redis_dts/views.py:32 msgid "获取DTS历史任务以及其对应task cnt" msgstr "Get DTS historical tasks and their corresponding task cnt" @@ -4231,27 +4251,35 @@ msgstr "Get DTS historical tasks and their corresponding task cnt" msgid "获取dts任务详情" msgstr "Query task details" -#: backend/db_proxy/views/redis_dts/views.py:99 backend/redis_dts/views.py:43 +#: backend/db_proxy/views/redis_dts/views.py:99 +#: backend/db_services/redis_dts/views.py:43 msgid "获取迁移任务task列表,失败的排在前面" msgstr "Get the list of migration tasks, the failed ones are listed first" -#: backend/db_proxy/views/redis_dts/views.py:109 backend/redis_dts/views.py:54 +#: backend/db_proxy/views/redis_dts/views.py:109 +#: backend/db_services/redis_dts/views.py:54 msgid "" "dts task操作,目前支持 同步完成(syncStopTodo)、强制终止(ForceKillTaskTodo) 两" "个操作" -msgstr "The dts task operation currently supports two operations: synchronous completion (syncStopTodo) and forced termination (ForceKillTaskTodo)" +msgstr "" +"The dts task operation currently supports two operations: synchronous " +"completion (syncStopTodo) and forced termination (ForceKillTaskTodo)" -#: backend/db_proxy/views/redis_dts/views.py:121 backend/redis_dts/views.py:65 +#: backend/db_proxy/views/redis_dts/views.py:121 +#: backend/db_services/redis_dts/views.py:65 msgid "dts tasks重新开始" msgstr "dts tasks restart" -#: backend/db_proxy/views/redis_dts/views.py:131 backend/redis_dts/views.py:76 +#: backend/db_proxy/views/redis_dts/views.py:131 +#: backend/db_services/redis_dts/views.py:76 msgid "dts tasks重试当前步骤" msgstr "dts tasks retry current step" #: backend/db_proxy/views/redis_dts/views.py:141 msgid "dts 分布式锁,trylock,成功返回True,失败返回False" -msgstr "dts distributed lock, trylock, returns True on success, returns False on failure" +msgstr "" +"dts distributed lock, trylock, returns True on success, returns False on " +"failure" #: backend/db_proxy/views/redis_dts/views.py:156 msgid "dts 分布式锁,unlock" @@ -4267,7 +4295,9 @@ msgstr "Get the task with the largest syncPort on DtsServer" #: backend/db_proxy/views/redis_dts/views.py:201 msgid "获取最近30天内task_type类型的等待执行的tasks" -msgstr "Obtain the tasks waiting to be executed of the task_type type in the last 30 days" +msgstr "" +"Obtain the tasks waiting to be executed of the task_type type in the last 30 " +"days" #: backend/db_proxy/views/redis_dts/views.py:216 msgid "获取最近30天内的等待调度的jobs" @@ -4606,8 +4636,8 @@ msgid "实例地址(ip:port)" msgstr "Instance address (ip:port)" #: backend/db_services/dbbase/resources/serializers.py:48 -#: backend/ticket/builders/common/bigdata.py:202 -#: backend/ticket/builders/common/bigdata.py:269 +#: backend/ticket/builders/common/bigdata.py:206 +#: backend/ticket/builders/common/bigdata.py:273 msgid "IP" msgstr "IP" @@ -4984,8 +5014,8 @@ msgstr "host ID" #: backend/db_services/mysql/cluster/serializers.py:42 #: backend/db_services/mysql/instance/serializers.py:39 #: backend/ticket/builders/common/base.py:31 -#: backend/ticket/builders/common/bigdata.py:206 -#: backend/ticket/builders/common/bigdata.py:272 +#: backend/ticket/builders/common/bigdata.py:210 +#: backend/ticket/builders/common/bigdata.py:276 msgid "主机ID" msgstr "host ID" @@ -5071,7 +5101,8 @@ msgstr "update{} deployment scheme" #: backend/db_services/dbresource/views/deploy_plan.py:50 msgid "部署方案: {} 正在被引用,无法修改相关参数" -msgstr "Deployment plan: {} is being referenced, cannot modify related parameters" +msgstr "" +"Deployment plan: {} is being referenced, cannot modify related parameters" #: backend/db_services/dbresource/views/deploy_plan.py:54 msgid "查询{}部署方案列表" @@ -5104,7 +5135,7 @@ msgid "查询资源导入任务" msgstr "Query resource import tasks" #: backend/db_services/dbresource/views/resource.py:182 -#: backend/ticket/builders/__init__.py:333 backend/ticket/constants.py:322 +#: backend/ticket/builders/__init__.py:333 backend/ticket/constants.py:323 msgid "资源申请" msgstr "resource application" @@ -5142,7 +5173,9 @@ msgstr "Specifications: {} has been quoted, only extended models are allowed" #: backend/db_services/dbresource/views/sepc.py:74 msgid "规格: {}已经被引用,无法修改配置!(只允许拓展机型和修改描述)" -msgstr "Specification: {} has been referenced, cannot modify the configuration! (Only allow to expand the model and modify the description)" +msgstr "" +"Specification: {} has been referenced, cannot modify the configuration! " +"(Only allow to expand the model and modify the description)" #: backend/db_services/dbresource/views/sepc.py:79 #, fuzzy @@ -5253,10 +5286,10 @@ msgid "标准型S5" msgstr "Standard S5" #: backend/db_services/infras/serializers.py:56 -#: backend/ticket/builders/common/bigdata.py:85 -#: backend/ticket/builders/common/bigdata.py:112 -#: backend/ticket/builders/common/bigdata.py:165 -#: backend/ticket/builders/common/bigdata.py:286 +#: backend/ticket/builders/common/bigdata.py:89 +#: backend/ticket/builders/common/bigdata.py:116 +#: backend/ticket/builders/common/bigdata.py:169 +#: backend/ticket/builders/common/bigdata.py:290 #: backend/ticket/builders/influxdb/influxdb_apply.py:32 #: backend/ticket/builders/mysql/mysql_single_apply.py:57 #: backend/ticket/builders/pulsar/pulsar_shrink.py:31 @@ -5398,6 +5431,10 @@ msgstr "free machine pool" msgid "空闲机" msgstr "idle machine" +#: backend/db_services/ipchooser/query/resource.py:467 +msgid "直连区域" +msgstr "Direct Mode" + #: backend/db_services/ipchooser/serializers/base.py:18 msgid "数据起始位置" msgstr "data starting position" @@ -5591,8 +5628,8 @@ msgstr "IP address" #: backend/db_services/mysql/cluster/serializers.py:43 #: backend/db_services/mysql/instance/serializers.py:40 #: backend/ticket/builders/common/base.py:36 -#: backend/ticket/builders/common/bigdata.py:203 -#: backend/ticket/builders/common/bigdata.py:270 +#: backend/ticket/builders/common/bigdata.py:207 +#: backend/ticket/builders/common/bigdata.py:274 msgid "端口号" msgstr "The port number" @@ -5683,7 +5720,7 @@ msgstr "Interface call exception {}" #: backend/db_services/mysql/permission/authorize/models.py:24 #: backend/db_services/mysql/permission/clone/models.py:25 #: backend/ticket/models/ticket.py:45 backend/ticket/models/ticket.py:247 -#: backend/ticket/models/ticket.py:297 backend/ticket/models/todo.py:32 +#: backend/ticket/models/ticket.py:303 backend/ticket/models/todo.py:32 msgid "关联工单" msgstr "Associated work order" @@ -6634,1616 +6671,2000 @@ msgstr "Regex-based" msgid "基于文件" msgstr "file based" -#: backend/db_services/taskflow/exceptions.py:18 -msgid "任务流程模块异常" -msgstr "Task process module exception" +#: backend/db_services/redis_dts/constants.py:19 +msgid "tendis ssd备份任务" +msgstr "tendis ssd backup task" -#: backend/db_services/taskflow/exceptions.py:23 -msgid "重试节点异常" -msgstr "retry node exception" +#: backend/db_services/redis_dts/constants.py:20 +msgid "tendis ssd备份拉取任务" +msgstr "tendis ssd backup pull task" -#: backend/db_services/taskflow/exceptions.py:28 -msgid "回调节点异常" -msgstr "callback node exception" +#: backend/db_services/redis_dts/constants.py:21 +msgid "tendis ssd备份解析任务" +msgstr "Tendis ssd backup analysis task" -#: backend/db_services/taskflow/exceptions.py:33 -msgid "跳过节点异常" -msgstr "skip node exception" +#: backend/db_services/redis_dts/constants.py:22 +msgid "tendis ssd数据导入任务" +msgstr "Tendis ssd data import task" -#: backend/db_services/taskflow/exceptions.py:38 -msgid "强制失败节点异常" -msgstr "Force failure node exception" +#: backend/db_services/redis_dts/constants.py:23 +msgid "tendis ssd拉起sync任务" +msgstr "Tendis ssd pulls up the sync task" -#: backend/db_services/taskflow/exceptions.py:43 -msgid "撤销流程异常" -msgstr "Abnormal cancellation process" +#: backend/db_services/redis_dts/constants.py:24 +#: backend/db_services/redis_dts/constants.py:28 +msgid "tendis ssd监视sync任务" +msgstr "Tendis ssd monitor sync task" -#: backend/db_services/taskflow/handlers.py:78 -msgid "人工强制失败" -msgstr "Manual forced failure" +#: backend/db_services/redis_dts/constants.py:27 +msgid "redis cache拉起redis-shake任务" +msgstr "Redis cache pulls up the redis-shake task" -#: backend/db_services/taskflow/handlers.py:125 -msgid "节点尚未运行,请稍后查看" -msgstr "The node is not running yet, please check later" +#: backend/db_services/redis_dts/constants.py:31 +msgid "tendisplus拉起reids-sync任务" +msgstr "Tendisplus pulls up the reids-sync task" -#: backend/db_services/taskflow/handlers.py:127 -msgid "节点日志仅保留7天" -msgstr "Node logs are only kept for 7 days" +#: backend/db_services/redis_dts/constants.py:33 +#, fuzzy +#| msgid "tendisplus实例安装 元数据" +msgid "tendisplus全量数据同步" +msgstr "Tendisplus instance installation metadata" -#: backend/db_services/taskflow/handlers.py:152 -msgid "日志上报中,请稍后查看" -msgstr "The log is being reported, please check it later" +#: backend/db_services/redis_dts/constants.py:34 +#, fuzzy +#| msgid "tendisplus实例安装 元数据" +msgid "tendisplus增量数据同步" +msgstr "Tendisplus instance installation metadata" -#: backend/db_services/taskflow/serializers.py:21 -#: backend/ticket/serializers.py:73 -msgid "单据类型名称" -msgstr "ticket type name" +#: backend/db_services/redis_dts/constants.py:40 +msgid "停止数据同步todo" +msgstr "stop data sync todo" -#: backend/db_services/taskflow/serializers.py:22 -#: backend/ticket/serializers.py:75 backend/ticket/serializers.py:113 -#: backend/ticket/serializers.py:166 -msgid "耗时" -msgstr "time consuming" +#: backend/db_services/redis_dts/constants.py:41 +msgid "停止数据同步失败" +msgstr "Failed to stop data sync" -#: backend/db_services/taskflow/serializers.py:48 backend/flow/models.py:39 -msgid "节点ID" -msgstr "Node ID" +#: backend/db_services/redis_dts/constants.py:42 +msgid "停止数据同步成功" +msgstr "Stop data synchronization successfully" -#: backend/db_services/taskflow/serializers.py:52 -msgid "回调描述" -msgstr "callback description" +#: backend/db_services/redis_dts/constants.py:44 +msgid "强制暂停任务todo" +msgstr "Forcibly suspend task todo" -#: backend/db_services/taskflow/serializers.py:56 -msgid "版本ID" -msgstr "version ID" +#: backend/db_services/redis_dts/constants.py:45 +#, fuzzy +#| msgid "创建模拟任务失败!" +msgid "强制暂停任务失败" +msgstr "Failed to create simulation task!" -#: backend/db_services/taskflow/serializers.py:57 -msgid "是否下载日志" -msgstr "Whether to download logs" +#: backend/db_services/redis_dts/constants.py:46 +#, fuzzy +#| msgid "创建模拟任务成功" +msgid "强制暂停任务成功" +msgstr "Create mock task successfully" -#: backend/db_services/taskflow/serializers.py:67 -msgid "目标目录列表" -msgstr "target directory listing" +#: backend/db_services/redis_dts/constants.py:52 +#, fuzzy +#| msgid "获取集群部署配置" +msgid "集群节点数变更" +msgstr "Get cluster deployment configuration" -#: backend/db_services/taskflow/task.py:54 -msgid "存在执行互斥,正在进行重试,当前重试次数为{}" -msgstr "" -"There is an execution mutex, and retrying is in progress, and the current " -"number of retries is {}" +#: backend/db_services/redis_dts/constants.py:53 +#, fuzzy +#| msgid "集群类型" +msgid "集群类型变更" +msgstr "cluster type" -#: backend/db_services/taskflow/task.py:58 -msgid "自动重试次数已超过最大重试次数{}, 请重新手动重试" -msgstr "" -"The number of automatic retries has exceeded the maximum number of retries " -"{}, please try again manually" +#: backend/db_services/redis_dts/constants.py:54 +msgid "数据复制" +msgstr "data replication" -#: backend/db_services/taskflow/task.py:72 -msgid "执行互斥错误信息: {}" -msgstr "Execution mutex error message: {}" +#: backend/db_services/redis_dts/constants.py:60 +msgid "同一业务不同集群" +msgstr "Different clusters of the same business" -#: backend/db_services/taskflow/task.py:79 -msgid "存在执行互斥将自动进行重试..." -msgstr "Execution mutexes will automatically be retried..." +#: backend/db_services/redis_dts/constants.py:61 +msgid "不同业务不同集群" +msgstr "Different business clusters" -#: backend/db_services/taskflow/task.py:89 -msgid "重试成功" -msgstr "successful retry" +#: backend/db_services/redis_dts/constants.py:62 +msgid "复制到其他系统" +msgstr "copy to other system" -#: backend/db_services/taskflow/views/flow.py:61 -msgid "任务列表" -msgstr "task list" +#: backend/db_services/redis_dts/constants.py:63 +msgid "从回档临时环境复制数据" +msgstr "Copy data from the archive staging environment" -#: backend/db_services/taskflow/views/flow.py:68 -#, fuzzy -#| msgid "查询任务详情" -msgid "任务详情" -msgstr "Query task details" +#: backend/db_services/redis_dts/constants.py:64 +msgid "用户自建redis迁移到DBM" +msgstr "Migrating user-built redis to DBM" -#: backend/db_services/taskflow/views/flow.py:78 -#, fuzzy -#| msgid "撤销流程异常" -msgid "撤销流程" -msgstr "Abnormal cancellation process" +#: backend/db_services/redis_dts/constants.py:70 +msgid "自动切换" +msgstr "auto switch" -#: backend/db_services/taskflow/views/flow.py:87 -#, fuzzy -#| msgid "重试节点异常" -msgid "重试节点" -msgstr "retry node exception" +#: backend/db_services/redis_dts/constants.py:71 +msgid "用户确认切换" +msgstr "User confirmation switch" -#: backend/db_services/taskflow/views/flow.py:94 -msgid "非超级用户,暂不允许调用此接口" -msgstr "Non-super users are not allowed to call this interface" +#: backend/db_services/redis_dts/constants.py:77 +#: backend/ticket/builders/common/constants.py:79 +msgid "自动修复" +msgstr "automatic repair" -#: backend/db_services/taskflow/views/flow.py:101 +#: backend/db_services/redis_dts/constants.py:78 +msgid "用户确认修复" +msgstr "User confirms the fix" + +#: backend/db_services/redis_dts/exceptions.py:18 #, fuzzy -#| msgid "跳过节点异常" -msgid "跳过节点" -msgstr "skip node exception" +#| msgid "DBMeta模块异常" +msgid "DBDts模块异常" +msgstr "DBMeta module exception" -#: backend/db_services/taskflow/views/flow.py:111 +#: backend/db_services/redis_dts/exceptions.py:23 #, fuzzy -#| msgid "强制失败节点异常" -msgid "强制失败节点" -msgstr "Force failure node exception" +#| msgid "任务列表" +msgid "获取DTS任务列表异常" +msgstr "task list" -#: backend/db_services/taskflow/views/flow.py:121 -msgid "节点版本列表" -msgstr "List of node versions" +#: backend/db_services/redis_dts/exceptions.py:29 +msgid "DTS task操作异常" +msgstr "DTS task operation is abnormal" -#: backend/db_services/taskflow/views/flow.py:132 +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:17 #, fuzzy -#| msgid "节点日志仅保留7天" -msgid "节点日志" -msgstr "Node logs are only kept for 7 days" +#| msgid "关键字唯一标识" +msgid "锁的唯一标识" +msgstr "Keyword Unique Identifier" -#: backend/db_services/taskflow/views/flow.py:154 -#, fuzzy -#| msgid "回调节点异常" -msgid "回调节点" -msgstr "callback node exception" +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:18 +msgid "锁的持有者" +msgstr "lock holder" -#: backend/db_services/taskflow/views/redis.py:49 +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:20 +msgid "锁的过期时间" +msgstr "lock expiration time" + +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:17 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:19 #, fuzzy -#| msgid "sql文件列表" -msgid "结果文件列表" -msgstr "sql file list" +#| msgid "单据" +msgid "单据号" +msgstr "tickets" -#: backend/db_services/taskflow/views/redis.py:94 -msgid "打包下载结果文件列表" -msgstr "Package download result file list" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:18 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:21 +msgid "业务bk_biz_id" +msgstr "Business bk_biz_id" -#: backend/db_services/taskflow/views/redis.py:122 -msgid "指定目录下载(返回下载链接)" -msgstr "Specify directory to download (return to download link)" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:19 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:22 +msgid "云区域id" +msgstr "cloud region id" -#: backend/db_services/user/serializers.py:16 -msgid "模糊搜索" -msgstr "fuzzy search" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:20 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:20 +msgid "申请人" +msgstr "applicant" -#: backend/db_services/user/serializers.py:18 -msgid "不分页,即将下架,请不要使用,并尽快迁移" -msgstr "" -"No pagination, it will be discontinued soon, please do not use it, and " -"migrate as soon as possible" - -#: backend/db_services/version/constants.py:23 -msgid "MySQL-5.6" -msgstr "MySQL-5.6" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:25 +#, fuzzy +#| msgid "单据类型" +msgid "DTS单据类型" +msgstr "Ticket Type" -#: backend/db_services/version/constants.py:24 -msgid "MySQL-5.7" -msgstr "MySQL-5.7" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:32 +msgid "DTS数据复制类型" +msgstr "DTS data replication type" -#: backend/db_services/version/constants.py:25 -msgid "MySQL-8.0" -msgstr "MySQL-8.0" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:36 +msgid "在线切换类型" +msgstr "Online switch type" -#: backend/db_services/version/constants.py:31 -msgid "Redis-6" -msgstr "Redis-6" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:37 +#, fuzzy +#| msgid "数据校验执行" +msgid "是否数据校验" +msgstr "Data validation execution" -#: backend/db_services/version/constants.py:37 -msgid "Tendisplus-2.5" -msgstr "Tendisplus-2.5" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:38 +msgid "是否数据修复" +msgstr "Data repair Execution" -#: backend/db_services/version/constants.py:38 -#, fuzzy -#| msgid "Tendisplus-2.5" -msgid "Tendisplus-2.6" -msgstr "Tendisplus-2.5" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:42 +msgid "数据修复模式" +msgstr "Data Repair Mode" -#: backend/db_services/version/constants.py:44 -msgid "TendisSSD-1.2" -msgstr "TendisSSD-1.2" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:45 +msgid "源集群类型" +msgstr "source cluster type" -#: backend/db_services/version/constants.py:45 -msgid "TendisSSD-1.3" -msgstr "TendisSSD-1.3" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:46 +msgid "回滚单据号" +msgstr "Rollback document number" -#: backend/db_services/version/constants.py:51 -msgid "TwemproxyLatest" -msgstr "TwemproxyLatest" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:47 +msgid "回滚临时环境实例" +msgstr "Rollback a temporary environment instance" -#: backend/db_services/version/constants.py:57 -msgid "PredixyLatest" -msgstr "PredixyLatest" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:48 +msgid "目标业务id" +msgstr "target business id" -#: backend/db_services/version/serializers.py:20 -msgid "查询关键字" -msgstr "query keywords" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:49 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:49 +msgid "目的集群" +msgstr "destination cluster" -#: backend/db_services/version/views.py:27 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:51 #, fuzzy -#| msgid "数据库版本" -msgid "查询数据库版本列表" -msgstr "database version" +#| msgid "集群类型" +msgid "目标集群类型" +msgstr "cluster type" -#: backend/exceptions.py:48 -msgid "系统异常" -msgstr "System exception" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:52 +msgid "key正则(包含key)" +msgstr "key regular (including key)" -#: backend/exceptions.py:103 -msgid "系统错误" -msgstr "system error" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:53 +msgid "key正则(排除key)" +msgstr "key regularization (exclude key)" -#: backend/exceptions.py:113 -msgid "参数验证失败" -msgstr "Parameter validation failed" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:56 +msgid "bill备注" +msgstr "Bill Remarks" -#: backend/exceptions.py:118 -msgid "远程服务请求结果异常" -msgstr "The result of the remote service request is abnormal" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:23 +msgid "执行迁移任务的dts_server" +msgstr "dts_server that executes migration tasks" -#: backend/exceptions.py:123 -msgid "组件调用异常" -msgstr "Component call exception" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:25 +msgid "源集群优先级,值越大,优先级越高" +msgstr "Source cluster priority, the larger the value, the higher the priority" -#: backend/exceptions.py:128 -msgid "业务不存在" -msgstr "business does not exist" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:26 +msgid "源slave_ip" +msgstr "source slave ip" -#: backend/exceptions.py:133 -msgid "语言不支持" -msgstr "language not supported" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:27 +msgid "源slave_port" +msgstr "source slave_port" -#: backend/exceptions.py:138 -msgid "权限不足" -msgstr "Insufficient permissions" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:28 +msgid "源实例密码base64值" +msgstr "Source instance password base64 value" -#: backend/exceptions.py:165 -msgid "服务不稳定,请检查组件健康状况" -msgstr "The service is unstable, please check the component health status" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:30 +msgid "源slave db类型" +msgstr "Source slave db type" -#: backend/flow/consts.py:101 -msgid "创建态" -msgstr "creation state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:32 +msgid "源实例数据量大小,单位Byte" +msgstr "Source instance data size, unit Byte" -#: backend/flow/consts.py:102 -msgid "准备态" -msgstr "ready state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:34 +msgid "源实例所属segment_start" +msgstr "The segment_start to which the source instance belongs" -#: backend/flow/consts.py:103 -msgid "运行态" -msgstr "running state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:35 +msgid "源实例所属segment_end" +msgstr "The segment_end to which the source instance belongs" -#: backend/flow/consts.py:104 -msgid "暂停态" -msgstr "pause state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:37 +msgid "源实例权重" +msgstr "Source Instance Weight" -#: backend/flow/consts.py:105 -msgid "闭塞态" -msgstr "Blocked state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:39 +msgid "源slave_ip上task并发数控制" +msgstr "Task concurrency control on the source slave_ip" -#: backend/flow/consts.py:106 -msgid "完成态" -msgstr "Completion" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:40 +msgid "源实例所在城市" +msgstr "The time zone where the instance is located" -#: backend/flow/consts.py:107 -msgid "失败态" -msgstr "failure state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:42 +msgid "源实例slave-keep-log-count的旧值" +msgstr "Old value of source instance slave-keep-log-count" -#: backend/flow/consts.py:108 -msgid "取消态" -msgstr "cancel state" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:43 +msgid "源实例slave-keep-log-count的新值" +msgstr "The new value of the source instance slave-keep-log-count" -#: backend/flow/consts.py:116 -msgid "共用参数" -msgstr "Shared parameters" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:44 +msgid "源实例slave-keep-log-count是否恢复" +msgstr "Whether the source instance slave-keep-log-count is restored" -#: backend/flow/consts.py:117 -msgid "redis共用参数" -msgstr "redis shared parameters" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:45 +msgid "srcRedis是否包含list类型key" +msgstr "Whether srcRedis contains list type key" -#: backend/flow/consts.py:118 -msgid "TenDBHA" -msgstr "TenDBHA" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:46 +msgid "包含key(正则)" +msgstr "Contains key (regular)" -#: backend/flow/consts.py:119 -msgid "RedisCache 主从版" -msgstr "RedisCache master-slave version" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:47 +msgid "排除key(正则)" +msgstr "Exclude key (regular)" -#: backend/flow/consts.py:120 -msgid "twemproxy + RedisInstance架构" -msgstr "twemproxy + RedisInstance architecture" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:50 +msgid "目的密码base64值" +msgstr "Destination password base64 value" -#: backend/flow/consts.py:121 -msgid "predixy + tendisplus架构" -msgstr "predixy + tendisplus architecture" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:53 +msgid "tendisssd slave上bakup文件位置" +msgstr "bakup file location on tendisssd slave" -#: backend/flow/consts.py:122 -msgid "Es" -msgstr "Es" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:54 +msgid "backup文件拉取到dts_server本地位置" +msgstr "The backup file is pulled to the local location of dts_server" -#: backend/flow/consts.py:123 -msgid "tendb" -msgstr "tendb" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:55 +msgid "tendisdumper得到的sql文件夹" +msgstr "The sql folder obtained by tendisdumper" -#: backend/flow/consts.py:125 -msgid "Hdfs" -msgstr "Hdfs" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:56 +msgid "redis-sync端口" +msgstr "redis-sync port" -#: backend/flow/consts.py:127 -#, fuzzy -#| msgid "InfluxDB" -msgid "Influxdb" -msgstr "InfluxDB" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:57 +msgid "sync的进程id" +msgstr "sync process id" -#: backend/flow/consts.py:132 -msgid "初始化帐户" -msgstr "Initialize account" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:59 +msgid "task重试次数" +msgstr "task retries" -#: backend/flow/consts.py:133 -msgid "实例和帐户" -msgstr "instance and account" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:61 +msgid "sync操作" +msgstr "sync operation" -#: backend/flow/consts.py:134 -msgid "系统配置" -msgstr "System Configuration" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:63 +msgid "杀死syncer" +msgstr "kill syncer" -#: backend/flow/consts.py:135 -msgid "实例配置" -msgstr "instance configuration" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:66 +msgid "信息" +msgstr "information" -#: backend/flow/consts.py:136 -msgid "默认配置" -msgstr "default allocation" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:68 +msgid "被忽略的错误" +msgstr "ignored errors" -#: backend/flow/consts.py:137 -msgid "proxyconfig" -msgstr "proxyconfig" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:69 +msgid "sync从该时间点重新同步" +msgstr "sync resynchronizes from this point in time" -#: backend/flow/consts.py:138 -msgid "ES实例配置" -msgstr "ES instance configuration" +#: backend/db_services/taskflow/exceptions.py:18 +msgid "任务流程模块异常" +msgstr "Task process module exception" -#: backend/flow/consts.py:139 -msgid "act配置" -msgstr "act configuration" +#: backend/db_services/taskflow/exceptions.py:23 +msgid "重试节点异常" +msgstr "retry node exception" -#: backend/flow/consts.py:140 -msgid "系统配置类型" -msgstr "system configuration type" +#: backend/db_services/taskflow/exceptions.py:28 +msgid "回调节点异常" +msgstr "callback node exception" -#: backend/flow/consts.py:141 -msgid "Kafka实例配置" -msgstr "Kafka instance configuration" +#: backend/db_services/taskflow/exceptions.py:33 +msgid "跳过节点异常" +msgstr "skip node exception" -#: backend/flow/consts.py:142 -msgid "HDFS集群配置" -msgstr "HDFS cluster configuration" +#: backend/db_services/taskflow/exceptions.py:38 +msgid "强制失败节点异常" +msgstr "Force failure node exception" -#: backend/flow/consts.py:143 -msgid "HDFS实例hdfs-site配置" -msgstr "HDFS instance hdfs-site configuration" +#: backend/db_services/taskflow/exceptions.py:43 +msgid "撤销流程异常" +msgstr "Abnormal cancellation process" -#: backend/flow/consts.py:144 -msgid "HDFS实例core-site配置" -msgstr "HDFS instance core-site configuration" +#: backend/db_services/taskflow/handlers.py:78 +msgid "人工强制失败" +msgstr "Manual forced failure" -#: backend/flow/consts.py:145 -msgid "HDFS实例安装配置" -msgstr "HDFS instance installation configuration" +#: backend/db_services/taskflow/handlers.py:125 +msgid "节点尚未运行,请稍后查看" +msgstr "The node is not running yet, please check later" -#: backend/flow/consts.py:149 -msgid "系统" -msgstr "system" +#: backend/db_services/taskflow/handlers.py:127 +msgid "节点日志仅保留7天" +msgstr "Node logs are only kept for 7 days" -#: backend/flow/consts.py:150 -msgid "twemproxy config file" -msgstr "twemproxy config file" +#: backend/db_services/taskflow/handlers.py:152 +msgid "日志上报中,请稍后查看" +msgstr "The log is being reported, please check it later" -#: backend/flow/consts.py:151 -msgid "predixy config file" -msgstr "predixy config file" +#: backend/db_services/taskflow/serializers.py:21 +#: backend/ticket/serializers.py:73 +msgid "单据类型名称" +msgstr "ticket type name" -#: backend/flow/consts.py:152 -msgid "redis config file" -msgstr "redis config file" +#: backend/db_services/taskflow/serializers.py:22 +#: backend/ticket/serializers.py:75 backend/ticket/serializers.py:113 +#: backend/ticket/serializers.py:166 +msgid "耗时" +msgstr "time consuming" -#: backend/flow/consts.py:153 -msgid "全备配置" -msgstr "full configuration" +#: backend/db_services/taskflow/serializers.py:48 backend/flow/models.py:39 +msgid "节点ID" +msgstr "Node ID" -#: backend/flow/consts.py:154 -msgid "增备配置" -msgstr "Additional configuration" +#: backend/db_services/taskflow/serializers.py:52 +msgid "回调描述" +msgstr "callback description" -#: backend/flow/consts.py:155 -msgid "心跳配置" -msgstr "heartbeat configuration" +#: backend/db_services/taskflow/serializers.py:56 +msgid "版本ID" +msgstr "version ID" -#: backend/flow/consts.py:156 -msgid "监控配置" -msgstr "monitoring configuration" +#: backend/db_services/taskflow/serializers.py:57 +msgid "是否下载日志" +msgstr "Whether to download logs" -#: backend/flow/consts.py:157 -msgid "基本配置" -msgstr "basic configuration" +#: backend/db_services/taskflow/serializers.py:67 +msgid "目标目录列表" +msgstr "target directory listing" -#: backend/flow/consts.py:158 -msgid "热key配置" -msgstr "Hot key configuration" +#: backend/db_services/taskflow/task.py:54 +msgid "存在执行互斥,正在进行重试,当前重试次数为{}" +msgstr "" +"There is an execution mutex, and retrying is in progress, and the current " +"number of retries is {}" -#: backend/flow/consts.py:159 -msgid "大key配置" -msgstr "Big key configuration" +#: backend/db_services/taskflow/task.py:58 +msgid "自动重试次数已超过最大重试次数{}, 请重新手动重试" +msgstr "" +"The number of automatic retries has exceeded the maximum number of retries " +"{}, please try again manually" -#: backend/flow/consts.py:163 -msgid "MASTER" -msgstr "MASTER" +#: backend/db_services/taskflow/task.py:72 +msgid "执行互斥错误信息: {}" +msgstr "Execution mutex error message: {}" -#: backend/flow/consts.py:164 -msgid "SLAVE" -msgstr "SLAVE" +#: backend/db_services/taskflow/task.py:79 +msgid "存在执行互斥将自动进行重试..." +msgstr "Execution mutexes will automatically be retried..." -#: backend/flow/consts.py:168 backend/flow/consts.py:245 -msgid "mysql" -msgstr "mysql" +#: backend/db_services/taskflow/task.py:89 +msgid "重试成功" +msgstr "successful retry" -#: backend/flow/consts.py:169 -msgid "mysql-proxy" -msgstr "mysql-proxy" +#: backend/db_services/taskflow/views/flow.py:61 +msgid "任务列表" +msgstr "task list" -#: backend/flow/consts.py:173 -msgid "dbbackup" -msgstr "dbbackup" +#: backend/db_services/taskflow/views/flow.py:68 +msgid "任务详情" +msgstr "Task details" -#: backend/flow/consts.py:174 -msgid "actuator" -msgstr "actuator" +#: backend/db_services/taskflow/views/flow.py:78 +msgid "撤销流程" +msgstr "Rollback process" -#: backend/flow/consts.py:175 -msgid "最新版本" -msgstr "The latest version" +#: backend/db_services/taskflow/views/flow.py:87 +msgid "重试节点" +msgstr "retry node" -#: backend/flow/consts.py:178 -msgid "redis_tools" -msgstr "redis_tools" +#: backend/db_services/taskflow/views/flow.py:94 +msgid "非超级用户,暂不允许调用此接口" +msgstr "Non-super users are not allowed to call this interface" -#: backend/flow/consts.py:179 backend/flow/consts.py:251 -msgid "es" -msgstr "es" +#: backend/db_services/taskflow/views/flow.py:101 +#, fuzzy +#| msgid "跳过节点异常" +msgid "跳过节点" +msgstr "skip node exception" -#: backend/flow/consts.py:180 backend/flow/consts.py:252 -msgid "kafka" -msgstr "kafka" +#: backend/db_services/taskflow/views/flow.py:111 +#, fuzzy +#| msgid "强制失败节点异常" +msgid "强制失败节点" +msgstr "Force failure node exception" -#: backend/flow/consts.py:181 backend/flow/consts.py:253 -msgid "hdfs" -msgstr "hdfs" +#: backend/db_services/taskflow/views/flow.py:121 +msgid "节点版本列表" +msgstr "List of node versions" -#: backend/flow/consts.py:182 backend/flow/consts.py:254 +#: backend/db_services/taskflow/views/flow.py:132 #, fuzzy -#| msgid "Pulsar" -msgid "pulsar" -msgstr "Pulsar" - -#: backend/flow/consts.py:184 -msgid "dbmon" -msgstr "dbmon" +#| msgid "节点日志仅保留7天" +msgid "节点日志" +msgstr "Node logs are only kept for 7 days" -#: backend/flow/consts.py:185 -msgid "mysql-checksum" -msgstr "mysql-checksum" +#: backend/db_services/taskflow/views/flow.py:154 +#, fuzzy +#| msgid "回调节点异常" +msgid "回调节点" +msgstr "callback node exception" -#: backend/flow/consts.py:186 -msgid "Binlog 滚动备份工具" -msgstr "Binlog rotate tool" +#: backend/db_services/taskflow/views/redis.py:49 +#, fuzzy +#| msgid "sql文件列表" +msgid "结果文件列表" +msgstr "sql file list" -#: backend/flow/consts.py:187 -msgid "DBA 工具集" -msgstr "DBA toolkit" +#: backend/db_services/taskflow/views/redis.py:94 +msgid "打包下载结果文件列表" +msgstr "Package download result file list" -#: backend/flow/consts.py:188 -msgid "mysql-crond" -msgstr "mysql-crond" +#: backend/db_services/taskflow/views/redis.py:122 +msgid "指定目录下载(返回下载链接)" +msgstr "Specify directory to download (return to download link)" -#: backend/flow/consts.py:189 -#, fuzzy -#| msgid "MySQL 授权" -msgid "MySQL 监控" -msgstr "MySQL Authorization" +#: backend/db_services/user/serializers.py:16 +msgid "模糊搜索" +msgstr "fuzzy search" -#: backend/flow/consts.py:190 -msgid "nginx 服务" -msgstr "nginx service" +#: backend/db_services/user/serializers.py:18 +msgid "不分页,即将下架,请不要使用,并尽快迁移" +msgstr "" +"No pagination, it will be discontinued soon, please do not use it, and " +"migrate as soon as possible" -#: backend/flow/consts.py:191 -msgid "dns-bind 服务" -msgstr "dns-bind service" +#: backend/db_services/version/constants.py:23 +msgid "MySQL-5.6" +msgstr "MySQL-5.6" -#: backend/flow/consts.py:192 -msgid "dns-pull-crond服务" -msgstr "dns-pull-crond service" +#: backend/db_services/version/constants.py:24 +msgid "MySQL-5.7" +msgstr "MySQL-5.7" -#: backend/flow/consts.py:193 -msgid "cloud-dbha服务" -msgstr "cloud-dbha service" +#: backend/db_services/version/constants.py:25 +msgid "MySQL-8.0" +msgstr "MySQL-8.0" -#: backend/flow/consts.py:194 -msgid "cloud-drs服务" -msgstr "cloud-drs service" +#: backend/db_services/version/constants.py:31 +msgid "Redis-6" +msgstr "Redis-6" -#: backend/flow/consts.py:195 -msgid "cloud-drs-tmysqlparse服务" -msgstr "cloud-drs-tmysqlparse service" +#: backend/db_services/version/constants.py:37 +msgid "Tendisplus-2.5" +msgstr "Tendisplus-2.5" -#: backend/flow/consts.py:196 +#: backend/db_services/version/constants.py:38 #, fuzzy -#| msgid "Master节点" -msgid "spider节点名称" -msgstr "Master node" +#| msgid "Tendisplus-2.5" +msgid "Tendisplus-2.6" +msgstr "Tendisplus-2.5" -#: backend/flow/consts.py:197 -msgid "spider中控节点名称" -msgstr "Spider control node name" +#: backend/db_services/version/constants.py:44 +msgid "TendisSSD-1.2" +msgstr "TendisSSD-1.2" -#: backend/flow/consts.py:201 -msgid "nginx服务" -msgstr "nginx-service" +#: backend/db_services/version/constants.py:45 +msgid "TendisSSD-1.3" +msgstr "TendisSSD-1.3" -#: backend/flow/consts.py:202 -msgid "dns服务" -msgstr "dns service" +#: backend/db_services/version/constants.py:51 +msgid "TwemproxyLatest" +msgstr "TwemproxyLatest" -#: backend/flow/consts.py:203 -msgid "drs服务" -msgstr "drs service" +#: backend/db_services/version/constants.py:57 +msgid "PredixyLatest" +msgstr "PredixyLatest" -#: backend/flow/consts.py:204 -msgid "dbha服务" -msgstr "dbha service" +#: backend/db_services/version/serializers.py:20 +msgid "查询关键字" +msgstr "query keywords" -#: backend/flow/consts.py:208 -msgid "pull-crond.conf" -msgstr "pull-crond.conf" +#: backend/db_services/version/views.py:27 +#, fuzzy +#| msgid "数据库版本" +msgid "查询数据库版本列表" +msgstr "database version" -#: backend/flow/consts.py:209 -msgid "ha-gm.conf" -msgstr "ha-gm.conf" +#: backend/dbm_init/management/commands/cloud_component.py:38 +#, fuzzy +#| msgid "权限克隆失败,错误信息: {}\n" +msgid "云区域组件初始化失败,错误信息:{}" +msgstr "Permission clone failed, error message: {}\n" -#: backend/flow/consts.py:210 -msgid "ha-agent.conf" -msgstr "ha-agent.conf" +#: backend/exceptions.py:48 +msgid "系统异常" +msgstr "System exception" -#: backend/flow/consts.py:211 -msgid "drs.env" -msgstr "drs.env" +#: backend/exceptions.py:103 +msgid "系统错误" +msgstr "system error" -#: backend/flow/consts.py:215 -msgid "GM" -msgstr "GM" +#: backend/exceptions.py:113 +msgid "参数验证失败" +msgstr "Parameter validation failed" -#: backend/flow/consts.py:216 -msgid "AGENT" -msgstr "AGENT" +#: backend/exceptions.py:118 +msgid "远程服务请求结果异常" +msgstr "The result of the remote service request is abnormal" -#: backend/flow/consts.py:217 -#, fuzzy -#| msgid "deploy-monitor" -msgid "mysql-monitor" -msgstr "deploy-monitor" +#: backend/exceptions.py:123 +msgid "组件调用异常" +msgstr "Component call exception" -#: backend/flow/consts.py:227 -msgid "nginx服务模块" -msgstr "nginx service module" +#: backend/exceptions.py:128 +msgid "业务不存在" +msgstr "business does not exist" -#: backend/flow/consts.py:228 -msgid "dns服务模块" -msgstr "dns service module" +#: backend/exceptions.py:133 +msgid "语言不支持" +msgstr "language not supported" -#: backend/flow/consts.py:229 -msgid "drs服务模块" -msgstr "drs service module" +#: backend/exceptions.py:138 +msgid "权限不足" +msgstr "Insufficient permissions" -#: backend/flow/consts.py:230 -msgid "dbha服务模块" -msgstr "dbha service module" +#: backend/exceptions.py:165 +msgid "服务不稳定,请检查组件健康状况" +msgstr "The service is unstable, please check the component health status" -#: backend/flow/consts.py:235 -msgid "蓝盾制品库" -msgstr "Blue Shield Product Library" +#: backend/flow/consts.py:107 +msgid "创建态" +msgstr "creation state" -#: backend/flow/consts.py:240 -msgid "V1" -msgstr "V1" +#: backend/flow/consts.py:108 +msgid "准备态" +msgstr "ready state" -#: backend/flow/consts.py:248 -msgid "tendis" -msgstr "tending" +#: backend/flow/consts.py:109 +msgid "运行态" +msgstr "running state" -#: backend/flow/consts.py:256 -msgid "bkdbmon" -msgstr "bkdbmon" +#: backend/flow/consts.py:110 +msgid "暂停态" +msgstr "pause state" -#: backend/flow/consts.py:257 -msgid "download" -msgstr "download" +#: backend/flow/consts.py:111 +msgid "闭塞态" +msgstr "Blocked state" -#: backend/flow/consts.py:259 -#, fuzzy -#| msgid "spider" -msgid "spiderctl" -msgstr "spider" +#: backend/flow/consts.py:112 +msgid "完成态" +msgstr "Completion" -#: backend/flow/consts.py:263 backend/flow/consts.py:306 -msgid "sysinit" -msgstr "sysinit" +#: backend/flow/consts.py:113 +msgid "失败态" +msgstr "failure state" -#: backend/flow/consts.py:264 -msgid "deploy" -msgstr "deploy" +#: backend/flow/consts.py:114 +msgid "取消态" +msgstr "cancel state" -#: backend/flow/consts.py:265 -msgid "find-local-backup" -msgstr "find-local-backup" +#: backend/flow/consts.py:122 +msgid "共用参数" +msgstr "Shared parameters" -#: backend/flow/consts.py:266 -msgid "restore-dr" -msgstr "restore-dr" +#: backend/flow/consts.py:123 +msgid "redis共用参数" +msgstr "redis shared parameters" -#: backend/flow/consts.py:267 -msgid "recover-binlog" -msgstr "recover-binlog" +#: backend/flow/consts.py:124 +msgid "TenDBHA" +msgstr "TenDBHA" -#: backend/flow/consts.py:268 -msgid "grant-repl" -msgstr "grant-repl" +#: backend/flow/consts.py:125 +msgid "RedisCache 主从版" +msgstr "RedisCache master-slave version" -#: backend/flow/consts.py:269 -msgid "change-master" -msgstr "change-master" +#: backend/flow/consts.py:126 +msgid "twemproxy + RedisInstance架构" +msgstr "twemproxy + RedisInstance architecture" -#: backend/flow/consts.py:270 -msgid "set-backend" -msgstr "set-backend" +#: backend/flow/consts.py:127 +msgid "predixy + tendisplus架构" +msgstr "predixy + tendisplus architecture" -#: backend/flow/consts.py:271 -msgid "uninstall" -msgstr "uninstall" +#: backend/flow/consts.py:128 +msgid "Es" +msgstr "Es" -#: backend/flow/consts.py:272 -msgid "deploy-dbbackup" -msgstr "deploy-dbbackup" +#: backend/flow/consts.py:129 +msgid "tendb" +msgstr "tendb" -#: backend/flow/consts.py:273 +#: backend/flow/consts.py:131 +msgid "Hdfs" +msgstr "Hdfs" + +#: backend/flow/consts.py:133 #, fuzzy -#| msgid "install-dn" -msgid "install-monitor" -msgstr "install-dn" +#| msgid "InfluxDB" +msgid "Influxdb" +msgstr "InfluxDB" -#: backend/flow/consts.py:274 -msgid "deploy-rotate" -msgstr "deploy-rotate" +#: backend/flow/consts.py:138 +msgid "初始化帐户" +msgstr "Initialize account" -#: backend/flow/consts.py:275 backend/flow/consts.py:281 -msgid "semantic-dumpschema" -msgstr "semantic-dumpschema" +#: backend/flow/consts.py:139 +msgid "实例和帐户" +msgstr "instance and account" -#: backend/flow/consts.py:276 -msgid "import-sqlfile" -msgstr "import-sqlfile" +#: backend/flow/consts.py:140 +msgid "系统配置" +msgstr "System Configuration" -#: backend/flow/consts.py:277 -msgid "clone-client-grant" -msgstr "clone-client-grant" +#: backend/flow/consts.py:141 +msgid "实例配置" +msgstr "instance configuration" -#: backend/flow/consts.py:278 -msgid "clone-proxy-user" -msgstr "clone-proxy-user" +#: backend/flow/consts.py:142 +msgid "默认配置" +msgstr "default allocation" -#: backend/flow/consts.py:279 -msgid "clear-crontab" -msgstr "clear-crontab" +#: backend/flow/consts.py:143 +msgid "proxyconfig" +msgstr "proxyconfig" -#: backend/flow/consts.py:280 -msgid "semantic-check" -msgstr "semantic-check" +#: backend/flow/consts.py:144 +msgid "ES实例配置" +msgstr "ES instance configuration" -#: backend/flow/consts.py:282 -msgid "backup-truncate-database" -msgstr "backup-truncate-database" +#: backend/flow/consts.py:145 +msgid "act配置" +msgstr "act configuration" -#: backend/flow/consts.py:283 -msgid "restart" -msgstr "restart" +#: backend/flow/consts.py:146 +msgid "系统配置类型" +msgstr "system configuration type" -#: backend/flow/consts.py:284 -msgid "clean-mysql" -msgstr "clean-mysql" +#: backend/flow/consts.py:147 +msgid "Kafka实例配置" +msgstr "Kafka instance configuration" -#: backend/flow/consts.py:285 -msgid "backup-database-table" -msgstr "backup-database-table" +#: backend/flow/consts.py:148 +msgid "HDFS集群配置" +msgstr "HDFS cluster configuration" -#: backend/flow/consts.py:286 -msgid "set-backend-toward-slave" -msgstr "set-backend-toward-slave" +#: backend/flow/consts.py:149 +msgid "HDFS实例hdfs-site配置" +msgstr "HDFS instance hdfs-site configuration" -#: backend/flow/consts.py:287 -msgid "pt-table-checksum" -msgstr "pt-table-checksum" +#: backend/flow/consts.py:150 +msgid "HDFS实例core-site配置" +msgstr "HDFS instance core-site configuration" -#: backend/flow/consts.py:288 -msgid "执行分区" -msgstr "execution partition" +#: backend/flow/consts.py:151 +msgid "HDFS实例安装配置" +msgstr "HDFS instance installation configuration" -#: backend/flow/consts.py:289 -msgid "ibs-recover" -msgstr "ibs-recover" +#: backend/flow/consts.py:155 +msgid "系统" +msgstr "system" -#: backend/flow/consts.py:290 -msgid "数据修复指令" -msgstr "Data Repair Instructions" +#: backend/flow/consts.py:156 +msgid "twemproxy config file" +msgstr "twemproxy config file" -#: backend/flow/consts.py:291 -msgid "flashback-binlog" -msgstr "flashback-binlog" +#: backend/flow/consts.py:157 +msgid "predixy config file" +msgstr "predixy config file" -#: backend/flow/consts.py:292 -msgid "full-backup" -msgstr "full-backup" - -#: backend/flow/consts.py:293 -msgid "install-checksum" -msgstr "install-checksum" - -#: backend/flow/consts.py:294 -msgid "mycnf-change" -msgstr "mycnf-change" +#: backend/flow/consts.py:158 +msgid "redis config file" +msgstr "redis config file" -#: backend/flow/consts.py:295 -msgid "安装rotate-binlog程序" -msgstr "Install the rotate-binlog program" +#: backend/flow/consts.py:159 +msgid "全备配置" +msgstr "full configuration" -#: backend/flow/consts.py:296 -msgid "安装dba-toolkit程序" -msgstr "Install the dba-toolkit program" +#: backend/flow/consts.py:160 +msgid "增备配置" +msgstr "Additional configuration" -#: backend/flow/consts.py:297 -msgid "deploy-mysql-crond" -msgstr "deploy-mysql-crond" +#: backend/flow/consts.py:161 +msgid "心跳配置" +msgstr "heartbeat configuration" -#: backend/flow/consts.py:298 -msgid "mysql实例的周边配置清理" -msgstr "Clean up the surrounding configuration of the mysql instance" +#: backend/flow/consts.py:162 +msgid "监控配置" +msgstr "monitoring configuration" -#: backend/flow/consts.py:299 -msgid "初始化spider集群节点关系" -msgstr "Initialize the spider cluster node relationship" +#: backend/flow/consts.py:163 +msgid "基本配置" +msgstr "basic configuration" -#: backend/flow/consts.py:300 -#, fuzzy -#| msgid "spider中控节点名称" -msgid "添加spider临时节点" -msgstr "Spider control node name" +#: backend/flow/consts.py:164 +msgid "热key配置" +msgstr "Hot key configuration" -#: backend/flow/consts.py:301 -#, fuzzy -#| msgid "restart" -msgid "restart-spider" -msgstr "restart" +#: backend/flow/consts.py:165 +msgid "大key配置" +msgstr "Big key configuration" -#: backend/flow/consts.py:302 -msgid "添加spider-slave集群的相关路由信息" -msgstr "Add the relevant routing information of the spider-slave cluster" +#: backend/flow/consts.py:169 +msgid "MASTER" +msgstr "MASTER" -#: backend/flow/consts.py:307 -msgid "install" -msgstr "install" +#: backend/flow/consts.py:170 +msgid "SLAVE" +msgstr "SLAVE" -#: backend/flow/consts.py:308 -msgid "replica_batch" -msgstr "replica_batch" +#: backend/flow/consts.py:174 backend/flow/consts.py:251 +#: backend/flow/consts.py:723 +msgid "mysql" +msgstr "mysql" -#: backend/flow/consts.py:309 -msgid "replicaof" -msgstr "replicaof" +#: backend/flow/consts.py:175 +msgid "mysql-proxy" +msgstr "mysql-proxy" -#: backend/flow/consts.py:310 -msgid "clustermeet_slotsassign" -msgstr "clustermeet_slotassign" +#: backend/flow/consts.py:179 +msgid "dbbackup" +msgstr "dbbackup" -#: backend/flow/consts.py:311 -msgid "keyspattern" -msgstr "keyspattern" +#: backend/flow/consts.py:180 +msgid "actuator" +msgstr "actuator" -#: backend/flow/consts.py:312 -msgid "keysdelete_regex" -msgstr "keysdelete_regex" +#: backend/flow/consts.py:181 +msgid "最新版本" +msgstr "The latest version" -#: backend/flow/consts.py:313 -msgid "keysdelete_files" -msgstr "keysdelete_files" +#: backend/flow/consts.py:184 +msgid "redis_tools" +msgstr "redis_tools" -#: backend/flow/consts.py:314 -msgid "backup" -msgstr "backup" +#: backend/flow/consts.py:185 backend/flow/consts.py:257 +msgid "es" +msgstr "es" -#: backend/flow/consts.py:315 -msgid "flush_data" -msgstr "flush_data" +#: backend/flow/consts.py:186 backend/flow/consts.py:258 +msgid "kafka" +msgstr "kafka" -#: backend/flow/consts.py:316 -msgid "shutdown" -msgstr "shutdown" +#: backend/flow/consts.py:187 backend/flow/consts.py:259 +msgid "hdfs" +msgstr "hdfs" -#: backend/flow/consts.py:317 -msgid "open" -msgstr "open" +#: backend/flow/consts.py:188 backend/flow/consts.py:260 +#, fuzzy +#| msgid "Pulsar" +msgid "pulsar" +msgstr "Pulsar" -#: backend/flow/consts.py:318 -msgid "close" -msgstr "close" +#: backend/flow/consts.py:190 +msgid "dbmon" +msgstr "dbmon" -#: backend/flow/consts.py:319 -msgid "operate" -msgstr "operate" +#: backend/flow/consts.py:191 +msgid "mysql-checksum" +msgstr "mysql-checksum" -#: backend/flow/consts.py:320 -msgid "capturer" -msgstr "capture" +#: backend/flow/consts.py:192 +msgid "Binlog 滚动备份工具" +msgstr "Binlog rotate tool" -#: backend/flow/consts.py:321 -msgid "kill_conn" -msgstr "kill_conn" +#: backend/flow/consts.py:193 +msgid "DBA 工具集" +msgstr "DBA toolkit" -#: backend/flow/consts.py:322 -msgid "param_sync" -msgstr "param_sync" +#: backend/flow/consts.py:194 +msgid "mysql-crond" +msgstr "mysql-crond" -#: backend/flow/consts.py:323 +#: backend/flow/consts.py:195 #, fuzzy -#| msgid "semantic-check" -msgid "sync_check" -msgstr "semantic-check" +#| msgid "MySQL 授权" +msgid "MySQL 监控" +msgstr "MySQL Authorization" -#: backend/flow/consts.py:324 -#, fuzzy -#| msgid "hdfs_datanode" -msgid "dts_datacheck" -msgstr "hdfs_datanode" +#: backend/flow/consts.py:196 +msgid "nginx 服务" +msgstr "nginx service" -#: backend/flow/consts.py:325 -msgid "dts_datarepaire" -msgstr "dts_datarepaire" +#: backend/flow/consts.py:197 +msgid "dns-bind 服务" +msgstr "dns-bind service" -#: backend/flow/consts.py:329 backend/flow/consts.py:352 -#: backend/flow/consts.py:372 backend/flow/consts.py:391 -#: backend/flow/consts.py:541 -msgid "init" -msgstr "init" +#: backend/flow/consts.py:198 +msgid "dns-pull-crond服务" +msgstr "dns-pull-crond service" -#: backend/flow/consts.py:330 backend/flow/consts.py:353 -#: backend/flow/consts.py:373 backend/flow/consts.py:392 -#: backend/flow/consts.py:542 -msgid "decompress_pkg" -msgstr "decompress_pkg" +#: backend/flow/consts.py:199 +msgid "cloud-dbha服务" +msgstr "cloud-dbha service" -#: backend/flow/consts.py:331 backend/flow/consts.py:354 -#: backend/flow/consts.py:374 backend/flow/consts.py:393 -msgid "install_supervisor" -msgstr "install_supervisor" +#: backend/flow/consts.py:200 +msgid "cloud-drs服务" +msgstr "cloud-drs service" -#: backend/flow/consts.py:332 -msgid "install_master" -msgstr "install_master" +#: backend/flow/consts.py:201 +msgid "cloud-drs-tmysqlparse服务" +msgstr "cloud-drs-tmysqlparse service" -#: backend/flow/consts.py:333 -msgid "install_hot" -msgstr "install_hot" +#: backend/flow/consts.py:202 +#, fuzzy +#| msgid "Master节点" +msgid "spider节点名称" +msgstr "Master node" -#: backend/flow/consts.py:334 -msgid "install_cold" -msgstr "install_cold" +#: backend/flow/consts.py:203 +msgid "spider中控节点名称" +msgstr "Spider control node name" -#: backend/flow/consts.py:335 -msgid "install_client" -msgstr "install_client" +#: backend/flow/consts.py:207 +msgid "nginx服务" +msgstr "nginx-service" -#: backend/flow/consts.py:336 -msgid "init_grant" -msgstr "init_grant" +#: backend/flow/consts.py:208 +msgid "dns服务" +msgstr "dns service" -#: backend/flow/consts.py:337 -msgid "install_exporter" -msgstr "install_exporter" +#: backend/flow/consts.py:209 +msgid "drs服务" +msgstr "drs service" -#: backend/flow/consts.py:338 -msgid "install_kibana" -msgstr "install_kibana" +#: backend/flow/consts.py:210 +msgid "dbha服务" +msgstr "dbha service" -#: backend/flow/consts.py:339 backend/flow/consts.py:376 -msgid "install_telegraf" -msgstr "install_telegraf" +#: backend/flow/consts.py:214 +msgid "pull-crond.conf" +msgstr "pull-crond.conf" -#: backend/flow/consts.py:340 backend/flow/consts.py:359 -#: backend/flow/consts.py:378 backend/flow/consts.py:400 -msgid "start_process" -msgstr "start_process" +#: backend/flow/consts.py:215 +msgid "ha-gm.conf" +msgstr "ha-gm.conf" -#: backend/flow/consts.py:341 backend/flow/consts.py:360 -#: backend/flow/consts.py:379 backend/flow/consts.py:401 -msgid "stop_process" -msgstr "stop_process" +#: backend/flow/consts.py:216 +msgid "ha-agent.conf" +msgstr "ha-agent.conf" -#: backend/flow/consts.py:342 backend/flow/consts.py:361 -#: backend/flow/consts.py:380 backend/flow/consts.py:402 -msgid "restart_process" -msgstr "restart_process" +#: backend/flow/consts.py:217 +msgid "drs.env" +msgstr "drs.env" -#: backend/flow/consts.py:343 backend/flow/consts.py:362 -#: backend/flow/consts.py:381 backend/flow/consts.py:403 -msgid "clean_data" -msgstr "clean_data" +#: backend/flow/consts.py:221 +msgid "GM" +msgstr "GM" -#: backend/flow/consts.py:344 -msgid "exclude_node" -msgstr "exclude_node" +#: backend/flow/consts.py:222 +msgid "AGENT" +msgstr "AGENT" -#: backend/flow/consts.py:345 -msgid "check_shards" -msgstr "check_shards" +#: backend/flow/consts.py:223 +#, fuzzy +#| msgid "deploy-monitor" +msgid "mysql-monitor" +msgstr "deploy-monitor" -#: backend/flow/consts.py:346 -msgid "check_connections" -msgstr "check_connections" +#: backend/flow/consts.py:233 +msgid "nginx服务模块" +msgstr "nginx service module" -#: backend/flow/consts.py:347 -msgid "check_nodes" -msgstr "check_nodes" - -#: backend/flow/consts.py:348 -msgid "replace_master" -msgstr "replace_master" +#: backend/flow/consts.py:234 +msgid "dns服务模块" +msgstr "dns service module" -#: backend/flow/consts.py:355 backend/flow/consts.py:394 -msgid "install_zookeeper" -msgstr "install_zookeeper" +#: backend/flow/consts.py:235 +msgid "drs服务模块" +msgstr "drs service module" -#: backend/flow/consts.py:356 -msgid "init_kafkaUser" -msgstr "init_kafkaUser" +#: backend/flow/consts.py:236 +msgid "dbha服务模块" +msgstr "dbha service module" -#: backend/flow/consts.py:357 backend/flow/consts.py:397 -msgid "install_broker" -msgstr "install_broker" +#: backend/flow/consts.py:241 +msgid "蓝盾制品库" +msgstr "Blue Shield Product Library" -#: backend/flow/consts.py:358 -msgid "install_manager" -msgstr "install_manager" +#: backend/flow/consts.py:246 +msgid "V1" +msgstr "V1" -#: backend/flow/consts.py:363 -msgid "reduce_broker" -msgstr "reduce_broker" +#: backend/flow/consts.py:254 +msgid "tendis" +msgstr "tending" -#: backend/flow/consts.py:364 -msgid "check_reassign" -msgstr "check_reassign" +#: backend/flow/consts.py:262 +msgid "bkdbmon" +msgstr "bkdbmon" -#: backend/flow/consts.py:365 -msgid "reconfig_add" -msgstr "reconfig_add" +#: backend/flow/consts.py:263 +msgid "download" +msgstr "download" -#: backend/flow/consts.py:366 -msgid "restart_broker" -msgstr "restart_broker" +#: backend/flow/consts.py:265 +#, fuzzy +#| msgid "spider" +msgid "spiderctl" +msgstr "spider" -#: backend/flow/consts.py:367 -msgid "reconfig_remove" -msgstr "reconfig_remove" +#: backend/flow/consts.py:269 backend/flow/consts.py:313 +msgid "sysinit" +msgstr "sysinit" -#: backend/flow/consts.py:368 -msgid "replace_broker" -msgstr "replace_broker" +#: backend/flow/consts.py:270 +msgid "deploy" +msgstr "deploy" -#: backend/flow/consts.py:375 -#, fuzzy -#| msgid "install_cold" -msgid "install_influxdb" -msgstr "install_cold" +#: backend/flow/consts.py:271 +msgid "find-local-backup" +msgstr "find-local-backup" -#: backend/flow/consts.py:377 -#, fuzzy -#| msgid "init_kafkaUser" -msgid "init_user" -msgstr "init_kafkaUser" +#: backend/flow/consts.py:272 +msgid "restore-dr" +msgstr "restore-dr" -#: backend/flow/consts.py:385 -#, fuzzy -#| msgid "check_connections" -msgid "check_broker_config" -msgstr "check_connections" +#: backend/flow/consts.py:273 +msgid "recover-binlog" +msgstr "recover-binlog" -#: backend/flow/consts.py:386 -msgid "check_namespace_config" -msgstr "check_namespace_config" +#: backend/flow/consts.py:274 +msgid "grant-repl" +msgstr "grant-repl" -#: backend/flow/consts.py:387 -msgid "check_under_replicated" -msgstr "check_under_replicated" +#: backend/flow/consts.py:275 +msgid "change-master" +msgstr "change-master" -#: backend/flow/consts.py:388 -msgid "check_ledger_metadata" -msgstr "check_ledger_metadata" +#: backend/flow/consts.py:276 +msgid "set-backend" +msgstr "set-backend" -#: backend/flow/consts.py:389 -msgid "set_bookie_readonly" -msgstr "set_bookie_readonly" +#: backend/flow/consts.py:277 +msgid "uninstall" +msgstr "uninstall" -#: backend/flow/consts.py:390 -msgid "decommission_bookie" -msgstr "decommission_bookie" +#: backend/flow/consts.py:278 +msgid "deploy-dbbackup" +msgstr "deploy-dbbackup" -#: backend/flow/consts.py:395 +#: backend/flow/consts.py:279 #, fuzzy -#| msgid "tendbcluster" -msgid "init_cluster" -msgstr "tendbcluster" +#| msgid "install-dn" +msgid "install-monitor" +msgstr "install-dn" -#: backend/flow/consts.py:396 -#, fuzzy -#| msgid "install_zookeeper" -msgid "install_bookkeeper" -msgstr "install_zookeeper" +#: backend/flow/consts.py:280 +msgid "deploy-rotate" +msgstr "deploy-rotate" -#: backend/flow/consts.py:398 -#, fuzzy -#| msgid "install_manager" -msgid "install_pulsar_manager" -msgstr "install_manager" +#: backend/flow/consts.py:281 backend/flow/consts.py:287 +msgid "semantic-dumpschema" +msgstr "semantic-dumpschema" -#: backend/flow/consts.py:399 -#, fuzzy -#| msgid "install_manager" -msgid "init_pulsar_manager" -msgstr "install_manager" +#: backend/flow/consts.py:282 +msgid "import-sqlfile" +msgstr "import-sqlfile" -#: backend/flow/consts.py:404 -msgid "add_hosts" -msgstr "add_hosts" +#: backend/flow/consts.py:283 +msgid "clone-client-grant" +msgstr "clone-client-grant" -#: backend/flow/consts.py:405 -#, fuzzy -#| msgid "dfs-host" -msgid "modify_hosts" -msgstr "dfs-host" +#: backend/flow/consts.py:284 +msgid "clone-proxy-user" +msgstr "clone-proxy-user" -#: backend/flow/consts.py:409 -msgid "NOT_RUNNING" -msgstr "NOT_RUNNING" +#: backend/flow/consts.py:285 +msgid "clear-crontab" +msgstr "clear-crontab" -#: backend/flow/consts.py:410 backend/flow/consts.py:468 -msgid "RUNNING" -msgstr "RUNNING" +#: backend/flow/consts.py:286 +msgid "semantic-check" +msgstr "semantic-check" -#: backend/flow/consts.py:411 backend/flow/consts.py:469 -msgid "SUCCESS" -msgstr "SUCCESS" +#: backend/flow/consts.py:288 +msgid "backup-truncate-database" +msgstr "backup-truncate-database" -#: backend/flow/consts.py:412 backend/flow/consts.py:470 -msgid "FAILED" -msgstr "FAILED" +#: backend/flow/consts.py:289 +msgid "restart" +msgstr "restart" -#: backend/flow/consts.py:413 -msgid "SKIPPED" -msgstr "SKIPPED" +#: backend/flow/consts.py:290 +msgid "clean-mysql" +msgstr "clean-mysql" -#: backend/flow/consts.py:414 -msgid "IGNORED" -msgstr "IGNORED" +#: backend/flow/consts.py:291 +msgid "backup-database-table" +msgstr "backup-database-table" -#: backend/flow/consts.py:415 -msgid "WAITING" -msgstr "WAITING" +#: backend/flow/consts.py:292 +msgid "set-backend-toward-slave" +msgstr "set-backend-toward-slave" -#: backend/flow/consts.py:416 -msgid "NORMAL" -msgstr "NORMAL" +#: backend/flow/consts.py:293 +msgid "pt-table-checksum" +msgstr "pt-table-checksum" -#: backend/flow/consts.py:418 -msgid "步骤强制终止中" -msgstr "The step is forcibly terminated" +#: backend/flow/consts.py:294 +msgid "执行分区" +msgstr "execution partition" -#: backend/flow/consts.py:419 -msgid "步骤强制终止成功" -msgstr "Step force terminated successfully" +#: backend/flow/consts.py:295 +msgid "ibs-recover" +msgstr "ibs-recover" -#: backend/flow/consts.py:423 -msgid "准备中" -msgstr "preparing" +#: backend/flow/consts.py:296 +msgid "数据修复指令" +msgstr "Data Repair Instructions" -#: backend/flow/consts.py:424 -msgid "运行中" -msgstr "running" +#: backend/flow/consts.py:297 +msgid "flashback-binlog" +msgstr "flashback-binlog" -#: backend/flow/consts.py:425 -msgid "完成" -msgstr "Finish" +#: backend/flow/consts.py:298 +msgid "full-backup" +msgstr "full-backup" -#: backend/flow/consts.py:426 -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:94 -#: backend/ticket/constants.py:66 backend/ticket/constants.py:76 -msgid "失败" -msgstr "fail" +#: backend/flow/consts.py:299 +msgid "install-checksum" +msgstr "install-checksum" -#: backend/flow/consts.py:431 -msgid "available" -msgstr "available" +#: backend/flow/consts.py:300 +msgid "mycnf-change" +msgstr "mycnf-change" -#: backend/flow/consts.py:433 -msgid "locked" -msgstr "locked" +#: backend/flow/consts.py:301 +#, fuzzy +#| msgid "安装rotate-binlog程序" +msgid "安装mysql-rotatebinlog程序" +msgstr "Install the rotate-binlog program" -#: backend/flow/consts.py:437 -msgid "cluster no" -msgstr "cluster no" +#: backend/flow/consts.py:302 +msgid "安装dba-toolkit程序" +msgstr "Install the dba-toolkit program" -#: backend/flow/consts.py:438 -msgid "cluster yes" -msgstr "cluster yes" +#: backend/flow/consts.py:303 +msgid "deploy-mysql-crond" +msgstr "deploy-mysql-crond" -#: backend/flow/consts.py:442 backend/flow/consts.py:450 -msgid "create" -msgstr "create" +#: backend/flow/consts.py:304 +msgid "mysql实例的周边配置清理" +msgstr "Clean up the surrounding configuration of the mysql instance" -#: backend/flow/consts.py:443 -msgid "cluster_delete" -msgstr "cluster_delete" +#: backend/flow/consts.py:305 +msgid "初始化spider集群节点关系" +msgstr "Initialize the spider cluster node relationship" -#: backend/flow/consts.py:444 -msgid "recycle_record" -msgstr "recycle_record" +#: backend/flow/consts.py:306 +#, fuzzy +#| msgid "spider中控节点名称" +msgid "添加spider临时节点" +msgstr "Spider control node name" -#: backend/flow/consts.py:445 backend/flow/consts.py:451 -msgid "update" -msgstr "update" - -#: backend/flow/consts.py:446 -msgid "select" -msgstr "select" - -#: backend/flow/consts.py:452 +#: backend/flow/consts.py:307 #, fuzzy -#| msgid "cluster_delete" -msgid "delete" -msgstr "cluster_delete" +#| msgid "restart" +msgid "restart-spider" +msgstr "restart" -#: backend/flow/consts.py:456 -#, fuzzy -#| msgid "安装kibana" -msgid "kibana" -msgstr "install kibana" +#: backend/flow/consts.py:308 +msgid "添加spider-slave集群的相关路由信息" +msgstr "Add the relevant routing information of the spider-slave cluster" -#: backend/flow/consts.py:457 +#: backend/flow/consts.py:309 #, fuzzy -#| msgid "安装kafka manager" -msgid "kafka_manager" -msgstr "install kafka-manager" +#| msgid "sql备份信息" +msgid "mysql备份请求" +msgstr "sql backup information" -#: backend/flow/consts.py:458 -#, fuzzy -#| msgid "install_manager" -msgid "pulsar_manager" -msgstr "install_manager" +#: backend/flow/consts.py:314 +msgid "install" +msgstr "install" -#: backend/flow/consts.py:459 -#, fuzzy -#| msgid "proxy" -msgid "ha_proxy" -msgstr "proxy" +#: backend/flow/consts.py:315 +msgid "replica_batch" +msgstr "replica_batch" -#: backend/flow/consts.py:463 -msgid "KIBANA_PORT" -msgstr "KIBANA_PORT" +#: backend/flow/consts.py:316 +msgid "replicaof" +msgstr "replicaof" -#: backend/flow/consts.py:464 -#, fuzzy -#| msgid "KAFKA_SCALE_UP" -msgid "KAFKA_MANAGER_PORT" -msgstr "KAFKA_SCALE_UP" +#: backend/flow/consts.py:317 +msgid "clustermeet_slotsassign" +msgstr "clustermeet_slotassign" -#: backend/flow/consts.py:474 -msgid "proxy默认实例个数" -msgstr "The number of proxy default instances" +#: backend/flow/consts.py:318 +msgid "keyspattern" +msgstr "keyspattern" -#: backend/flow/consts.py:475 -msgid "redis角色数" -msgstr "Number of redis roles" +#: backend/flow/consts.py:319 +msgid "keysdelete_regex" +msgstr "keysdelete_regex" -#: backend/flow/consts.py:479 -msgid "DB安装目录" -msgstr "DB installation directory" +#: backend/flow/consts.py:320 +msgid "keysdelete_files" +msgstr "keysdelete_files" -#: backend/flow/consts.py:483 -msgid "gcs 安装路径" -msgstr "gcs installation path" +#: backend/flow/consts.py:321 +msgid "backup" +msgstr "backup" -#: backend/flow/consts.py:484 -msgid "key生命周期路径" -msgstr "key lifecycle path" +#: backend/flow/consts.py:322 +msgid "flush_data" +msgstr "flush_data" -#: backend/flow/consts.py:488 -msgid "truncate_table" -msgstr "truncate_table" +#: backend/flow/consts.py:323 +msgid "shutdown" +msgstr "shutdown" -#: backend/flow/consts.py:489 -msgid "drop_database" -msgstr "drop_database" +#: backend/flow/consts.py:324 +msgid "open" +msgstr "open" -#: backend/flow/consts.py:490 -msgid "drop_table" -msgstr "drop_table" +#: backend/flow/consts.py:325 +msgid "close" +msgstr "close" -#: backend/flow/consts.py:513 -msgid "TendataModuleDefault" -msgstr "TendataModuleDefault" +#: backend/flow/consts.py:326 +msgid "operate" +msgstr "operate" -#: backend/flow/consts.py:517 backend/ticket/builders/common/constants.py:38 -msgid "hot" -msgstr "hot" +#: backend/flow/consts.py:327 +msgid "capturer" +msgstr "capture" -#: backend/flow/consts.py:518 backend/ticket/builders/common/constants.py:39 -msgid "cold" -msgstr "cold" +#: backend/flow/consts.py:328 +msgid "kill_conn" +msgstr "kill_conn" -#: backend/flow/consts.py:519 backend/ticket/builders/common/constants.py:40 -msgid "client" -msgstr "client" +#: backend/flow/consts.py:329 +msgid "param_sync" +msgstr "param_sync" -#: backend/flow/consts.py:524 -msgid "redis key删除正则方式" -msgstr "Redis key deletion regular method" +#: backend/flow/consts.py:330 +#, fuzzy +#| msgid "semantic-check" +msgid "sync_check" +msgstr "semantic-check" -#: backend/flow/consts.py:525 -msgid "redis key删除文件方式" -msgstr "Redis key delete file method" +#: backend/flow/consts.py:331 +#, fuzzy +#| msgid "hdfs_datanode" +msgid "dts_datacheck" +msgstr "hdfs_datanode" -#: backend/flow/consts.py:529 -msgid "get" -msgstr "get" +#: backend/flow/consts.py:332 +msgid "dts_datarepaire" +msgstr "dts_datarepaire" -#: backend/flow/consts.py:530 -msgid "release" -msgstr "release" +#: backend/flow/consts.py:336 backend/flow/consts.py:359 +#: backend/flow/consts.py:379 backend/flow/consts.py:398 +#: backend/flow/consts.py:548 +msgid "init" +msgstr "init" -#: backend/flow/consts.py:534 -msgid "覆盖写入上下文变量" -msgstr "overwriting context variables" +#: backend/flow/consts.py:337 backend/flow/consts.py:360 +#: backend/flow/consts.py:380 backend/flow/consts.py:399 +#: backend/flow/consts.py:549 +msgid "decompress_pkg" +msgstr "decompress_pkg" -#: backend/flow/consts.py:535 -msgid "追加写入上下文变量" -msgstr "append to context variable" +#: backend/flow/consts.py:338 backend/flow/consts.py:361 +#: backend/flow/consts.py:381 backend/flow/consts.py:400 +msgid "install_supervisor" +msgstr "install_supervisor" -#: backend/flow/consts.py:539 -msgid "install-supervisor" -msgstr "install-supervisor" +#: backend/flow/consts.py:339 +msgid "install_master" +msgstr "install_master" -#: backend/flow/consts.py:540 -msgid "render-config" -msgstr "render-config" +#: backend/flow/consts.py:340 +msgid "install_hot" +msgstr "install_hot" -#: backend/flow/consts.py:543 -msgid "install-zookeeper" -msgstr "install-zookeeper" +#: backend/flow/consts.py:341 +msgid "install_cold" +msgstr "install_cold" -#: backend/flow/consts.py:544 -msgid "install-journalnode" -msgstr "install-journalnode" +#: backend/flow/consts.py:342 +msgid "install_client" +msgstr "install_client" -#: backend/flow/consts.py:545 -msgid "install-nn1" -msgstr "install-nn1" +#: backend/flow/consts.py:343 +msgid "init_grant" +msgstr "init_grant" -#: backend/flow/consts.py:546 -msgid "install-nn2" -msgstr "install-nn2" +#: backend/flow/consts.py:344 +msgid "install_exporter" +msgstr "install_exporter" -#: backend/flow/consts.py:547 -msgid "install-dn" -msgstr "install-dn" +#: backend/flow/consts.py:345 +msgid "install_kibana" +msgstr "install_kibana" -#: backend/flow/consts.py:548 -msgid "install-zkfc" -msgstr "install-zkfc" +#: backend/flow/consts.py:346 backend/flow/consts.py:383 +msgid "install_telegraf" +msgstr "install_telegraf" -#: backend/flow/consts.py:549 -msgid "install-telegraf" -msgstr "install-telegraf" +#: backend/flow/consts.py:347 backend/flow/consts.py:366 +#: backend/flow/consts.py:385 backend/flow/consts.py:407 +msgid "start_process" +msgstr "start_process" -#: backend/flow/consts.py:550 -msgid "install-haproxy" -msgstr "install-haproxy" +#: backend/flow/consts.py:348 backend/flow/consts.py:367 +#: backend/flow/consts.py:386 backend/flow/consts.py:408 +msgid "stop_process" +msgstr "stop_process" -#: backend/flow/consts.py:551 -msgid "update-hosts" -msgstr "update-hosts" +#: backend/flow/consts.py:349 backend/flow/consts.py:368 +#: backend/flow/consts.py:387 backend/flow/consts.py:409 +msgid "restart_process" +msgstr "restart_process" -#: backend/flow/consts.py:552 -msgid "stop-process" -msgstr "stop-process" +#: backend/flow/consts.py:350 backend/flow/consts.py:369 +#: backend/flow/consts.py:388 backend/flow/consts.py:410 +msgid "clean_data" +msgstr "clean_data" -#: backend/flow/consts.py:553 -msgid "start-component" -msgstr "start-component" +#: backend/flow/consts.py:351 +msgid "exclude_node" +msgstr "exclude_node" -#: backend/flow/consts.py:554 -msgid "clean-data" -msgstr "clean-data" +#: backend/flow/consts.py:352 +msgid "check_shards" +msgstr "check_shards" -#: backend/flow/consts.py:555 -msgid "dfs-host" -msgstr "dfs-host" +#: backend/flow/consts.py:353 +msgid "check_connections" +msgstr "check_connections" -#: backend/flow/consts.py:566 backend/ticket/builders/common/constants.py:45 -msgid "namenode" -msgstr "namenode" +#: backend/flow/consts.py:354 +msgid "check_nodes" +msgstr "check_nodes" -#: backend/flow/consts.py:567 backend/ticket/builders/common/constants.py:44 -msgid "datanode" -msgstr "datanode" +#: backend/flow/consts.py:355 +msgid "replace_master" +msgstr "replace_master" -#: backend/flow/consts.py:568 -msgid "journalnode" -msgstr "journalnode" +#: backend/flow/consts.py:362 backend/flow/consts.py:401 +msgid "install_zookeeper" +msgstr "install_zookeeper" -#: backend/flow/consts.py:570 -msgid "zkfc" -msgstr "zkfc" +#: backend/flow/consts.py:363 +msgid "init_kafkaUser" +msgstr "init_kafkaUser" -#: backend/flow/consts.py:574 backend/ticket/builders/common/constants.py:54 -#, fuzzy -#| msgid "zookeeper" -msgid "bookkeeper" -msgstr "zookeeper" +#: backend/flow/consts.py:364 backend/flow/consts.py:404 +msgid "install_broker" +msgstr "install_broker" -#: backend/flow/consts.py:581 -msgid "常规备份" -msgstr "regular backup" +#: backend/flow/consts.py:365 +msgid "install_manager" +msgstr "install_manager" -#: backend/flow/consts.py:582 -msgid "长期备份" -msgstr "long-term backup" +#: backend/flow/consts.py:370 +msgid "reduce_broker" +msgstr "reduce_broker" -#: backend/flow/consts.py:586 -msgid "KAFKA_REPLACE" -msgstr "KAFKA_REPLACE" +#: backend/flow/consts.py:371 +msgid "check_reassign" +msgstr "check_reassign" -#: backend/flow/consts.py:587 -msgid "KAFKA_SCALE_UP" -msgstr "KAFKA_SCALE_UP" +#: backend/flow/consts.py:372 +msgid "reconfig_add" +msgstr "reconfig_add" -#: backend/flow/consts.py:591 -#, fuzzy -#| msgid "KAFKA_REPLACE" -msgid "INFLUXDB_REPLACE" -msgstr "KAFKA_REPLACE" - -#: backend/flow/consts.py:595 -msgid "逻辑备份" -msgstr "logical backup" - -#: backend/flow/consts.py:599 -msgid "全备-保留25天" -msgstr "Fully Prepared - Reserved for 25 days" - -#: backend/flow/consts.py:600 -msgid "长久存储-保留三年" -msgstr "Long-term storage - keep for three years" - -#: backend/flow/consts.py:608 -msgid "Mysql的进程名称" -msgstr "Mysql process name" - -#: backend/flow/consts.py:609 -msgid "Mysql-proxy进程名称" -msgstr "Mysql-proxy process name" +#: backend/flow/consts.py:373 +msgid "restart_broker" +msgstr "restart_broker" -#: backend/flow/consts.py:610 -msgid "ES的进程名称" -msgstr "ES process name" +#: backend/flow/consts.py:374 +msgid "reconfig_remove" +msgstr "reconfig_remove" -#: backend/flow/consts.py:611 -msgid "HDFS-NameNode的进程名称" -msgstr "HDFS-NameNode process name" +#: backend/flow/consts.py:375 +msgid "replace_broker" +msgstr "replace_broker" -#: backend/flow/consts.py:612 -msgid "HDFS-DataNode的进程名称" -msgstr "HDFS-DataNode process name" +#: backend/flow/consts.py:382 +#, fuzzy +#| msgid "install_cold" +msgid "install_influxdb" +msgstr "install_cold" -#: backend/flow/consts.py:613 +#: backend/flow/consts.py:384 #, fuzzy -#| msgid "ES的进程名称" -msgid "Pulsar的进程名称" -msgstr "ES process name" +#| msgid "init_kafkaUser" +msgid "init_user" +msgstr "init_kafkaUser" -#: backend/flow/consts.py:621 -msgid "远程备份+时间" -msgstr "remote backup + time" +#: backend/flow/consts.py:392 +#, fuzzy +#| msgid "check_connections" +msgid "check_broker_config" +msgstr "check_connections" -#: backend/flow/consts.py:622 -msgid "远程备份+备份ID" -msgstr "Remote Backup + Backup ID" +#: backend/flow/consts.py:393 +msgid "check_namespace_config" +msgstr "check_namespace_config" -#: backend/flow/consts.py:623 -msgid "本地备份+时间" -msgstr "local backup + time" +#: backend/flow/consts.py:394 +msgid "check_under_replicated" +msgstr "check_under_replicated" -#: backend/flow/consts.py:624 -msgid "本地备份+备份ID" -msgstr "Local backup + backup ID" +#: backend/flow/consts.py:395 +msgid "check_ledger_metadata" +msgstr "check_ledger_metadata" -#: backend/flow/consts.py:632 -msgid "手动单据发起" -msgstr "Manual ticket initiation" +#: backend/flow/consts.py:396 +msgid "set_bookie_readonly" +msgstr "set_bookie_readonly" -#: backend/flow/consts.py:633 -msgid "例行校验单据发起" -msgstr "Routine verification ticket initiation" +#: backend/flow/consts.py:397 +msgid "decommission_bookie" +msgstr "decommission_bookie" -#: backend/flow/consts.py:639 +#: backend/flow/consts.py:402 #, fuzzy -#| msgid "mms" -msgid "ms" -msgstr "mms" - -#: backend/flow/consts.py:649 -msgid "redis slot分隔符" -msgstr "redis slot separator" - -#: backend/flow/consts.py:650 -msgid "redis slot导入分隔符" -msgstr "redis slot import delimiter" - -#: backend/flow/consts.py:651 -msgid "redis slot迁移分隔符" -msgstr "redis slot migration delimiter" +#| msgid "tendbcluster" +msgid "init_cluster" +msgstr "tendbcluster" -#: backend/flow/consts.py:659 +#: backend/flow/consts.py:403 #, fuzzy -#| msgid "redis_master" -msgid "redis min slot" -msgstr "redis_master" +#| msgid "install_zookeeper" +msgid "install_bookkeeper" +msgstr "install_zookeeper" -#: backend/flow/consts.py:660 +#: backend/flow/consts.py:405 #, fuzzy -#| msgid "redis_master" -msgid "redis max slot" -msgstr "redis_master" +#| msgid "install_manager" +msgid "install_pulsar_manager" +msgstr "install_manager" -#: backend/flow/consts.py:661 +#: backend/flow/consts.py:406 #, fuzzy -#| msgid "redis_tools" -msgid "redis total slot" -msgstr "redis_tools" +#| msgid "install_manager" +msgid "init_pulsar_manager" +msgstr "install_manager" -#: backend/flow/consts.py:669 -msgid "redis PFAIL state" -msgstr "redis PFAIL state" +#: backend/flow/consts.py:411 +msgid "add_hosts" +msgstr "add_hosts" -#: backend/flow/consts.py:670 +#: backend/flow/consts.py:412 #, fuzzy -#| msgid "redis_master" -msgid "redis fail state" -msgstr "redis_master" +#| msgid "dfs-host" +msgid "modify_hosts" +msgstr "dfs-host" -#: backend/flow/consts.py:671 -msgid "redis handshake state" -msgstr "redis handshake state" +#: backend/flow/consts.py:416 +msgid "NOT_RUNNING" +msgstr "NOT_RUNNING" -#: backend/flow/consts.py:672 -#, fuzzy -#| msgid "redis_master" -msgid "redis noaddr state" -msgstr "redis_master" +#: backend/flow/consts.py:417 backend/flow/consts.py:475 +msgid "RUNNING" +msgstr "RUNNING" -#: backend/flow/consts.py:673 -#, fuzzy -#| msgid "redis config file" -msgid "redis noflags state" -msgstr "redis config file" +#: backend/flow/consts.py:418 backend/flow/consts.py:476 +msgid "SUCCESS" +msgstr "SUCCESS" -#: backend/flow/consts.py:681 -#, fuzzy -#| msgid "redis_master" -msgid "redis master role" -msgstr "redis_master" +#: backend/flow/consts.py:419 backend/flow/consts.py:477 +msgid "FAILED" +msgstr "FAILED" -#: backend/flow/consts.py:682 -#, fuzzy -#| msgid "redis_slave" -msgid "redis slave role" -msgstr "redis_slave" +#: backend/flow/consts.py:420 +msgid "SKIPPED" +msgstr "SKIPPED" -#: backend/flow/consts.py:683 -#, fuzzy -#| msgid "redis config file" -msgid "redis unknown role" -msgstr "redis config file" +#: backend/flow/consts.py:421 +msgid "IGNORED" +msgstr "IGNORED" -#: backend/flow/consts.py:691 -msgid "redis master link status up" -msgstr "redis master link status up" +#: backend/flow/consts.py:422 +msgid "WAITING" +msgstr "WAITING" -#: backend/flow/consts.py:692 -msgid "redis master link status down" -msgstr "redis master link status down" +#: backend/flow/consts.py:423 +msgid "NORMAL" +msgstr "NORMAL" -#: backend/flow/consts.py:693 -msgid "redis ssd incrSync state" -msgstr "redis ssd incrSync state" +#: backend/flow/consts.py:425 +msgid "步骤强制终止中" +msgstr "The step is forcibly terminated" -#: backend/flow/consts.py:694 -msgid "redis ssd REPL_FOLLOW state" -msgstr "redis ssd REPL_FOLLOW state" +#: backend/flow/consts.py:426 +msgid "步骤强制终止成功" +msgstr "Step force terminated successfully" -#: backend/flow/consts.py:695 -msgid "redis connected status" -msgstr "redis connected status" +#: backend/flow/consts.py:430 +msgid "准备中" +msgstr "preparing" -#: backend/flow/consts.py:696 -msgid "redis disconnected status" -msgstr "redis disconnected status" +#: backend/flow/consts.py:431 +msgid "运行中" +msgstr "running" -#: backend/flow/consts.py:704 -msgid "" -"redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" -msgstr "redis cluster state ok, all slots are covered. Obtained by cluster info command" +#: backend/flow/consts.py:432 +msgid "完成" +msgstr "Finish" -#: backend/flow/consts.py:705 -msgid "" -"redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" -msgstr "redis cluster state fail, not all slots are covered. Obtained through the cluster info command" +#: backend/flow/consts.py:433 +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:94 +#: backend/ticket/constants.py:66 backend/ticket/constants.py:76 +msgid "失败" +msgstr "fail" -#: backend/flow/engine/bamboo/engine.py:245 -msgid "获取流程失败" -msgstr "Get process failed" +#: backend/flow/consts.py:438 +msgid "available" +msgstr "available" -#: backend/flow/engine/bamboo/engine.py:248 -msgid "获取流程节点失败" -msgstr "Failed to get process node" +#: backend/flow/consts.py:440 +msgid "locked" +msgstr "locked" -#: backend/flow/engine/bamboo/engine.py:251 -msgid "获取节点运行版本失败" -msgstr "Failed to get node running version" +#: backend/flow/consts.py:444 +msgid "cluster no" +msgstr "cluster no" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:127 -msgid "下发{}可执行文件包" -msgstr "Deliver {} executable file package" +#: backend/flow/consts.py:445 +msgid "cluster yes" +msgstr "cluster yes" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:136 -msgid "部署{}服务进程" -msgstr "Deploy {} service process" +#: backend/flow/consts.py:449 backend/flow/consts.py:457 +msgid "create" +msgstr "create" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:185 -#, fuzzy -#| msgid "配置文件名" -msgid "下发{}配置文件" -msgstr "configuration file name" +#: backend/flow/consts.py:450 +msgid "cluster_delete" +msgstr "cluster_delete" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:311 -msgid "存量集群的权限更新" -msgstr "Permission update for existing clusters" +#: backend/flow/consts.py:451 +msgid "recycle_record" +msgstr "recycle_record" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:339 -#, fuzzy -#| msgid "更新服务" -msgid "更新服务元信息" -msgstr "update service" +#: backend/flow/consts.py:452 backend/flow/consts.py:458 +msgid "update" +msgstr "update" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:364 -msgid "裁撤{}的服务" -msgstr "Cancel {} service" +#: backend/flow/consts.py:453 +msgid "select" +msgstr "select" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:387 +#: backend/flow/consts.py:459 #, fuzzy -#| msgid "nginx服务" -msgid "重启nginx服务" -msgstr "nginx-service" +#| msgid "cluster_delete" +msgid "delete" +msgstr "cluster_delete" -#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:40 -msgid "主机{}部署gm服务" +#: backend/flow/consts.py:463 +#, fuzzy +#| msgid "安装kibana" +msgid "kibana" +msgstr "install kibana" + +#: backend/flow/consts.py:464 +#, fuzzy +#| msgid "安装kafka manager" +msgid "kafka_manager" +msgstr "install kafka-manager" + +#: backend/flow/consts.py:465 +#, fuzzy +#| msgid "install_manager" +msgid "pulsar_manager" +msgstr "install_manager" + +#: backend/flow/consts.py:466 +#, fuzzy +#| msgid "proxy" +msgid "ha_proxy" +msgstr "proxy" + +#: backend/flow/consts.py:470 +msgid "KIBANA_PORT" +msgstr "KIBANA_PORT" + +#: backend/flow/consts.py:471 +#, fuzzy +#| msgid "KAFKA_SCALE_UP" +msgid "KAFKA_MANAGER_PORT" +msgstr "KAFKA_SCALE_UP" + +#: backend/flow/consts.py:481 +msgid "proxy默认实例个数" +msgstr "The number of proxy default instances" + +#: backend/flow/consts.py:482 +msgid "redis角色数" +msgstr "Number of redis roles" + +#: backend/flow/consts.py:486 +msgid "DB安装目录" +msgstr "DB installation directory" + +#: backend/flow/consts.py:490 +msgid "gcs 安装路径" +msgstr "gcs installation path" + +#: backend/flow/consts.py:491 +msgid "key生命周期路径" +msgstr "key lifecycle path" + +#: backend/flow/consts.py:495 +msgid "truncate_table" +msgstr "truncate_table" + +#: backend/flow/consts.py:496 +msgid "drop_database" +msgstr "drop_database" + +#: backend/flow/consts.py:497 +msgid "drop_table" +msgstr "drop_table" + +#: backend/flow/consts.py:520 +msgid "TendataModuleDefault" +msgstr "TendataModuleDefault" + +#: backend/flow/consts.py:524 backend/ticket/builders/common/constants.py:38 +msgid "hot" +msgstr "hot" + +#: backend/flow/consts.py:525 backend/ticket/builders/common/constants.py:39 +msgid "cold" +msgstr "cold" + +#: backend/flow/consts.py:526 backend/ticket/builders/common/constants.py:40 +msgid "client" +msgstr "client" + +#: backend/flow/consts.py:531 +msgid "redis key删除正则方式" +msgstr "Redis key deletion regular method" + +#: backend/flow/consts.py:532 +msgid "redis key删除文件方式" +msgstr "Redis key delete file method" + +#: backend/flow/consts.py:536 +msgid "get" +msgstr "get" + +#: backend/flow/consts.py:537 +msgid "release" +msgstr "release" + +#: backend/flow/consts.py:541 +msgid "覆盖写入上下文变量" +msgstr "overwriting context variables" + +#: backend/flow/consts.py:542 +msgid "追加写入上下文变量" +msgstr "append to context variable" + +#: backend/flow/consts.py:546 +msgid "install-supervisor" +msgstr "install-supervisor" + +#: backend/flow/consts.py:547 +msgid "render-config" +msgstr "render-config" + +#: backend/flow/consts.py:550 +msgid "install-zookeeper" +msgstr "install-zookeeper" + +#: backend/flow/consts.py:551 +msgid "install-journalnode" +msgstr "install-journalnode" + +#: backend/flow/consts.py:552 +msgid "install-nn1" +msgstr "install-nn1" + +#: backend/flow/consts.py:553 +msgid "install-nn2" +msgstr "install-nn2" + +#: backend/flow/consts.py:554 +msgid "install-dn" +msgstr "install-dn" + +#: backend/flow/consts.py:555 +msgid "install-zkfc" +msgstr "install-zkfc" + +#: backend/flow/consts.py:556 +msgid "install-telegraf" +msgstr "install-telegraf" + +#: backend/flow/consts.py:557 +msgid "install-haproxy" +msgstr "install-haproxy" + +#: backend/flow/consts.py:558 +msgid "update-hosts" +msgstr "update-hosts" + +#: backend/flow/consts.py:559 +msgid "stop-process" +msgstr "stop-process" + +#: backend/flow/consts.py:560 +msgid "start-component" +msgstr "start-component" + +#: backend/flow/consts.py:561 +msgid "clean-data" +msgstr "clean-data" + +#: backend/flow/consts.py:562 +msgid "dfs-host" +msgstr "dfs-host" + +#: backend/flow/consts.py:573 backend/ticket/builders/common/constants.py:45 +msgid "namenode" +msgstr "namenode" + +#: backend/flow/consts.py:574 backend/ticket/builders/common/constants.py:44 +msgid "datanode" +msgstr "datanode" + +#: backend/flow/consts.py:575 +msgid "journalnode" +msgstr "journalnode" + +#: backend/flow/consts.py:577 +msgid "zkfc" +msgstr "zkfc" + +#: backend/flow/consts.py:581 backend/ticket/builders/common/constants.py:54 +#, fuzzy +#| msgid "zookeeper" +msgid "bookkeeper" +msgstr "zookeeper" + +#: backend/flow/consts.py:588 +msgid "常规备份" +msgstr "regular backup" + +#: backend/flow/consts.py:589 +msgid "长期备份" +msgstr "long-term backup" + +#: backend/flow/consts.py:593 +msgid "KAFKA_REPLACE" +msgstr "KAFKA_REPLACE" + +#: backend/flow/consts.py:594 +msgid "KAFKA_SCALE_UP" +msgstr "KAFKA_SCALE_UP" + +#: backend/flow/consts.py:598 +#, fuzzy +#| msgid "KAFKA_REPLACE" +msgid "INFLUXDB_REPLACE" +msgstr "KAFKA_REPLACE" + +#: backend/flow/consts.py:602 +msgid "逻辑备份" +msgstr "logical backup" + +#: backend/flow/consts.py:603 +msgid "物理备份" +msgstr "" + +#: backend/flow/consts.py:607 +msgid "全备-保留25天" +msgstr "Fully Prepared - Reserved for 25 days" + +#: backend/flow/consts.py:608 +msgid "长久存储-保留三年" +msgstr "Long-term storage - keep for three years" + +#: backend/flow/consts.py:616 +msgid "Mysql的进程名称" +msgstr "Mysql process name" + +#: backend/flow/consts.py:617 +msgid "Mysql-proxy进程名称" +msgstr "Mysql-proxy process name" + +#: backend/flow/consts.py:618 +msgid "ES的进程名称" +msgstr "ES process name" + +#: backend/flow/consts.py:619 +msgid "HDFS-NameNode的进程名称" +msgstr "HDFS-NameNode process name" + +#: backend/flow/consts.py:620 +msgid "HDFS-DataNode的进程名称" +msgstr "HDFS-DataNode process name" + +#: backend/flow/consts.py:621 +#, fuzzy +#| msgid "ES的进程名称" +msgid "Pulsar的进程名称" +msgstr "ES process name" + +#: backend/flow/consts.py:629 +msgid "远程备份+时间" +msgstr "remote backup + time" + +#: backend/flow/consts.py:630 +msgid "远程备份+备份ID" +msgstr "Remote Backup + Backup ID" + +#: backend/flow/consts.py:631 +msgid "本地备份+时间" +msgstr "local backup + time" + +#: backend/flow/consts.py:632 +msgid "本地备份+备份ID" +msgstr "Local backup + backup ID" + +#: backend/flow/consts.py:640 +msgid "手动单据发起" +msgstr "Manual ticket initiation" + +#: backend/flow/consts.py:641 +msgid "例行校验单据发起" +msgstr "Routine verification ticket initiation" + +#: backend/flow/consts.py:647 +msgid "ms" +msgstr "ms" + +#: backend/flow/consts.py:657 +msgid "redis slot分隔符" +msgstr "redis slot separator" + +#: backend/flow/consts.py:658 +msgid "redis slot导入分隔符" +msgstr "redis slot import delimiter" + +#: backend/flow/consts.py:659 +msgid "redis slot迁移分隔符" +msgstr "redis slot migration delimiter" + +#: backend/flow/consts.py:667 +#, fuzzy +#| msgid "redis_master" +msgid "redis min slot" +msgstr "redis_master" + +#: backend/flow/consts.py:668 +#, fuzzy +#| msgid "redis_master" +msgid "redis max slot" +msgstr "redis_master" + +#: backend/flow/consts.py:669 +#, fuzzy +#| msgid "redis_tools" +msgid "redis total slot" +msgstr "redis_tools" + +#: backend/flow/consts.py:677 +msgid "redis PFAIL state" +msgstr "redis PFAIL state" + +#: backend/flow/consts.py:678 +#, fuzzy +#| msgid "redis_master" +msgid "redis fail state" +msgstr "redis_master" + +#: backend/flow/consts.py:679 +msgid "redis handshake state" +msgstr "redis handshake state" + +#: backend/flow/consts.py:680 +#, fuzzy +#| msgid "redis_master" +msgid "redis noaddr state" +msgstr "redis_master" + +#: backend/flow/consts.py:681 +#, fuzzy +#| msgid "redis config file" +msgid "redis noflags state" +msgstr "redis config file" + +#: backend/flow/consts.py:689 +#, fuzzy +#| msgid "redis_master" +msgid "redis master role" +msgstr "redis_master" + +#: backend/flow/consts.py:690 +#, fuzzy +#| msgid "redis_slave" +msgid "redis slave role" +msgstr "redis_slave" + +#: backend/flow/consts.py:691 +#, fuzzy +#| msgid "redis config file" +msgid "redis unknown role" +msgstr "redis config file" + +#: backend/flow/consts.py:699 +msgid "redis master link status up" +msgstr "redis master link status up" + +#: backend/flow/consts.py:700 +msgid "redis master link status down" +msgstr "redis master link status down" + +#: backend/flow/consts.py:701 +msgid "redis ssd incrSync state" +msgstr "redis ssd incrSync state" + +#: backend/flow/consts.py:702 +msgid "redis ssd REPL_FOLLOW state" +msgstr "redis ssd REPL_FOLLOW state" + +#: backend/flow/consts.py:703 +msgid "redis connected status" +msgstr "redis connected status" + +#: backend/flow/consts.py:704 +msgid "redis disconnected status" +msgstr "redis disconnected status" + +#: backend/flow/consts.py:712 +msgid "" +"redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" +msgstr "" +"redis cluster state ok, all slots are covered. Obtained by cluster info " +"command" + +#: backend/flow/consts.py:713 +msgid "" +"redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" +msgstr "" +"redis cluster state fail, not all slots are covered. Obtained through the " +"cluster info command" + +#: backend/flow/consts.py:722 +msgid "tdbctl" +msgstr "" + +#: backend/flow/engine/bamboo/engine.py:245 +msgid "获取流程失败" +msgstr "Get process failed" + +#: backend/flow/engine/bamboo/engine.py:248 +msgid "获取流程节点失败" +msgstr "Failed to get process node" + +#: backend/flow/engine/bamboo/engine.py:251 +msgid "获取节点运行版本失败" +msgstr "Failed to get node running version" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:127 +msgid "下发{}可执行文件包" +msgstr "Deliver {} executable file package" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:136 +msgid "部署{}服务进程" +msgstr "Deploy {} service process" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:185 +#, fuzzy +#| msgid "配置文件名" +msgid "下发{}配置文件" +msgstr "configuration file name" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:311 +msgid "存量集群的权限更新" +msgstr "Permission update for existing clusters" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:339 +#, fuzzy +#| msgid "更新服务" +msgid "更新服务元信息" +msgstr "update service" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:364 +msgid "裁撤{}的服务" +msgstr "Cancel {} service" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:387 +#, fuzzy +#| msgid "nginx服务" +msgid "重启nginx服务" +msgstr "nginx-service" + +#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:40 +msgid "主机{}部署gm服务" msgstr "Host{} deploys gm service" #: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:59 @@ -8350,7 +8771,7 @@ msgid "执行sa初始化" msgstr "Execute sa initialization" #: backend/flow/engine/bamboo/scene/common/machine_os_init.py:64 -#: backend/ticket/constants.py:239 +#: backend/ticket/constants.py:240 msgid "资源池导入" msgstr "Resource pool import" @@ -8378,8 +8799,6 @@ msgstr "Resource pool import" #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:72 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:63 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_shrink_flow.py:55 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:76 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:74 msgid "获取集群部署配置" msgstr "Get cluster deployment configuration" @@ -8395,8 +8814,6 @@ msgstr "Get cluster deployment configuration" #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:76 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:68 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_shrink_flow.py:59 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:70 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:68 msgid "获取机器信息" msgstr "Get machine information" @@ -8682,12 +9099,11 @@ msgstr "Deliver hdfs media package" #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:145 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:343 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:120 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:108 #: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:140 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:105 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:89 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:227 #: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:99 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:208 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:165 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:223 msgid "初始化机器" msgstr "Initialize the machine" @@ -8974,8 +9390,10 @@ msgstr "install telegraf-{}" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:290 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:181 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:120 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:331 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:264 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:125 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:162 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:348 +#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:91 msgid "更新DBMeta元信息" msgstr "Update DBMeta meta information" @@ -9059,8 +9477,9 @@ msgstr "Old instance information" #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:145 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:176 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:114 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:318 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:250 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:164 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:332 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:335 msgid "添加集群域名" msgstr "Add cluster domain name" @@ -9149,79 +9568,78 @@ msgstr "stop process - {}" msgid "清理数据" msgstr "clean data" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:62 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:61 msgid "执行ip信息为空" msgstr "The execution ip information is empty" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:70 -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:345 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:69 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:366 #, fuzzy #| msgid "下发MySQL介质" msgid "下发MySQL周边程序介质" msgstr "Deliver MySQL media" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:87 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:86 #, fuzzy #| msgid "Master安装备份程序" msgid "Master[{}]安装备份程序" msgstr "Master installs the backup program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:100 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:99 #, fuzzy #| msgid "Master安装rotate_binlog程序" msgid "Master[{}]安装rotate_binlog程序" msgstr "Master installs the rotate_binlog program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:113 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:112 #, fuzzy #| msgid "安装mysql-crond" msgid "Master[{}]安装mysql-monitor" msgstr "Install mysql-crond" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:132 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:131 #, fuzzy #| msgid "Master安装校验程序" msgid "Master[{}]安装校验程序" msgstr "Master installation verification program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:149 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:148 #, fuzzy #| msgid "Master安装DBATools工具箱" msgid "Master[{}]安装DBATools工具箱" msgstr "Master installs the DBATools toolbox" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:168 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:167 #, fuzzy #| msgid "Slave安装备份程序" msgid "Slave[{}]安装备份程序" msgstr "Slave installs the backup program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:181 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:180 #, fuzzy #| msgid "Slave安装rotate_binlog程序" msgid "Slave[{}]安装rotate_binlog程序" msgstr "Slave installs the rotate_binlog program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:194 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:193 #, fuzzy #| msgid "安装mysql-crond" msgid "Slave[{}]安装mysql-monitor" msgstr "Install mysql-crond" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:213 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:212 #, fuzzy #| msgid "Slave安装校验程序" msgid "Slave[{}]安装校验程序" msgstr "Slave installation verification program" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:230 -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:361 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:229 #, fuzzy #| msgid "Slave安装DBATools工具箱" msgid "Slave[{}]安装DBATools工具箱" msgstr "Slave installs the DBATools toolbox" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:248 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:247 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_add.py:260 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:291 #, fuzzy @@ -9229,54 +9647,44 @@ msgstr "Slave installs the DBATools toolbox" msgid "Proxy安装mysql-monitor" msgstr "Install mysql-crond" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:263 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:262 #, fuzzy #| msgid "安装MySQL实例" msgid "安装MySql周边程序" msgstr "Install MySQL instance" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:298 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:297 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:219 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:384 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:450 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:400 msgid "新增repl帐户" msgstr "Add repl account" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:313 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:312 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:228 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:135 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:399 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:149 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:465 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:415 msgid "建立主从关系" msgstr "Establish a master-slave relationship" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:325 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:324 #, fuzzy #| msgid "建立主从关系{}" msgid "建立主从同步[{}]" msgstr "Create a master-slave relationship {}" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:377 -#, fuzzy -#| msgid "安装mysql-crond" -msgid "spider[{}]安装mysql-monitor" -msgstr "Install mysql-crond" - -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:397 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:17 #, fuzzy -#| msgid "Master安装备份程序" -msgid "spider[{}]安装备份程序" -msgstr "Master installs the backup program" - -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:411 -#, fuzzy -#| msgid "安装MySQL实例" -msgid "安装Spider周边程序" -msgstr "Install MySQL instance" +#| msgid "Flow模块HDFS异常" +msgid "Flow模块TenDB 异常" +msgstr "Flow module HDFS exception" #: backend/flow/engine/bamboo/scene/mysql/import_sqlfile_flow.py:77 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:110 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_disable_flow.py:97 #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:73 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:172 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:180 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_add.py:178 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:191 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:334 @@ -9351,7 +9759,7 @@ msgstr "" #: backend/flow/engine/bamboo/scene/mysql/mysql_checksum.py:124 #: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:113 #: backend/flow/plugins/components/collections/common/sleep_timer_service.py:140 -#: backend/ticket/constants.py:320 +#: backend/ticket/constants.py:321 msgid "定时" msgstr "timing" @@ -9360,14 +9768,18 @@ msgid "创建临时用户" msgstr "create temporary user" #: backend/flow/engine/bamboo/scene/mysql/mysql_checksum.py:149 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:117 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:137 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:129 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:102 #: backend/flow/engine/bamboo/scene/mysql/mysql_partition.py:119 #: backend/flow/engine/bamboo/scene/mysql/mysql_rename_database_flow.py:173 #: backend/flow/engine/bamboo/scene/mysql/mysql_truncate_flow.py:171 #: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:119 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:126 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:215 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:172 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:262 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:317 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:155 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:226 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:273 #: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:258 #: backend/flow/engine/bamboo/scene/spider/spider_partition.py:90 #: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:270 @@ -9463,7 +9875,7 @@ msgid "空闲检查" msgstr "idle check" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:129 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:174 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:189 msgid "下发MySQL介质包" msgstr "Deliver the MySQL media package" @@ -9478,21 +9890,21 @@ msgstr "Deliver the proxy media package" #: backend/flow/engine/bamboo/scene/mysql/mysql_restore_slave_flow.py:597 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:350 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:127 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:98 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:236 #: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:110 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:219 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:174 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:234 msgid "部署mysql-crond" msgstr "Deploy mysql-crond" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:184 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:211 msgid "安装proxy实例" msgstr "Install proxy instance" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:194 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:357 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:134 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:233 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:248 msgid "安装MySQL实例" msgstr "Install MySQL instance" @@ -9513,7 +9925,7 @@ msgid "添加从集群域名" msgstr "Add slave cluster domain name" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:276 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:367 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:383 msgid "{}集群部署" msgstr "{} cluster deployment" @@ -9521,33 +9933,40 @@ msgstr "{} cluster deployment" msgid "部署MySQL高可用集群" msgstr "Deploy MySQL High Availability Cluster" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:94 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:97 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:83 #, fuzzy #| msgid "%s slave 节点不存在" msgid "{} standby slave 不存在" msgstr "%s slave node does not exist" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:111 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:117 msgid "构造mydumper正则" msgstr "Construct mydumper regular" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:129 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:149 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:123 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:166 +msgid "检查正则匹配" +msgstr "" + +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:141 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:114 msgid "执行库表备份" msgstr "Execute database table backup" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:143 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:163 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:244 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:155 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:128 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:124 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:123 msgid "关联备份id" msgstr "Associated backup id" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:148 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:250 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:160 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:130 msgid "{} 库表备份" msgstr "{} database table backup" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:151 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:163 msgid "构建库表备份流程成功" msgstr "Build database table backup process successfully" @@ -9556,15 +9975,8 @@ msgstr "Build database table backup process successfully" #: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:105 #, fuzzy #| msgid "删除服务实例" -msgid "删除注册CC系统的服务实例" -msgstr "delete service instance" - -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:128 -#: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:528 -#, fuzzy -#| msgid "清理实例级别周边配置" -msgid "清理实例周边配置" -msgstr "Clean up instance-level perimeter configuration" +msgid "删除注册CC系统的服务实例" +msgstr "delete service instance" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:142 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:356 @@ -9622,11 +10034,11 @@ msgstr "Change the status of the cluster to ONLINE" msgid "启动MySQL高可用集群[{}]" msgstr "Start MySQL high availability cluster[{}]" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:168 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:133 msgid "{} 全库备份" msgstr "{} full database backup" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:171 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:136 msgid "构建全库备份流程成功" msgstr "The process of building a full database backup is successful" @@ -9635,7 +10047,7 @@ msgid "执行集群主故障转移" msgstr "Perform cluster master failover" #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:134 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:266 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:274 msgid "salve节点同步新master数据" msgstr "The salve node synchronizes the new master data" @@ -9644,7 +10056,7 @@ msgid "{}集群执行主故障切换" msgstr "{} cluster performs master failover" #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:160 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:292 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:300 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:278 msgid "变更db_meta元信息" msgstr "Change db_meta meta information" @@ -9653,33 +10065,37 @@ msgstr "Change db_meta meta information" msgid "主故障切换流程[整机切换]" msgstr "Main failover process [whole machine switchover]" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:121 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:87 +msgid "the is_stand_by of new-master-instance [{}] is False " +msgstr "" + +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:129 msgid "回收新master的域名映射" msgstr "Recycle the domain name mapping of the new master" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:136 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:144 msgid "对旧master添加域名映射" msgstr "Add domain name mapping to the old master" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:216 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:224 msgid "旧master添加切换临时账号" msgstr "Old master add switch temporary account" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:231 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:239 #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:453 msgid "新master克隆旧master权限" msgstr "The new master clones the old master permission" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:252 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:260 #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:461 msgid "执行集群切换" msgstr "Perform a cluster switchover" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:285 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:293 msgid "{}集群执行主从切换" msgstr "{} Cluster performs master-slave switchover" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:315 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:323 msgid "主从切换流程[整机切换]" msgstr "Master-slave switching process [whole machine switching]" @@ -9819,6 +10235,12 @@ msgstr "Add domain name mapping to new slave" msgid "{}集群执行成对切换" msgstr "{} cluster performs pairwise switchover" +#: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:528 +#, fuzzy +#| msgid "清理实例级别周边配置" +msgid "清理实例周边配置" +msgstr "Clean up instance-level perimeter configuration" + #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:546 #, fuzzy #| msgid "安装MySQL实例:{}" @@ -10511,6 +10933,42 @@ msgstr "Rolling restart broker node -{ip}" msgid "等待数据过期" msgstr "wait for data to expire" +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:68 +#, fuzzy +#| msgid "[redis]下发介质包" +msgid "Proxy-001-{}-下发介质包" +msgstr "[redis] Send media package" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:75 +#, fuzzy +#| msgid "初始化机器" +msgid "Proxy-002-{}-初始化机器" +msgstr "Initialize the machine" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:100 +#, fuzzy +#| msgid "Redis-003-{}-安装实例" +msgid "Proxy-003-{}-安装实例" +msgstr "Redis-003-{}-installation example" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:109 +#, fuzzy +#| msgid "Redis-004-{}-写入元数据" +msgid "Proxy-004-{}-写入元数据" +msgstr "Redis-004-{}-write metadata" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:130 +#, fuzzy +#| msgid "Redis-005-{}-安装监控" +msgid "Proxy-005-{}-安装监控" +msgstr "Redis-005-{}-install monitoring" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:135 +#, fuzzy +#| msgid "Redis-{}-安装原子任务" +msgid "Proxy-{}-安装原子任务" +msgstr "Redis-{}-install atomic tasks" + #: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dbmon.py:57 #, fuzzy #| msgid "[redis]下发介质包" @@ -10522,31 +10980,31 @@ msgid "Redis-202-{}-安装监控" msgstr "Redis-202-{}-install monitoring" #: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dbmon.py:83 -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:120 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:129 msgid "Redis-{}-安装原子任务" msgstr "Redis-{}-install atomic tasks" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:61 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:63 #, fuzzy #| msgid "[redis]下发介质包" msgid "Redis-001-{}-下发介质包" msgstr "[redis] Send media package" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:69 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:71 #, fuzzy #| msgid "初始化机器" msgid "Redis-002-{}-初始化机器" msgstr "Initialize the machine" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:81 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:90 msgid "Redis-003-{}-安装实例" msgstr "Redis-003-{}-installation example" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:95 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:104 msgid "Redis-004-{}-写入元数据" msgstr "Redis-004-{}-write metadata" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:115 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:124 msgid "Redis-005-{}-安装监控" msgstr "Redis-005-{}-install monitoring" @@ -10662,80 +11120,46 @@ msgstr "Redis-505 - Metadata toggle" msgid "Redis-{}-实例切换" msgstr "instance switching" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:87 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:84 -msgid "[proxy]下发介质包" -msgstr "[proxy] Deliver the media package" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:97 -msgid "[redis]下发介质包" -msgstr "[redis] Send media package" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:119 -msgid "安装Redis实例" -msgstr "Install Redis instance" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:128 -msgid "redis实例安装 元数据" -msgstr "redis instance installation metadata" +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:98 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:98 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:114 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:104 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_master.py:137 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_slave.py:135 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_shutdown.py:118 +#: backend/flow/engine/bamboo/scene/redis/redis_dbmon.py:78 +#: backend/flow/engine/bamboo/scene/redis/redis_flush_data.py:102 +#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:100 +#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:88 +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:128 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:88 +msgid "初始化配置" +msgstr "Initial configuration" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:139 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:160 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:157 msgid "redis建立主从 元数据" msgstr "Redis establishes master-slave metadata" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:168 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:165 -msgid "[redis master]部署bkdbmon" -msgstr "[redis master] Deploy bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:193 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:190 -msgid "[redis slave]部署bkdbmon" -msgstr "[redis slave] Deploy bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:235 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:232 -msgid "[proxy]部署bkdbmon" -msgstr "[proxy] deploy bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:248 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:245 -msgid "proxy安装 元数据" -msgstr "proxy installation metadata" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:254 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:250 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:186 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:184 msgid "建立集群 元数据" msgstr "Create cluster metadata" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:278 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:263 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:210 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:197 msgid "回写集群配置[Redis]" msgstr "Write back cluster configuration [Redis]" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:294 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:226 msgid "回写集群配置[Twemproxy]" msgstr "Write back cluster configuration [Twemproxy]" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:309 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:294 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:241 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:228 msgid "注册域名" msgstr "Domain name registration" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:98 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:114 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:104 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_master.py:137 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_slave.py:135 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_shutdown.py:118 -#: backend/flow/engine/bamboo/scene/redis/redis_dbmon.py:78 -#: backend/flow/engine/bamboo/scene/redis/redis_flush_data.py:102 -#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:100 -#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:88 -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:128 -msgid "初始化配置" -msgstr "Initial configuration" - #: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:103 #: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:119 #: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:109 @@ -10774,7 +11198,9 @@ msgstr "New Tendis pre-check exception" #: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:109 msgid "redis dts发起任务并等待至增量同步阶段" -msgstr "redis dts initiates a task and waits until the incremental synchronization phase" +msgstr "" +"redis dts initiates a task and waits until the incremental synchronization " +"phase" #: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:128 #, fuzzy @@ -10883,2015 +11309,1809 @@ msgstr "Cluster[{}] deletes keys according to the rules" msgid "获取磁盘空闲最大机器" msgstr "Get disk free max machine" -#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:158 -msgid "按文件删除key" -msgstr "Delete key by file" - -#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:163 -msgid "集群[{}]按文件删除keys" -msgstr "cluster[{}] delete keys by file" - -#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:103 -msgid "提取key: {}" -msgstr "Extract key: {}" - -#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:110 -msgid "集群[{}提取keys" -msgstr "cluster[{} extract keys" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:136 -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:211 -msgid "proxy下发介质包" -msgstr "The proxy delivers the media package" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:151 -msgid "{}安装proxy实例" -msgstr "{} install proxy instance" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:158 -msgid "{}部署bkdbmon" -msgstr "{} deploy bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:171 -msgid "{}proxy扩容 元数据" -msgstr "{} proxy expansion metadata" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:184 -msgid "{}添加域名" -msgstr "{} add domain name" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:200 -msgid "主机转移" -msgstr "host transfer" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:203 -msgid "新增proxy实例" -msgstr "Add proxy instance" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:226 -msgid "{}删除域名" -msgstr "{} delete domain name" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:244 -#: backend/flow/engine/bamboo/scene/redis/singele_redis_shutdown.py:136 -msgid "主机转移到空闲机" -msgstr "Host transfer to idle machine" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:249 -msgid "下架proxy实例" -msgstr "Remove the proxy instance" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:259 -msgid "proxy下架元数据" -msgstr "Proxy removal metadata" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:94 -msgid "[tendisplus]下发介质包" -msgstr "[tendisplus] Send media package" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:116 -msgid "安装tendisplus实例" -msgstr "Install a tendisplus instance" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:125 -msgid "tendisplus实例安装 元数据" -msgstr "Tendisplus instance installation metadata" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:132 -msgid "建立meet关系" -msgstr "Establish a meet relationship" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:136 -msgid "redis建立主从元数据" -msgstr "Redis establishes master-slave metadata" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:208 -msgid "安装predixy实例" -msgstr "Install predixy instance" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:279 -msgid "回写集群配置[predixy]" -msgstr "Write back cluster configuration [predixy]" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:209 -msgid "查询remotedb version 失败" -msgstr "Query remotedb version failed" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:215 -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:231 -#, python-brace-format -msgid "存在多个版本{version}" -msgstr "Multiple versions {version} exist" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:225 -msgid "查询spider version 失败" -msgstr "Query spider version failed" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:79 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:187 -msgid "下发Spider/tdbCtl介质包" -msgstr "Deliver the Spider/tdbCtl media package" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:129 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:253 -msgid "安装Spider实例" -msgstr "Install the Spider instance" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:140 -msgid "spider上对中控主节点进行授权" -msgstr "Authorize the central control master node on the spider" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:150 -msgid "中控主节点注册临时spider节点路由信息" -msgstr "The central control master node registers the routing information of the temporary spider node" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:155 -msgid "{}添加临时spider节点" -msgstr "{}Add a temporary spider node" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:147 -#, fuzzy -#| msgid "创建临时用户" -msgid "分片{}:创建临时用户" -msgstr "create temporary user" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:201 -#, fuzzy -#| msgid "master[{}{}{}],slave[{}{}{}]的校验结果" -msgid "分片{}:master[{}{}{}],slave[{}{}{}]的校验结果" -msgstr "Check result of master[{}{}{}],slave[{}{}{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:216 -#, fuzzy -#| msgid "master[{}{}{}]的校验任务" -msgid "分片{}:master[{}{}{}]的校验任务" -msgstr "Verification task of master[{}{}{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:224 -#, fuzzy -#| msgid "master[{}{}{}]的校验任务" -msgid "集群[{}]的校验任务" -msgstr "Verification task of master[{}{}{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:120 -#, fuzzy -#| msgid "构造mydumper正则" -msgid "构造 spider/ctl mydumper正则" -msgstr "Construct mydumper regular" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:138 -#, fuzzy -#| msgid "执行库表备份" -msgid "spider 执行库表备份" -msgstr "Execute database table backup" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:151 -#, fuzzy -#| msgid "执行库表备份" -msgid "ctl 执行库表备份" -msgstr "Execute database table backup" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:164 -#, fuzzy -#| msgid "备份测试库表结构" -msgid "spider/ctl 备份库表结构" -msgstr "Backup test database table structure" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:209 -#, fuzzy -#| msgid "构造mydumper正则" -msgid "构造remote mydumper正则" -msgstr "Construct mydumper regular" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:227 -#, fuzzy -#| msgid "执行库表备份" -msgid "remote 执行库表备份" -msgstr "Execute database table backup" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:239 -msgid "remote 备份库表" -msgstr "remote backup database table" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:254 -#, fuzzy -#| msgid "构建库表备份流程成功" -msgid "构造库表备份流程成功" -msgstr "Build database table backup process successfully" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:72 -msgid "存入的存储节点数量不是偶数,请检查!" -msgstr "" -"The number of stored storage nodes is not an even number, please check!" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:269 -msgid "安装Spider集群中控实例" -msgstr "Install the control instance of the Spider cluster" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:301 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:199 -msgid "集群内部节点间授权" -msgstr "Inter-node authorization within the cluster" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:311 -#, fuzzy -#| msgid "初始化集群配置-{}" -msgid "初始化集群节点间关系" -msgstr "Init cluster config-{}" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:413 -msgid "部署spider-ctl集群" -msgstr "Deploy the spider-ctl cluster" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:136 -msgid "卸载spider实例" -msgstr "Uninstall the spider instance" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:150 -msgid "卸载中控实例" -msgstr "Uninstall the central control instance" +#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:158 +msgid "按文件删除key" +msgstr "Delete key by file" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:193 -#, fuzzy -#| msgid "TendisplusCluster集群" -msgid "下架TenDB-Cluster集群[{}]" -msgstr "TendisplusCluster cluster" +#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:163 +msgid "集群[{}]按文件删除keys" +msgstr "cluster[{}] delete keys by file" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_disable_deploy.py:103 -#, fuzzy -#| msgid "卸载spider实例" -msgid "重启spider实例" -msgstr "Uninstall the spider instance" +#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:103 +msgid "提取key: {}" +msgstr "Extract key: {}" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_enable_deploy.py:137 -#, fuzzy -#| msgid "启动MySQL高可用集群[{}]" -msgid "启用spider集群[{}]" -msgstr "Start MySQL high availability cluster[{}]" +#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:110 +msgid "集群[{}提取keys" +msgstr "cluster[{} extract keys" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:182 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:186 -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:190 -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:194 -msgid "预清理备份库" -msgstr "Preclean the backup repository" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:136 +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:211 +msgid "proxy下发介质包" +msgstr "The proxy delivers the media package" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:240 -msgid "适配备份库映射" -msgstr "Adapt backup library mapping" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:151 +msgid "{}安装proxy实例" +msgstr "{} install proxy instance" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:246 -msgid "重建备份库" -msgstr "Rebuild the backup library" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:158 +msgid "{}部署bkdbmon" +msgstr "{} deploy bkdbmon" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:283 -msgid "{} on remote {} 清档" -msgstr "{} on remote {} clear file" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:171 +msgid "{}proxy扩容 元数据" +msgstr "{} proxy expansion metadata" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:294 -msgid "处理集群表" -msgstr "Working with clustered tables" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:184 +msgid "{}添加域名" +msgstr "{} add domain name" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:311 -#, fuzzy -#| msgid "构建清档流程成功" -msgid "构造清档流程成功" -msgstr "Build clearance process succeeded" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:200 +msgid "主机转移" +msgstr "host transfer" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:110 -msgid "partition_sql_file_{}_{}_{}_{}.txt" -msgstr "partition_sql_file_{}_{}_{}_{}.txt" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:203 +msgid "新增proxy实例" +msgstr "Add proxy instance" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:113 -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:124 -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:145 -msgid "{}: {}" -msgstr "{}: {}" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:226 +msgid "{}删除域名" +msgstr "{} delete domain name" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:167 -#, fuzzy -#| msgid "构建清档流程成功" -msgid "构建spider partition流程成功" -msgstr "Build clearance process succeeded" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:244 +#: backend/flow/engine/bamboo/scene/redis/singele_redis_shutdown.py:136 +msgid "主机转移到空闲机" +msgstr "Host transfer to idle machine" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:307 -#, fuzzy -#| msgid "{} 重命名数据库" -msgid "{} on remote {} 重命名数据库" -msgstr "{} rename database" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:249 +msgid "下架proxy实例" +msgstr "Remove the proxy instance" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:315 -#, fuzzy -#| msgid "删除集群域名" -msgid "删除集群源库" -msgstr "Delete the cluster domain name" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:259 +msgid "proxy下架元数据" +msgstr "Proxy removal metadata" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:323 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:140 #, fuzzy -#| msgid "重命名数据库列表" -msgid "构造数据库重命名流程成功" -msgstr "Rename database list" +#| msgid "建立meet关系" +msgid "建立集群meet关系" +msgstr "Establish a meet relationship" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:148 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:213 +msgid "回写集群配置[predixy]" +msgstr "Write back cluster configuration [predixy]" + +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:72 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:210 #, fuzzy #| msgid "下发proxy安装介质" msgid "下发spider安装介质" msgstr "Deliver proxy installation media" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:190 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:114 #, fuzzy #| msgid "安装Spider实例" msgid "安装Spider_slave实例" msgstr "Install the Spider instance" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:205 -#, fuzzy -#| msgid "下发actuator" -msgid "中控Master下发DB-actuator" -msgstr "Issue the actuator" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:130 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:284 +msgid "克隆权限到spider节点[{}]" +msgstr "Clone permissions to the spider node [{}]" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:221 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:149 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:307 msgid "添加对应路由关系" msgstr "Add corresponding routing relationship" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:231 -msgid "克隆权限到spider节点[{}]" -msgstr "Clone permissions to the spider node [{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:280 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:176 #, fuzzy -#| msgid "开始添加slave" -msgid "添加slave集群" -msgstr "Start adding slaves" - -#: backend/flow/engine/exceptions.py:28 -msgid "组件服务未部署" -msgstr "Component Services is not deployed" - -#: backend/flow/models.py:22 backend/flow/models.py:38 -msgid "流程ID" -msgstr "Process ID" - -#: backend/flow/models.py:23 -msgid "流程树" -msgstr "process tree" - -#: backend/flow/models.py:25 backend/ticket/serializers.py:108 -msgid "流程状态" -msgstr "process status" - -#: backend/flow/models.py:27 -msgid "流程创建人" -msgstr "Process Creator" - -#: backend/flow/models.py:28 -msgid "启动时间" -msgstr "Start Time" - -#: backend/flow/models.py:29 -msgid "流程结束时间" -msgstr "process end time" - -#: backend/flow/models.py:40 -msgid "当前版本ID" -msgstr "current version id" - -#: backend/flow/models.py:42 -msgid "节点状态" -msgstr "node status" +#| msgid "{}添加临时spider节点" +msgid "集群[{}]添加spider slave节点" +msgstr "{}Add a temporary spider node" -#: backend/flow/models.py:44 -msgid "节点运行时IP" -msgstr "Node runtime IP" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:252 +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:129 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:268 +msgid "安装Spider实例" +msgstr "Install the Spider instance" -#: backend/flow/models.py:46 -msgid "开始执行时间" -msgstr "start execution time" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:267 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:284 +msgid "安装Spider集群中控实例" +msgstr "Install the control instance of the Spider cluster" -#: backend/flow/plugins/components/collections/cloud/exec_service_script.py:58 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:344 #, fuzzy -#| msgid "该节点获取到执行ip信息为空,请联系系统管理员" -msgid "该节点{}获取到执行ip信息为空,请联系系统管理员" -msgstr "" -"The node obtained execution ip information is empty, please contact the " -"system administrator" - -#: backend/flow/plugins/components/collections/cloud/push_config_file.py:56 -#: backend/flow/plugins/components/collections/cloud/trans_files.py:59 -#: backend/flow/plugins/components/collections/es/trans_files.py:63 -#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:70 -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:99 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:85 -#: backend/flow/plugins/components/collections/redis/trans_flies.py:79 -msgid "[{}] 下发介质包参数:{}" -msgstr "[{}] Delivery media package parameters: {}" +#| msgid "{}添加临时spider节点" +msgid "集群[{}]添加spider master节点" +msgstr "{}Add a temporary spider node" -#: backend/flow/plugins/components/collections/cloud/trans_files.py:44 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:382 #, fuzzy -#| msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" -msgid "该节点{}获取到执行ip信息为空,请联系系统管理员{}" -msgstr "" -"The execution ip information obtained by this node is empty, please contact " -"the system administrator {}" - -#: backend/flow/plugins/components/collections/common/base_service.py:83 -msgid "[{}] 运行成功" -msgstr "[{}] ran successfully" +#| msgid "Master安装DBATools工具箱" +msgid "spider[{}]安装DBATools工具箱" +msgstr "Master installs the DBATools toolbox" -#: backend/flow/plugins/components/collections/common/base_service.py:87 -msgid "[{}] 失败: {}" -msgstr "[{}] fail: {}" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:398 +#, fuzzy +#| msgid "安装mysql-crond" +msgid "spider[{}]安装mysql-monitor" +msgstr "Install mysql-crond" -#: backend/flow/plugins/components/collections/common/base_service.py:216 -msgid "[写入上下文结果失败] failed: {}" -msgstr "[Failed to write context result] failed: {}" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:415 +#, fuzzy +#| msgid "Master安装备份程序" +msgid "spider[{}]安装备份程序" +msgstr "Master installs the backup program" -#: backend/flow/plugins/components/collections/common/base_service.py:253 -msgid "[{}] 任务正在执行🤔" -msgstr "[{}] Task is executing 🤔" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:429 +#, fuzzy +#| msgid "安装MySQL实例" +msgid "安装Spider周边程序" +msgstr "Install MySQL instance" -#: backend/flow/plugins/components/collections/common/base_service.py:262 -msgid "[{}] 任务调度失败😱" -msgstr "[{}] Task scheduling failed 😱" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:479 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:429 +msgid "部署spider-ctl集群" +msgstr "Deploy the spider-ctl cluster" -#: backend/flow/plugins/components/collections/common/base_service.py:273 -msgid "[{}]任务调度成功🥳︎" -msgstr "[{}] Task scheduling succeeded 🥳︎" +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:17 +#, fuzzy +#| msgid "Flow模块HDFS异常" +msgid "Flow模块TenDB Cluster异常" +msgstr "Flow module HDFS exception" -#: backend/flow/plugins/components/collections/common/base_service.py:279 -msgid "[{}]该节点需要获取执行后日志,赋值到trans_data" +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:28 +msgid "添加spider-master节点是分配incr初始值失败" msgstr "" -"[{}] This node needs to obtain the post-execution log and assign it to " -"trans_data" - -#: backend/flow/plugins/components/collections/common/base_service.py:290 -msgid "[{}] 获取执行后日志失败,获取ip[{}]" -msgstr "[{}] Failed to get log after execution, get ip[{}]" -#: backend/flow/plugins/components/collections/common/bigdata_manager_service.py:123 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:34 #, fuzzy -#| msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" -msgid "无法找到Manager处理类型,请联系系统管理员:{}" -msgstr "" -"Unable to adapt to the incoming domain name processing type, please contact " -"the system administrator: {}" +#| msgid "spider中控节点名称" +msgid "添加spider节点路由失败" +msgstr "Spider control node name" + +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:209 +msgid "查询remotedb version 失败" +msgstr "Query remotedb version failed" -#: backend/flow/plugins/components/collections/common/create_ticket.py:36 -msgid "未知单据类型, {}不存在于已知单据类型中" -msgstr "Unknown ticket type, {} does not exist in known ticket types" +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:215 +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:231 +#, python-brace-format +msgid "存在多个版本{version}" +msgstr "Multiple versions {version} exist" -#: backend/flow/plugins/components/collections/common/create_ticket.py:41 -msgid "不允许自动创建单据,单据创建流程结束" +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:225 +msgid "查询spider version 失败" +msgstr "Query spider version failed" + +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:87 +msgid "[{}]The cluster has not added a slave cluster, skip" msgstr "" -"Automatic ticket creation is not allowed, and the ticket creation process " -"ends" -#: backend/flow/plugins/components/collections/common/external_service.py:36 -msgid "第三方接口: {} 请求成功! 返回参数为: {}" -msgstr "Third-party interface: {} The request is successful! The return parameter is: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:96 +msgid "[{}]This type of role addition is not supported" +msgstr "" -#: backend/flow/plugins/components/collections/common/external_service.py:38 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:140 #, fuzzy -#| msgid "权限克隆失败,错误信息: {}\n" -msgid "第三方接口:{} 调用失败!错误信息为: {}" -msgstr "Permission clone failed, error message: {}\n" +#| msgid "{}添加临时spider节点" +msgid "[{}]添加spider-master节点流程" +msgstr "{}Add a temporary spider node" -#: backend/flow/plugins/components/collections/common/external_service.py:40 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:177 #, fuzzy -#| msgid "权限克隆失败,错误信息: {}\n" -msgid "请求遇到未知错误!错误信息为: {}" -msgstr "Permission clone failed, error message: {}\n" +#| msgid "{}添加临时spider节点" +msgid "[{}]添加spider-slave节点流程" +msgstr "{}Add a temporary spider node" -#: backend/flow/plugins/components/collections/common/pause.py:44 -msgid "【{}】自动化流程待确认,是否继续?" -msgstr "" -"【{}】The automated process is pending confirmation. Do you want to continue?" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:79 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:202 +msgid "下发Spider/tdbCtl介质包" +msgstr "Deliver the Spider/tdbCtl media package" -#: backend/flow/plugins/components/collections/common/pause.py:78 -msgid "回调数据" -msgstr "callback data" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:140 +msgid "spider上对中控主节点进行授权" +msgstr "Authorize the central control master node on the spider" -#: backend/flow/plugins/components/collections/common/pause.py:87 -#: backend/ticket/constants.py:314 -msgid "暂停" -msgstr "pause" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:150 +msgid "中控主节点注册临时spider节点路由信息" +msgstr "" +"The central control master node registers the routing information of the " +"temporary spider node" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:38 -msgid "{}-空闲检查" -msgstr "{} - idle check" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:155 +msgid "{}添加临时spider节点" +msgstr "{}Add a temporary spider node" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:70 -#: backend/flow/plugins/components/collections/common/sa_init.py:66 -msgid "空闲检查失败" -msgstr "idle check failed" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:147 +#, fuzzy +#| msgid "创建临时用户" +msgid "分片{}:创建临时用户" +msgstr "create temporary user" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:72 -#: backend/flow/plugins/components/collections/common/sa_init.py:68 -msgid "任务状态异常{}" -msgstr "The task status is abnormal {}" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:201 +#, fuzzy +#| msgid "master[{}{}{}],slave[{}{}{}]的校验结果" +msgid "分片{}:master[{}{}{}],slave[{}{}{}]的校验结果" +msgstr "Check result of master[{}{}{}],slave[{}{}{}]" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:85 -msgid "错误详情{}" -msgstr "error details{}" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:216 +#, fuzzy +#| msgid "master[{}{}{}]的校验任务" +msgid "分片{}:master[{}{}{}]的校验任务" +msgstr "Verification task of master[{}{}{}]" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:90 -msgid "sa空闲检查" -msgstr "sa idle check" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:224 +#, fuzzy +#| msgid "master[{}{}{}]的校验任务" +msgid "集群[{}]的校验任务" +msgstr "Verification task of master[{}{}{}]" -#: backend/flow/plugins/components/collections/common/sa_init.py:35 -msgid "SA初始化" -msgstr "SA initialization" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:121 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:120 +msgid "不支持的备份位置 {}" +msgstr "" -#: backend/flow/plugins/components/collections/common/sa_init.py:82 -msgid "sa初始化" -msgstr "sa initialization" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:134 +#, fuzzy +#| msgid "构建库表备份流程成功" +msgid "构造库表备份流程成功" +msgstr "Build database table backup process successfully" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:50 -msgid "定时时间" -msgstr "Timing" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:160 +#, fuzzy +#| msgid "构造mydumper正则" +msgid "构造 spider/ctl mydumper正则" +msgstr "Construct mydumper regular" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:53 -#, python-format -msgid "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" -msgstr "Timing time, the format is seconds (s) or (%%Y-%%m-%%d %%H:%%M:%%S)" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:184 +#, fuzzy +#| msgid "执行库表备份" +msgid "spider 执行库表备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:56 -msgid "是否强制晚于当前时间" -msgstr "Whether to force later than the current time" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:197 +#, fuzzy +#| msgid "执行库表备份" +msgid "ctl 执行库表备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:59 -msgid "" -"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" -msgstr "" -"Whether to force the time to be later than the current time when the user " -"enters the date format, only valid for timing input in the date format" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:208 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:191 +#, fuzzy +#| msgid "备份测试库表结构" +msgid "spider/ctl备份库表结构" +msgstr "Backup test database table structure" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:83 -#, python-format -msgid "输入参数%s不符合【时区(+08:00、-08:00)】格式" -msgstr "" -"The input parameter %s does not conform to the [time zone (+08:00, -08:00)] " -"format" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:256 +#, fuzzy +#| msgid "构造mydumper正则" +msgid "构造remote mydumper正则" +msgstr "Construct mydumper regular" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:98 -msgid "定时时间需晚于当前时间" -msgstr "The timing time needs to be later than the current time" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:274 +#, fuzzy +#| msgid "执行库表备份" +msgid "remote 执行库表备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:106 -#, python-format -msgid "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" -msgstr "" -"The input parameter %s does not conform to the [second (s) or time (%%Y-%%m-" -"%%d %%H:%%M:%%S)] format" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:286 +msgid "remote 备份库表" +msgstr "remote backup database table" -#: backend/flow/plugins/components/collections/es/es_dns_manage.py:61 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:37 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:48 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:75 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:57 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:69 -#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:29 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:43 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:78 -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:44 -msgid "该节点获取到执行ip信息为空,请联系系统管理员" -msgstr "" -"The node obtained execution ip information is empty, please contact the " -"system administrator" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:311 +#, fuzzy +#| msgid "运维节点" +msgid "构造运维节点正则" +msgstr "Operation and maintenance node" -#: backend/flow/plugins/components/collections/es/es_dns_manage.py:146 -#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:71 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:93 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:84 -#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:61 -#: backend/flow/plugins/components/collections/pulsar/pulsar_zk_dns_manage.py:51 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:84 -msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" -msgstr "" -"Unable to adapt to the incoming domain name processing type, please contact " -"the system administrator: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:329 +#, fuzzy +#| msgid "执行库表备份" +msgid "运维节点执行库表备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/es/exec_es_actuator_script.py:65 -#: backend/flow/plugins/components/collections/es/trans_files.py:47 -#: backend/flow/plugins/components/collections/hdfs/exec_actuator_script.py:69 -#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:53 -#: backend/flow/plugins/components/collections/influxdb/exec_actuator_script.py:62 -#: backend/flow/plugins/components/collections/kafka/exec_actuator_script.py:62 -#: backend/flow/plugins/components/collections/mysql/exec_actuator_script.py:103 -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:60 -#: backend/flow/plugins/components/collections/pulsar/exec_actuator_script.py:66 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:46 -#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:82 -#: backend/flow/plugins/components/collections/redis/trans_flies.py:61 -msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:340 +#, fuzzy +#| msgid "库表备份" +msgid "spider_mnt库表备份" +msgstr "Database table backup" + +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:84 +msgid "存入的存储节点数量不是偶数,请检查!" msgstr "" -"The execution ip information obtained by this node is empty, please contact " -"the system administrator {}" +"The number of stored storage nodes is not an even number, please check!" -#: backend/flow/plugins/components/collections/es/get_es_resource.py:57 -#: backend/flow/plugins/components/collections/kafka/get_kafka_resource.py:50 -#: backend/flow/plugins/components/collections/redis/get_redis_resource.py:81 -msgid "获取机器资源成功成功。 {}" -msgstr "Acquiring the machine resource was successful. {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:316 +msgid "集群内部节点间授权" +msgstr "Inter-node authorization within the cluster" -#: backend/flow/plugins/components/collections/hdfs/get_hdfs_resource.py:61 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:328 #, fuzzy -#| msgid "获取机器资源成功成功。 {}" -msgid "获取机器资源成功。 {}" -msgstr "Acquiring the machine resource was successful. {}" - -#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:48 -msgid "获取DNS操作IP为空" -msgstr "Get DNS operation IP is empty" +#| msgid "初始化集群配置-{}" +msgid "初始化集群节点间关系" +msgstr "Init cluster config-{}" -#: backend/flow/plugins/components/collections/hdfs/update_hdfs_resource.py:67 -msgid "更新机器资源成功成功。 {}" -msgstr "Updating the machine resource succeeded successfully. {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:136 +msgid "卸载spider实例" +msgstr "Uninstall the spider instance" -#: backend/flow/plugins/components/collections/influxdb/trans_flies.py:52 -#: backend/flow/plugins/components/collections/kafka/trans_flies.py:52 -msgid " 下发介质包参数:{}" -msgstr "Send media package parameters: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:150 +msgid "卸载中控实例" +msgstr "Uninstall the central control instance" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:64 -msgid "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" -msgstr "{}. Account rule: {}-{}, source ip: {}, target cluster: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:193 +#, fuzzy +#| msgid "TendisplusCluster集群" +msgid "下架TenDB-Cluster集群[{}]" +msgstr "TendisplusCluster cluster" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:70 -msgid "" -"授权规则明细:\n" -"{}\n" -msgstr "" -"Authorization rule details:\n" -"{}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_disable_deploy.py:103 +#, fuzzy +#| msgid "卸载spider实例" +msgid "重启spider实例" +msgstr "Uninstall the spider instance" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:83 -msgid "「授权接口返回结果异常」{}" -msgstr "Authorization interface returns abnormal result {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_enable_deploy.py:137 +#, fuzzy +#| msgid "启动MySQL高可用集群[{}]" +msgid "启用spider集群[{}]" +msgstr "Start MySQL high availability cluster[{}]" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:85 -msgid "「授权接口调用异常」{}" -msgstr "Authorization interface call exception {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:128 +#, fuzzy +#| msgid "{} 全库备份" +msgid "{} 全备" +msgstr "{} full database backup" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:88 -msgid "授权异常,相关信息: {}\n" -msgstr "Authorization exception, related information: {}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:131 +#, fuzzy +#| msgid "构建全库备份流程成功" +msgid "构造全库备份流程成功" +msgstr "The process of building a full database backup is successful" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:95 -msgid "授权整体结果{}" -msgstr "Authorization overall result{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:167 +#, fuzzy +#| msgid "执行库表备份" +msgid "spider 执行全库备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:99 -msgid "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" -msgstr "" -"The number of Excel import authorization lines: {}, the number of successful " -"authorization: {}, the number of failed authorization: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:180 +#, fuzzy +#| msgid "执行库表备份" +msgid "ctl 执行全库备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:108 -msgid "" -"授权结果详情请下载excel: excel 下载" -msgstr "" -"For details of authorization results, please download excel: excel download" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:238 +#, fuzzy +#| msgid "执行库表备份" +msgid "remote 执行全库备份" +msgstr "Execute database table backup" -#: backend/flow/plugins/components/collections/mysql/build_database_table_filter_regex.py:47 -msgid "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" -msgstr "[{}] Success: db_table_filter_regex: {}, db_filter_regex: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:250 +#, fuzzy +#| msgid "{} 全库备份" +msgid "remote 全库备份" +msgstr "{} full database backup" -#: backend/flow/plugins/components/collections/mysql/clear_machine.py:45 -msgid "机器还在系统中注册,暂不用清理[{}]" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:285 +msgid "运维节点执行全库备份" msgstr "" -"The machine is still registered in the system, there is no need to clean " -"up[{}]" -#: backend/flow/plugins/components/collections/mysql/clear_machine.py:50 -msgid "本次操作没有机器可以清理,提前结束活动节点" -msgstr "" -"There is no machine to clean up in this operation, and the active node is " -"terminated early" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:296 +#, fuzzy +#| msgid "库表备份" +msgid "spider_mnt全库备份" +msgstr "Database table backup" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:92 -#: backend/flow/plugins/components/collections/mysql/clone_user.py:61 -msgid "「权限克隆返回结果异常」{}" -msgstr "The return result of permission cloning is abnormal {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:182 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:186 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:190 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:194 +msgid "预清理备份库" +msgstr "Preclean the backup repository" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:94 -#: backend/flow/plugins/components/collections/mysql/clone_user.py:63 -msgid "「权限克隆调用异常」{}" -msgstr "Privilege clone call exception {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:240 +msgid "适配备份库映射" +msgstr "Adapt backup library mapping" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:98 -msgid "权限克隆失败,错误信息: {}\n" -msgstr "Permission clone failed, error message: {}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:246 +msgid "重建备份库" +msgstr "Rebuild the backup library" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:105 -msgid "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" -msgstr "" -"The overall execution result of permission cloning—total: {}, success: {}, " -"failure: {}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:283 +msgid "{} on remote {} 清档" +msgstr "{} on remote {} clear file" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:111 -msgid "" -"详情请下载excel: excel 下载" -msgstr "" -"For details, please download excel: excel " -"download" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:294 +msgid "处理集群表" +msgstr "Working with clustered tables" -#: backend/flow/plugins/components/collections/mysql/clone_user.py:64 -msgid "执行克隆失败!" -msgstr "Failed to execute clone!" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:311 +#, fuzzy +#| msgid "构建清档流程成功" +msgid "构造清档流程成功" +msgstr "Build clearance process succeeded" -#: backend/flow/plugins/components/collections/mysql/create_user.py:52 -msgid "在「{}」创建临时用户「{}@{}」成功" -msgstr "Successfully created temporary user {}@{} at {}" +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:110 +msgid "partition_sql_file_{}_{}_{}_{}.txt" +msgstr "partition_sql_file_{}_{}_{}_{}.txt" -#: backend/flow/plugins/components/collections/mysql/create_user.py:54 -msgid "创建用户接口异常,相关信息: {}" -msgstr "Create user interface exception, related information: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:113 +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:124 +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:145 +msgid "{}: {}" +msgstr "{}: {}" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:38 +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:167 #, fuzzy -#| msgid "在{}执行sql失败,相关信息: {}" -msgid "在「{}」执行sql失败,相关信息: {}" -msgstr "Failed to execute sql in {}, related information: {}" +#| msgid "构建清档流程成功" +msgid "构建spider partition流程成功" +msgstr "Build clearance process succeeded" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:42 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:307 #, fuzzy -#| msgid "在{}执行sql{}失败,相关信息: {}" -msgid "在「{}」执行sql{}失败,相关信息: {}" -msgstr "Failed to execute sql{} in {}, related information: {}" - -#: backend/flow/plugins/components/collections/mysql/drop_user.py:49 -msgid "删除用户接口异常,相关信息: {}" -msgstr "Delete user interface exception, related information: {}" +#| msgid "{} 重命名数据库" +msgid "{} on remote {} 重命名数据库" +msgstr "{} rename database" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:52 -msgid "在「{}」删除临时用户「{}@{}」成功" -msgstr "Successfully deleted temporary user {}@{} at {}" +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:315 +#, fuzzy +#| msgid "删除集群域名" +msgid "删除集群源库" +msgstr "Delete the cluster domain name" -#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:58 -msgid "这是一个fake的模拟执行" -msgstr "This is a simulated execution of a fake" +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:323 +#, fuzzy +#| msgid "重命名数据库列表" +msgid "构造数据库重命名流程成功" +msgstr "Rename database list" -#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:65 -msgid "语义检查执行成功" -msgstr "Semantic check performed successfully" +#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:106 +#, fuzzy +#| msgid "开始添加slave" +msgid "[{}]添加slave集群" +msgstr "Start adding slaves" -#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:91 -msgid "[{}] 过滤所得库表: {}" -msgstr "[{}] Filtered database table: {}" +#: backend/flow/engine/exceptions.py:28 +msgid "组件服务未部署" +msgstr "Component Services is not deployed" -#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:94 -msgid "[{}] 未匹配到任何库" -msgstr "[{}] did not match any libraries" +#: backend/flow/engine/exceptions.py:32 +msgid "MySQL备份位置异常" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:56 -msgid "在{}执行sql失败,相关信息: {}" -msgstr "Failed to execute sql in {}, related information: {}" +#: backend/flow/engine/exceptions.py:37 +msgid "MySQL备份方式和位置不兼容" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:61 -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:68 -msgid "在{}执行sql{}失败,相关信息: {}" -msgstr "Failed to execute sql{} in {}, related information: {}" +#: backend/flow/engine/exceptions.py:38 +#, python-brace-format +msgid "MySQL备份方式{backup_type}和位置{backup_local}不兼容" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:87 -msgid "查询数据库接口异常,相关信息: {}" -msgstr "Query database interface exception, related information: {}" +#: backend/flow/models.py:22 backend/flow/models.py:38 +msgid "流程ID" +msgstr "Process ID" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:90 -msgid "uid:{}" -msgstr "uid:{}" +#: backend/flow/models.py:23 +msgid "流程树" +msgstr "process tree" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:119 -msgid "ERROR 数据不一致的表的数量: {}" -msgstr "ERROR Number of tables with inconsistent data: {}" +#: backend/flow/models.py:25 backend/ticket/serializers.py:108 +msgid "流程状态" +msgstr "process status" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:120 -msgid "WARNING 被跳过校验的表的数量: {}" -msgstr "WARNING Number of tables skipped for validation: {}" +#: backend/flow/models.py:27 +msgid "流程创建人" +msgstr "Process Creator" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:121 -msgid "SUCCESS 数据一致的表的数量: {}" -msgstr "Number of tables with consistent SUCCESS data: {}" +#: backend/flow/models.py:28 +msgid "启动时间" +msgstr "Start Time" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:126 -msgid "ERROR 校验失败,数据不一致的表:" -msgstr "ERROR Validation failed, table with inconsistent data:" +#: backend/flow/models.py:29 +msgid "流程结束时间" +msgstr "process end time" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:132 -msgid "WARNING 校验程序没有校验的表:" -msgstr "WARNING Table not validated by validator:" +#: backend/flow/models.py:40 +msgid "当前版本ID" +msgstr "current version id" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:138 -msgid "SUCCESS 校验成功,数据一致的表:" -msgstr "SUCCESS verification is successful, the table with consistent data:" +#: backend/flow/models.py:42 +msgid "节点状态" +msgstr "node status" -#: backend/flow/plugins/components/collections/mysql/mysql_db_meta.py:41 -#: backend/flow/plugins/components/collections/redis/get_redis_payload.py:45 -#: backend/flow/plugins/components/collections/redis/redis_db_meta.py:46 -#: backend/flow/plugins/components/collections/spider/spider_db_meta.py:40 -msgid "集群元信息:{}" -msgstr "Cluster meta information: {}" +#: backend/flow/models.py:44 +msgid "节点运行时IP" +msgstr "Node runtime IP" -#: backend/flow/plugins/components/collections/mysql/mysql_ha_db_table_backup_response.py:28 -msgid "[{}] 备份 id: {}" -msgstr "[{}] backup id: {}" +#: backend/flow/models.py:46 +msgid "开始执行时间" +msgstr "start execution time" -#: backend/flow/plugins/components/collections/mysql/mysql_master_slave_relationship_check.py:72 -msgid "主备关系校验成功" -msgstr "Master-standby relationship verification succeeded" +#: backend/flow/plugins/components/collections/cloud/exec_service_script.py:58 +#, fuzzy +#| msgid "该节点获取到执行ip信息为空,请联系系统管理员" +msgid "该节点{}获取到执行ip信息为空,请联系系统管理员" +msgstr "" +"The node obtained execution ip information is empty, please contact the " +"system administrator" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:40 -#, fuzzy -#| msgid "创建用户接口异常,相关信息: {}" -msgid "分区管理服务api异常,相关信息: {}" -msgstr "Create user interface exception, related information: {}" +#: backend/flow/plugins/components/collections/cloud/push_config_file.py:56 +#: backend/flow/plugins/components/collections/cloud/trans_files.py:59 +#: backend/flow/plugins/components/collections/es/trans_files.py:63 +#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:70 +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:99 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:85 +#: backend/flow/plugins/components/collections/redis/trans_flies.py:79 +msgid "[{}] 下发介质包参数:{}" +msgstr "[{}] Delivery media package parameters: {}" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:45 -#: backend/flow/plugins/components/collections/mysql/upload_file.py:43 +#: backend/flow/plugins/components/collections/cloud/trans_files.py:44 #, fuzzy -#| msgid "单据id" -msgid "单据id{}" -msgstr "ticket id" +#| msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" +msgid "该节点{}获取到执行ip信息为空,请联系系统管理员{}" +msgstr "" +"The execution ip information obtained by this node is empty, please contact " +"the system administrator {}" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:46 -msgid "获取分区语句成功" -msgstr "Get partition statement succeeded" +#: backend/flow/plugins/components/collections/common/base_service.py:83 +msgid "[{}] 运行成功" +msgstr "[{}] ran successfully" -#: backend/flow/plugins/components/collections/mysql/rename_database_confirm_empty_from.py:69 -msgid "确认源数据库已空完成" -msgstr "Confirm that the source database is empty" +#: backend/flow/plugins/components/collections/common/base_service.py:87 +msgid "[{}] 失败: {}" +msgstr "[{}] fail: {}" -#: backend/flow/plugins/components/collections/mysql/rename_database_drop_from.py:51 -msgid "删除源数据库完成" -msgstr "Delete source database complete" +#: backend/flow/plugins/components/collections/common/base_service.py:216 +msgid "[写入上下文结果失败] failed: {}" +msgstr "[Failed to write context result] failed: {}" -#: backend/flow/plugins/components/collections/mysql/rename_database_prepare_param.py:28 -msgid "[{}] 构造 old_new_map 完成: {}" -msgstr "[{}] Construct old_new_map completed: {}" +#: backend/flow/plugins/components/collections/common/base_service.py:253 +msgid "[{}] 任务正在执行🤔" +msgstr "[{}] Task is executing 🤔" -#: backend/flow/plugins/components/collections/mysql/rollback_trans_flies.py:53 -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:63 -msgid "没有符合的备份文件提供定点恢复" -msgstr "There is no matching backup file to provide fixed-point recovery" +#: backend/flow/plugins/components/collections/common/base_service.py:262 +msgid "[{}] 任务调度失败😱" +msgstr "[{}] Task scheduling failed 😱" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:56 -msgid "创建模拟执行任务resp{}" -msgstr "Create a simulated execution task resp{}" +#: backend/flow/plugins/components/collections/common/base_service.py:273 +msgid "[{}]任务调度成功🥳︎" +msgstr "[{}] Task scheduling succeeded 🥳︎" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:60 -msgid "创建模拟任务失败:{}" -msgstr "Failed to create mock task: {}" +#: backend/flow/plugins/components/collections/common/base_service.py:279 +msgid "[{}]该节点需要获取执行后日志,赋值到trans_data" +msgstr "" +"[{}] This node needs to obtain the post-execution log and assign it to " +"trans_data" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:62 -msgid "创建模拟任务成功" -msgstr "Create mock task successfully" +#: backend/flow/plugins/components/collections/common/base_service.py:290 +msgid "[{}] 获取执行后日志失败,获取ip[{}]" +msgstr "[{}] Failed to get log after execution, get ip[{}]" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:66 -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:68 -msgid "「执行语义分析任务异常」{}" -msgstr "Execution of semantic analysis task exception {}" +#: backend/flow/plugins/components/collections/common/bigdata_manager_service.py:123 +#, fuzzy +#| msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" +msgid "无法找到Manager处理类型,请联系系统管理员:{}" +msgstr "" +"Unable to adapt to the incoming domain name processing type, please contact " +"the system administrator: {}" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:69 -msgid "创建模拟任务失败!" -msgstr "Failed to create simulation task!" +#: backend/flow/plugins/components/collections/common/create_ticket.py:36 +msgid "未知单据类型, {}不存在于已知单据类型中" +msgstr "Unknown ticket type, {} does not exist in known ticket types" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:119 -msgid "语义检查出发的自动创建单据" -msgstr "Automatic creation of tickets starting from semantic check" +#: backend/flow/plugins/components/collections/common/create_ticket.py:41 +msgid "不允许自动创建单据,单据创建流程结束" +msgstr "" +"Automatic ticket creation is not allowed, and the ticket creation process " +"ends" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:42 -msgid "仅在主库查找备份源" -msgstr "Find the backup source only in the main library" +#: backend/flow/plugins/components/collections/common/external_service.py:36 +msgid "第三方接口: {} 请求成功! 返回参数为: {}" +msgstr "" +"Third-party interface: {} The request is successful! The return parameter " +"is: {}" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:46 -msgid "在主、从库查找备份源" -msgstr "Find the backup source in the master and slave libraries" +#: backend/flow/plugins/components/collections/common/external_service.py:38 +#, fuzzy +#| msgid "权限克隆失败,错误信息: {}\n" +msgid "第三方接口:{} 调用失败!错误信息为: {}" +msgstr "Permission clone failed, error message: {}\n" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:50 -msgid "从备份源中筛选符合的备份" -msgstr "Filter matching backups from backup sources" +#: backend/flow/plugins/components/collections/common/external_service.py:40 +#, fuzzy +#| msgid "权限克隆失败,错误信息: {}\n" +msgid "请求遇到未知错误!错误信息为: {}" +msgstr "Permission clone failed, error message: {}\n" -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:66 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:52 -msgid "" -"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" -"{}" +#: backend/flow/plugins/components/collections/common/pause.py:44 +msgid "【{}】自动化流程待确认,是否继续?" msgstr "" -"Select the file transfer mode between servers. The machine ip list that " -"should be the source file cannot be empty. Please contact the system " -"administrator{}" +"【{}】The automated process is pending confirmation. Do you want to continue?" -#: backend/flow/plugins/components/collections/mysql/truncate_data_create_stage_database.py:55 -msgid "建立备份库完成" -msgstr "Create a backup db complete" +#: backend/flow/plugins/components/collections/common/pause.py:78 +msgid "回调数据" +msgstr "callback data" -#: backend/flow/plugins/components/collections/mysql/truncate_data_drop_stage_database.py:49 -msgid "删除备份库完成" -msgstr "Deleting the backup repository is complete" +#: backend/flow/plugins/components/collections/common/pause.py:87 +#: backend/ticket/constants.py:315 +msgid "暂停" +msgstr "pause" -#: backend/flow/plugins/components/collections/mysql/truncate_data_generate_stage_database_name.py:31 -msgid "生成备份库名完成" -msgstr "Generate backup db name complete" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:38 +msgid "{}-空闲检查" +msgstr "{} - idle check" -#: backend/flow/plugins/components/collections/mysql/truncate_data_recreate_table.py:60 -msgid "重建表成功" -msgstr "rebuild table successfully" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:70 +#: backend/flow/plugins/components/collections/common/sa_init.py:66 +msgid "空闲检查失败" +msgstr "idle check failed" -#: backend/flow/plugins/components/collections/mysql/truncate_data_rename_table.py:88 -msgid "[{}] 备份清档表完成" -msgstr "[{}] Backup cleanup table completed" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:72 +#: backend/flow/plugins/components/collections/common/sa_init.py:68 +msgid "任务状态异常{}" +msgstr "The task status is abnormal {}" -#: backend/flow/plugins/components/collections/mysql/upload_file.py:38 -msgid "分区sql为空无需上传" -msgstr "Partition sql is empty and no need to upload" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:85 +msgid "错误详情{}" +msgstr "error details{}" -#: backend/flow/plugins/components/collections/mysql/upload_file.py:44 -#, fuzzy -#| msgid "文件上传" -msgid "分区sql文件上传成功" -msgstr "File Upload" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:90 +msgid "sa空闲检查" +msgstr "sa idle check" -#: backend/flow/plugins/components/collections/pulsar/blank_schedule_service.py:66 -msgid "successfully enter blank schedule, interval times: {}" -msgstr "successfully enter blank schedule, interval times: {}" +#: backend/flow/plugins/components/collections/common/sa_init.py:35 +msgid "SA初始化" +msgstr "SA initialization" -#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:100 -msgid "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" -msgstr "" -"[{}] kwargs['payload'] is incomplete, you need to add {} content to " -"payload" +#: backend/flow/plugins/components/collections/common/sa_init.py:82 +msgid "sa初始化" +msgstr "sa initialization" -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:113 -msgid "无符合要求机器" -msgstr "No matching machine" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:50 +msgid "定时时间" +msgstr "Timing" -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:117 -msgid "获取最大磁盘空闲机器失败:{}" -msgstr "Failed to get max disk free machines: {}" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:53 +#, python-format +msgid "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" +msgstr "Timing time, the format is seconds (s) or (%%Y-%%m-%%d %%H:%%M:%%S)" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:393 -msgid "源redis集群{}存在{}个非running状态的slave" -msgstr "There are {} non-running slaves in the source redis cluster {}" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:56 +msgid "是否强制晚于当前时间" +msgstr "Whether to force later than the current time" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:450 -msgid "所有源redis slave机器:{} 磁盘空间检查通过" -msgstr "All source redis slave machines: {} disk space check passed" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:59 +msgid "" +"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" +msgstr "" +"Whether to force the time to be later than the current time when the user " +"enters the date format, only valid for timing input in the date format" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:461 -msgid "src_cluster:{} type:{} 无需检查cluster nodes是否ok" -msgstr "src_cluster:{} type:{} No need to check whether the cluster nodes are ok" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:83 +#, python-format +msgid "输入参数%s不符合【时区(+08:00、-08:00)】格式" +msgstr "" +"The input parameter %s does not conform to the [time zone (+08:00, -08:00)] " +"format" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:523 -msgid "src_cluster:{} 类型是:{} 无需检查cluster state" -msgstr "src_cluster: {} type is: {} no need to check cluster state" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:98 +msgid "定时时间需晚于当前时间" +msgstr "The timing time needs to be later than the current time" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:696 -msgid "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} Some tasks migration failed" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:106 +#, python-format +msgid "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" +msgstr "" +"The input parameter %s does not conform to the [second (s) or time (%%Y-%%m-" +"%%d %%H:%%M:%%S)] format" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:705 -msgid "" -"bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} All tasks are successful and the migration process is terminated" +#: backend/flow/plugins/components/collections/es/es_dns_manage.py:61 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:37 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:48 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:75 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:57 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:69 +#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:29 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:43 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:78 +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:44 +msgid "该节点获取到执行ip信息为空,请联系系统管理员" +msgstr "" +"The node obtained execution ip information is empty, please contact the " +"system administrator" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:715 -msgid "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} All tasks are incremental synchronization" +#: backend/flow/plugins/components/collections/es/es_dns_manage.py:146 +#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:71 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:93 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:84 +#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:61 +#: backend/flow/plugins/components/collections/pulsar/pulsar_zk_dns_manage.py:51 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:84 +msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" +msgstr "" +"Unable to adapt to the incoming domain name processing type, please contact " +"the system administrator: {}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:798 -msgid "task:{} {}:{} 迁移失败" -msgstr "task:{} {}:{} migration failed" +#: backend/flow/plugins/components/collections/es/exec_es_actuator_script.py:65 +#: backend/flow/plugins/components/collections/es/trans_files.py:47 +#: backend/flow/plugins/components/collections/hdfs/exec_actuator_script.py:69 +#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:53 +#: backend/flow/plugins/components/collections/influxdb/exec_actuator_script.py:62 +#: backend/flow/plugins/components/collections/kafka/exec_actuator_script.py:62 +#: backend/flow/plugins/components/collections/mysql/exec_actuator_script.py:103 +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:60 +#: backend/flow/plugins/components/collections/pulsar/exec_actuator_script.py:66 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:46 +#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:82 +#: backend/flow/plugins/components/collections/redis/trans_flies.py:61 +msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" +msgstr "" +"The execution ip information obtained by this node is empty, please contact " +"the system administrator {}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:863 -msgid "{}中有{}个proxy不是running状态" -msgstr "{} proxy in {} is not running" +#: backend/flow/plugins/components/collections/es/get_es_resource.py:57 +#: backend/flow/plugins/components/collections/kafka/get_kafka_resource.py:50 +msgid "获取机器资源成功成功。 {}" +msgstr "Acquiring the machine resource was successful. {}" -#: backend/flow/plugins/components/collections/redis/trans_flies.py:87 +#: backend/flow/plugins/components/collections/hdfs/get_hdfs_resource.py:61 #, fuzzy -#| msgid "下发介质包失败:resp: {}" -msgid "下发介质包失败: [{}/{}] resp:{}" -msgstr "Failed to deliver media package: resp: {}" +#| msgid "获取机器资源成功成功。 {}" +msgid "获取机器资源成功。 {}" +msgstr "Acquiring the machine resource was successful. {}" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:70 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:80 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:91 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:112 -msgid "在[{}]创建添加内置账号成功" -msgstr "Created and added built-in account in [{}] successfully" +#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:48 +msgid "获取DNS操作IP为空" +msgstr "Get DNS operation IP is empty" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:72 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:82 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:93 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:114 -#, fuzzy -#| msgid "删除用户接口异常,相关信息: {}" -msgid "[{}]添加用户接口异常,相关信息: {}" -msgstr "Delete user interface exception, related information: {}" +#: backend/flow/plugins/components/collections/hdfs/update_hdfs_resource.py:67 +msgid "更新机器资源成功成功。 {}" +msgstr "Updating the machine resource succeeded successfully. {}" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:118 -msgid "[{}]根据单据类型活动节点找不到对应的授权方式。" -msgstr "[{}] According to the document type, the active node cannot find the corresponding authorization method." +#: backend/flow/plugins/components/collections/influxdb/trans_flies.py:52 +#: backend/flow/plugins/components/collections/kafka/trans_flies.py:52 +msgid " 下发介质包参数:{}" +msgstr "Send media package parameters: {}" -#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:45 -#, fuzzy -#| msgid "检查源数据库是否在用" -msgid "{} {} 检查库表是否在用" -msgstr "Check if the source database is in use" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:64 +msgid "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" +msgstr "{}. Account rule: {}-{}, source ip: {}, target cluster: {}" -#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:50 -#, fuzzy -#| msgid "检查源数据库是否在用" -msgid "{} 检查库表是否在用" -msgstr "Check if the source database is in use" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:70 +msgid "" +"授权规则明细:\n" +"{}\n" +msgstr "" +"Authorization rule details:\n" +"{}\n" -#: backend/flow/plugins/components/collections/spider/clear_database_on_remote_service.py:56 -msgid "remote drop 新库完成" -msgstr "remote drop new library completed" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:83 +msgid "「授权接口返回结果异常」{}" +msgstr "Authorization interface returns abnormal result {}" -#: backend/flow/plugins/components/collections/spider/create_database_like_via_ctl.py:110 -msgid "建立集群备份库表完成" -msgstr "The establishment of the cluster backup library table is completed" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:85 +msgid "「授权接口调用异常」{}" +msgstr "Authorization interface call exception {}" -#: backend/flow/plugins/components/collections/spider/drop_spider_table_via_ctl.py:49 -#, fuzzy -#| msgid "删除源数据库完成" -msgid "删除老数据库完成" -msgstr "Delete source database complete" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:88 +msgid "授权异常,相关信息: {}\n" +msgstr "Authorization exception, related information: {}\n" -#: backend/flow/plugins/components/collections/spider/truncate_database_drop_stage_db_via_ctl.py:47 -#, fuzzy -#| msgid "建立备份库完成" -msgid "清理备份库完成" -msgstr "Create a backup db complete" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:95 +msgid "授权整体结果{}" +msgstr "Authorization overall result{}" -#: backend/flow/plugins/components/collections/spider/truncate_database_on_spider_via_ctl.py:145 -msgid "处理集群表完成" -msgstr "Processing cluster table complete" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:99 +msgid "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" +msgstr "" +"The number of Excel import authorization lines: {}, the number of successful " +"authorization: {}, the number of failed authorization: {}" -#: backend/flow/signal/handlers.py:35 -msgid "【状态信号捕获】{} root_id={}, node_id={}, status:{}" -msgstr "【Status signal capture】{} root_id={}, node_id={}, status:{}" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:108 +msgid "" +"授权结果详情请下载excel: excel 下载" +msgstr "" +"For details of authorization results, please download excel: excel download" -#: backend/flow/signal/handlers.py:68 -msgid "【状态信号捕获】未查找到FlowTree root_id={}" -msgstr "[Status signal capture] FlowTree root_id={} not found" +#: backend/flow/plugins/components/collections/mysql/build_database_table_filter_regex.py:47 +msgid "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" +msgstr "[{}] Success: db_table_filter_regex: {}, db_filter_regex: {}" -#: backend/flow/utils/cc_manage.py:55 -msgid "查询主机bk_host_id失败[数量不匹配]" -msgstr "Failed to query host bk_host_id [number does not match]" +#: backend/flow/plugins/components/collections/mysql/clear_machine.py:45 +msgid "机器还在系统中注册,暂不用清理[{}]" +msgstr "" +"The machine is still registered in the system, there is no need to clean " +"up[{}]" -#: backend/flow/utils/cc_manage.py:67 -msgid "查询空闲机模块ID bk_module_id 失败" -msgstr "Failed to query the idle machine module ID bk_module_id" +#: backend/flow/plugins/components/collections/mysql/clear_machine.py:50 +msgid "本次操作没有机器可以清理,提前结束活动节点" +msgstr "" +"There is no machine to clean up in this operation, and the active node is " +"terminated early" -#: backend/flow/utils/cloud/cloud_act_payload.py:42 -msgid "单据中不包含DRS的部署信息" -msgstr "The document does not contain the deployment information of DRS" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:92 +#: backend/flow/plugins/components/collections/mysql/clone_user.py:61 +msgid "「权限克隆返回结果异常」{}" +msgstr "The return result of permission cloning is abnormal {}" -#: backend/flow/utils/cloud/cloud_act_payload.py:50 -msgid "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" -msgstr "" -"The DNS service has not been deployed, please deploy the service after the " -"DNS service is deployed" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:94 +#: backend/flow/plugins/components/collections/mysql/clone_user.py:63 +msgid "「权限克隆调用异常」{}" +msgstr "Privilege clone call exception {}" -#: backend/flow/utils/cloud/cloud_act_payload.py:58 -msgid "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" -msgstr "" -"The Nginx service is not deployed, please deploy the service after the Nginx " -"service is deployed" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:98 +msgid "权限克隆失败,错误信息: {}\n" +msgstr "Permission clone failed, error message: {}\n" -#: backend/flow/utils/cloud/cloud_db_proxy.py:52 -#, fuzzy -#| msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" -msgid "找不到单据类型需要变更的proxy函数,服务信息入库失败" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:105 +msgid "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" msgstr "" -"The cmdb function that needs to be changed cannot be found, please contact " -"the system administrator" +"The overall execution result of permission cloning—total: {}, success: {}, " +"failure: {}\n" -#: backend/flow/utils/cloud/cloud_module_operate.py:135 -#, fuzzy -#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" -msgid "主机{}转移{}失败,转移参数:{}, 错误信息:{}" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:111 +msgid "" +"详情请下载excel: excel 下载" msgstr "" -"The transfer of host {} failed, transfer parameters: {}, error message: {}" +"For details, please download excel: excel " +"download" -#: backend/flow/utils/cloud/cloud_module_operate.py:196 -#, fuzzy -#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" -msgid "主机{}转移待回收失败,错误信息:{}" -msgstr "" -"The transfer of host {} failed, transfer parameters: {}, error message: {}" +#: backend/flow/plugins/components/collections/mysql/clone_user.py:64 +msgid "执行克隆失败!" +msgstr "Failed to execute clone!" -#: backend/flow/utils/es/es_db_meta.py:94 -msgid "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" -msgstr "" -"The cmdb function {} that needs to be changed cannot be found, please " -"contact the system administrator" +#: backend/flow/plugins/components/collections/mysql/create_user.py:52 +msgid "在「{}」创建临时用户「{}@{}」成功" +msgstr "Successfully created temporary user {}@{} at {}" -#: backend/flow/utils/hdfs/hdfs_db_meta.py:52 -#: backend/flow/utils/influxdb/influxdb_db_meta.py:114 -#: backend/flow/utils/kafka/kafka_db_meta.py:160 -#: backend/flow/utils/redis/redis_db_meta.py:49 -msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" -msgstr "" -"The cmdb function that needs to be changed cannot be found, please contact " -"the system administrator" +#: backend/flow/plugins/components/collections/mysql/create_user.py:54 +msgid "创建用户接口异常,相关信息: {}" +msgstr "Create user interface exception, related information: {}" -#: backend/flow/utils/mysql/db_resource.py:106 -#: backend/flow/utils/redis/db_resource.py:106 +#: backend/flow/plugins/components/collections/mysql/drop_user.py:38 #, fuzzy -#| msgid "在资源池获取资源失败" -msgid " 获取资源失败: {}" -msgstr "Failed to obtain resource from resource pool" - -#: backend/flow/utils/mysql/db_table_filter/exception.py:18 -msgid "库表过滤异常" -msgstr "Database table filtering exception" +#| msgid "在{}执行sql失败,相关信息: {}" +msgid "在「{}」执行sql失败,相关信息: {}" +msgstr "Failed to execute sql in {}, related information: {}" -#: backend/flow/utils/mysql/db_table_filter/exception.py:23 -msgid "输入校验异常" -msgstr "input validation exception" +#: backend/flow/plugins/components/collections/mysql/drop_user.py:42 +#, fuzzy +#| msgid "在{}执行sql{}失败,相关信息: {}" +msgid "在「{}」执行sql{}失败,相关信息: {}" +msgstr "Failed to execute sql{} in {}, related information: {}" -#: backend/flow/utils/mysql/db_table_filter/filter.py:42 -msgid "include patterns 不能为空" -msgstr "include patterns cannot be empty" +#: backend/flow/plugins/components/collections/mysql/drop_user.py:49 +msgid "删除用户接口异常,相关信息: {}" +msgstr "Delete user interface exception, related information: {}" -#: backend/flow/utils/mysql/db_table_filter/filter.py:48 -msgid "exclude patterns 要么同时为空, 要么都不为空" -msgstr "" -"exclude patterns are either empty at the same time, or none of them are empty" +#: backend/flow/plugins/components/collections/mysql/drop_user.py:52 +msgid "在「{}」删除临时用户「{}@{}」成功" +msgstr "Successfully deleted temporary user {}@{} at {}" -#: backend/flow/utils/mysql/db_table_filter/tools.py:30 -msgid "使用通配符时, 只能有一个模式: {}" -msgstr "When using wildcards, there can only be one pattern: {}" +#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:58 +msgid "这是一个fake的模拟执行" +msgstr "This is a simulated execution of a fake" -#: backend/flow/utils/mysql/db_table_filter/tools.py:33 -msgid "% ? 不能独立使用" -msgstr "% ? cannot be used independently" +#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:65 +msgid "语义检查执行成功" +msgstr "Semantic check performed successfully" -#: backend/flow/utils/mysql/db_table_filter/tools.py:36 -msgid "* 只能独立使用" -msgstr "* can only be used independently" +#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:91 +msgid "[{}] 过滤所得库表: {}" +msgstr "[{}] Filtered database table: {}" -#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:27 -msgid "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" -msgstr "" -"The exec_ip variable and the get_trans_data_ip_var variable cannot be " -"assigned at the same time" +#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:94 +msgid "[{}] 未匹配到任何库" +msgstr "[{}] did not match any libraries" -#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:29 -msgid "exec_ip变量和get_trans_data_ip_var变量不能同时为None" -msgstr "" -"The exec_ip variable and the get_trans_data_ip_var variable cannot be None " -"at the same time" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:56 +msgid "在{}执行sql失败,相关信息: {}" +msgstr "Failed to execute sql in {}, related information: {}" -#: backend/flow/utils/mysql/mysql_act_playload.py:337 -msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" -msgstr "" -"The incoming mysql port list is empty or an illegal value, please contact " -"the system administrator" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:61 +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:68 +msgid "在{}执行sql{}失败,相关信息: {}" +msgstr "Failed to execute sql{} in {}, related information: {}" -#: backend/flow/utils/mysql/mysql_act_playload.py:381 -#, fuzzy -#| msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" -msgid "传入的安装spider端口列表为空或者非法值,请联系系统管理员" -msgstr "" -"The incoming mysql port list is empty or an illegal value, please contact " -"the system administrator" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:87 +msgid "查询数据库接口异常,相关信息: {}" +msgstr "Query database interface exception, related information: {}" -#: backend/flow/utils/pulsar/consts.py:20 -msgid "broker默认分区数" -msgstr "broker default number of partitions" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:90 +msgid "uid:{}" +msgstr "uid:{}" -#: backend/flow/utils/pulsar/consts.py:21 -msgid "broker认证配置" -msgstr "Broker authentication configuration" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:119 +msgid "ERROR 数据不一致的表的数量: {}" +msgstr "ERROR Number of tables with inconsistent data: {}" -#: backend/flow/utils/pulsar/consts.py:22 -msgid "默认bookie池大小" -msgstr "Default bookie pool size" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:120 +msgid "WARNING 被跳过校验的表的数量: {}" +msgstr "WARNING Number of tables skipped for validation: {}" -#: backend/flow/utils/pulsar/consts.py:23 -msgid "写入副本数" -msgstr "Write replicas" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:121 +msgid "SUCCESS 数据一致的表的数量: {}" +msgstr "Number of tables with consistent SUCCESS data: {}" -#: backend/flow/utils/pulsar/consts.py:24 -msgid "确认写入副本数" -msgstr "Acknowledge the number of replicas written" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:126 +msgid "ERROR 校验失败,数据不一致的表:" +msgstr "ERROR Validation failed, table with inconsistent data:" -#: backend/flow/utils/pulsar/consts.py:25 -msgid "数据保留时间,单位为分钟" -msgstr "Data retention time, in minutes" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:132 +msgid "WARNING 校验程序没有校验的表:" +msgstr "WARNING Table not validated by validator:" -#: backend/flow/utils/pulsar/consts.py:26 -msgid "broker服务端口" -msgstr "broker service port" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:138 +msgid "SUCCESS 校验成功,数据一致的表:" +msgstr "SUCCESS verification is successful, the table with consistent data:" -#: backend/flow/utils/pulsar/consts.py:27 -msgid "访问Pulsar Manager账户名" -msgstr "Access Pulsar Manager account name" +#: backend/flow/plugins/components/collections/mysql/mysql_db_meta.py:41 +#: backend/flow/plugins/components/collections/redis/get_redis_payload.py:45 +#: backend/flow/plugins/components/collections/redis/redis_db_meta.py:45 +#: backend/flow/plugins/components/collections/spider/spider_db_meta.py:40 +msgid "集群元信息:{}" +msgstr "Cluster meta information: {}" -#: backend/flow/utils/pulsar/consts.py:28 -msgid "访问Pulsar Manager密码" -msgstr "Access Pulsar Manager Password" +#: backend/flow/plugins/components/collections/mysql/mysql_link_backup_id_bill_id.py:28 +msgid "[{}] 备份 id: {}" +msgstr "[{}] backup id: {}" -#: backend/flow/utils/redis/redis_db_meta.py:57 -msgid "找不到单据类型需要查询的cmdb函数,请联系系统管理员" -msgstr "" -"The cmdb function that needs to be queried for the ticket type cannot be " -"found, please contact the system administrator" +#: backend/flow/plugins/components/collections/mysql/mysql_master_slave_relationship_check.py:72 +msgid "主备关系校验成功" +msgstr "Master-standby relationship verification succeeded" -#: backend/flow/views/cloud_dbha_apply.py:39 -#: backend/flow/views/cloud_dns_bind_apply.py:39 +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:40 #, fuzzy -#| msgid "开始部署ES场景" -msgid "开始部署dns-bind服务场景" -msgstr "Start deploying ES scenarios" +#| msgid "创建用户接口异常,相关信息: {}" +msgid "分区管理服务api异常,相关信息: {}" +msgstr "Create user interface exception, related information: {}" -#: backend/flow/views/cloud_drs_apply.py:44 +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:45 +#: backend/flow/plugins/components/collections/mysql/upload_file.py:43 #, fuzzy -#| msgid "开始部署ES场景" -msgid "开始部署drs服务场景" -msgstr "Start deploying ES scenarios" +#| msgid "单据id" +msgid "单据id{}" +msgstr "ticket id" -#: backend/flow/views/cloud_nginx_apply.py:44 -#, fuzzy -#| msgid "开始部署ES场景" -msgid "开始部署nginx服务场景" -msgstr "Start deploying ES scenarios" +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:46 +msgid "获取分区语句成功" +msgstr "Get partition statement succeeded" -#: backend/flow/views/cloud_nginx_apply.py:54 -#, fuzzy -#| msgid "开始部署ES场景" -msgid "开始替换nginx服务场景" -msgstr "Start deploying ES scenarios" +#: backend/flow/plugins/components/collections/mysql/rename_database_confirm_empty_from.py:69 +msgid "确认源数据库已空完成" +msgstr "Confirm that the source database is empty" -#: backend/flow/views/es_apply.py:63 -msgid "开始部署ES场景" -msgstr "Start deploying ES scenarios" +#: backend/flow/plugins/components/collections/mysql/rename_database_drop_from.py:51 +msgid "删除源数据库完成" +msgstr "Delete source database complete" -#: backend/flow/views/es_destroy.py:39 -msgid "开始下架ES场景" -msgstr "Start to remove the ES scene" +#: backend/flow/plugins/components/collections/mysql/rename_database_prepare_param.py:28 +msgid "[{}] 构造 old_new_map 完成: {}" +msgstr "[{}] Construct old_new_map completed: {}" -#: backend/flow/views/es_disable.py:39 -msgid "开始禁用ES场景" -msgstr "Start disabling ES scenes" +#: backend/flow/plugins/components/collections/mysql/rollback_trans_flies.py:53 +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:63 +msgid "没有符合的备份文件提供定点恢复" +msgstr "There is no matching backup file to provide fixed-point recovery" -#: backend/flow/views/es_enable.py:39 -msgid "开始启用ES场景" -msgstr "Start to enable ES scene" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:56 +msgid "创建模拟执行任务resp{}" +msgstr "Create a simulated execution task resp{}" -#: backend/flow/views/es_reboot.py:47 -msgid "开始重启ES节点场景" -msgstr "Start restarting the ES node scenario" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:60 +msgid "创建模拟任务失败:{}" +msgstr "Failed to create mock task: {}" -#: backend/flow/views/es_replace.py:63 backend/flow/views/es_scale_up.py:52 -msgid "开始扩容ES场景" -msgstr "Start to expand the ES scene" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:62 +msgid "创建模拟任务成功" +msgstr "Create mock task successfully" -#: backend/flow/views/es_shrink.py:52 -msgid "开始缩容ES场景" -msgstr "Start shrinking the ES scene" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:66 +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:68 +msgid "「执行语义分析任务异常」{}" +msgstr "Execution of semantic analysis task exception {}" -#: backend/flow/views/hdfs_apply.py:61 -msgid "开始部署HDFS场景" -msgstr "Start deploying HDFS scenarios" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:69 +msgid "创建模拟任务失败!" +msgstr "Failed to create simulation task!" -#: backend/flow/views/hdfs_destroy.py:39 -msgid "开始HDFS集群销毁场景" -msgstr "Start the HDFS cluster destruction scenario" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:119 +msgid "语义检查出发的自动创建单据" +msgstr "Automatic creation of tickets starting from semantic check" -#: backend/flow/views/hdfs_disable.py:39 -#, fuzzy -#| msgid "HDFS集群禁用" -msgid "开始HDFS集群禁用场景" -msgstr "HDFS cluster disabled" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:42 +msgid "仅在主库查找备份源" +msgstr "Find the backup source only in the main library" -#: backend/flow/views/hdfs_enable.py:39 -#, fuzzy -#| msgid "HDFS 集群启用" -msgid "开始HDFS集群启用场景" -msgstr "HDFS cluster enabled" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:46 +msgid "在主、从库查找备份源" +msgstr "Find the backup source in the master and slave libraries" -#: backend/flow/views/hdfs_reboot.py:55 -msgid "开始重启HDFS场景" -msgstr "Start to restart the HDFS scene" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:50 +msgid "从备份源中筛选符合的备份" +msgstr "Filter matching backups from backup sources" -#: backend/flow/views/hdfs_replace.py:65 -msgid "开始替换HDFS场景" -msgstr "Start to replace the HDFS scene" +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:66 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:52 +msgid "" +"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" +"{}" +msgstr "" +"Select the file transfer mode between servers. The machine ip list that " +"should be the source file cannot be empty. Please contact the system " +"administrator{}" -#: backend/flow/views/hdfs_scale_up.py:42 -msgid "开始扩容HDFS场景" -msgstr "Start expanding the HDFS scene" +#: backend/flow/plugins/components/collections/mysql/truncate_data_create_stage_database.py:55 +msgid "建立备份库完成" +msgstr "Create a backup db complete" -#: backend/flow/views/hdfs_shrink.py:42 -#, fuzzy -#| msgid "HDFS 集群缩容" -msgid "开始HDFS集群缩容场景" -msgstr "HDFS cluster shrink" +#: backend/flow/plugins/components/collections/mysql/truncate_data_drop_stage_database.py:49 +msgid "删除备份库完成" +msgstr "Deleting the backup repository is complete" -#: backend/flow/views/influxdb_apply.py:57 -#, fuzzy -#| msgid "开始部署ES场景" -msgid "开始部署influxdb场景" -msgstr "Start deploying ES scenarios" +#: backend/flow/plugins/components/collections/mysql/truncate_data_generate_stage_database_name.py:31 +msgid "生成备份库名完成" +msgstr "Generate backup db name complete" -#: backend/flow/views/influxdb_destroy.py:39 -#, fuzzy -#| msgid "开始下架ES场景" -msgid "开始下架Influxdb场景" -msgstr "Start to remove the ES scene" +#: backend/flow/plugins/components/collections/mysql/truncate_data_recreate_table.py:60 +msgid "重建表成功" +msgstr "rebuild table successfully" -#: backend/flow/views/influxdb_disable.py:39 -#, fuzzy -#| msgid "开始禁用ES场景" -msgid "开始禁用Influxdb场景" -msgstr "Start disabling ES scenes" +#: backend/flow/plugins/components/collections/mysql/truncate_data_rename_table.py:88 +msgid "[{}] 备份清档表完成" +msgstr "[{}] Backup cleanup table completed" -#: backend/flow/views/influxdb_enable.py:39 -#, fuzzy -#| msgid "开始启用ES场景" -msgid "开始启用Influxdb场景" -msgstr "Start to enable ES scene" +#: backend/flow/plugins/components/collections/mysql/upload_file.py:38 +msgid "分区sql为空无需上传" +msgstr "Partition sql is empty and no need to upload" -#: backend/flow/views/influxdb_reboot.py:47 +#: backend/flow/plugins/components/collections/mysql/upload_file.py:44 #, fuzzy -#| msgid "开始重启ES节点场景" -msgid "开始重启Influxdb节点场景" -msgstr "Start restarting the ES node scenario" +#| msgid "文件上传" +msgid "分区sql文件上传成功" +msgstr "File Upload" -#: backend/flow/views/influxdb_replace.py:49 -#, fuzzy -#| msgid "开始替换kafka场景" -msgid "开始替换influxdb场景" -msgstr "Start to replace the kafka scene" +#: backend/flow/plugins/components/collections/pulsar/blank_schedule_service.py:66 +msgid "successfully enter blank schedule, interval times: {}" +msgstr "successfully enter blank schedule, interval times: {}" -#: backend/flow/views/kafka_apply.py:70 -msgid "开始部署kafka场景" -msgstr "Start deploying kafka scenarios" +#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:100 +msgid "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" +msgstr "" +"[{}] kwargs['payload'] is incomplete, you need to add {} content to " +"payload" -#: backend/flow/views/kafka_destroy.py:39 -msgid "开始下架Kafka场景" -msgstr "Start to remove the Kafka scene" +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:113 +msgid "无符合要求机器" +msgstr "No matching machine" -#: backend/flow/views/kafka_disable.py:39 -msgid "开始禁用Kafka场景" -msgstr "Start disabling the Kafka scene" +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:117 +msgid "获取最大磁盘空闲机器失败:{}" +msgstr "Failed to get max disk free machines: {}" -#: backend/flow/views/kafka_enable.py:39 -msgid "开始启用Kafka场景" -msgstr "Start to enable the Kafka scene" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:393 +msgid "源redis集群{}存在{}个非running状态的slave" +msgstr "There are {} non-running slaves in the source redis cluster {}" -#: backend/flow/views/kafka_reboot.py:47 -msgid "开始重启Kafka节点场景" -msgstr "Start restarting the Kafka node scenario" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:450 +msgid "所有源redis slave机器:{} 磁盘空间检查通过" +msgstr "All source redis slave machines: {} disk space check passed" -#: backend/flow/views/kafka_replace.py:51 -msgid "开始替换kafka场景" -msgstr "Start to replace the kafka scene" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:461 +msgid "src_cluster:{} type:{} 无需检查cluster nodes是否ok" +msgstr "" +"src_cluster:{} type:{} No need to check whether the cluster nodes are ok" -#: backend/flow/views/kafka_scale_up.py:49 -msgid "开始扩容kafka场景" -msgstr "Start to expand the kafka scene" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:523 +msgid "src_cluster:{} 类型是:{} 无需检查cluster state" +msgstr "src_cluster: {} type is: {} no need to check cluster state" -#: backend/flow/views/kafka_shrink.py:44 -msgid "开始缩容kafka场景" -msgstr "Start shrinking the kafka scene" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:696 +msgid "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" +msgstr "bill_id:{} src_cluster:{} dst_cluster:{} Some tasks migration failed" -#: backend/flow/views/mysql_add_slave.py:44 -msgid "开始添加slave" -msgstr "Start adding slaves" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:705 +msgid "" +"bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" +msgstr "" +"bill_id:{} src_cluster:{} dst_cluster:{} All tasks are successful and the " +"migration process is terminated" -#: backend/flow/views/mysql_edit_config.py:60 -msgid "开始下发修改的参数" -msgstr "Start sending the modified parameters" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:715 +msgid "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" +msgstr "" +"bill_id:{} src_cluster:{} dst_cluster:{} All tasks are incremental " +"synchronization" -#: backend/flow/views/mysql_flashback.py:49 -#, fuzzy -#| msgid "flashback信息" -msgid "开始flashback" -msgstr "flashback information" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:797 +msgid "task:{} {}:{} 迁移失败" +msgstr "task:{} {}:{} migration failed" -#: backend/flow/views/mysql_ha_db_table_backup.py:32 -#, fuzzy -#| msgid "库表备份" -msgid "开始库表备份场景" -msgstr "Database table backup" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:862 +msgid "{}中有{}个proxy不是running状态" +msgstr "{} proxy in {} is not running" -#: backend/flow/views/mysql_ha_destroy.py:31 -msgid "开始回收mysql主从版场景" -msgstr "Start to recycle the mysql master-slave version scenario" +#: backend/flow/plugins/components/collections/redis/trans_flies.py:87 +#, fuzzy +#| msgid "下发介质包失败:resp: {}" +msgid "下发介质包失败: [{}/{}] resp:{}" +msgstr "Failed to deliver media package: resp: {}" -#: backend/flow/views/mysql_ha_destroy.py:49 -msgid "开始禁用mysql主从版场景" -msgstr "Start to disable the mysql master-slave version scenario" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:60 +msgid "select mysql.servers failed: {}" +msgstr "" -#: backend/flow/views/mysql_ha_destroy.py:65 -msgid "开始启动mysql主从版场景" -msgstr "Start the mysql master-slave version scenario" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:94 +msgid "TdbCtl-create-node failed: {}" +msgstr "" -#: backend/flow/views/mysql_ha_full_backup.py:32 -#, fuzzy -#| msgid "全库备份执行" -msgid "开始全库备份场景" -msgstr "Full database backup execution" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:142 +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:148 +#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:23 +msgid "在[{}]创建添加内置账号成功" +msgstr "Created and added built-in account in [{}] successfully" -#: backend/flow/views/mysql_ha_master_fail_over.py:30 +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:151 +#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:25 #, fuzzy -#| msgid "主故障切换流程[整机切换]" -msgid "开始执行主故障切换[整机切换]的任务" -msgstr "Main failover process [whole machine switchover]" +#| msgid "删除用户接口异常,相关信息: {}" +msgid "[{}]添加用户接口异常,相关信息: {}" +msgstr "Delete user interface exception, related information: {}" -#: backend/flow/views/mysql_ha_rename_database.py:30 -#: backend/flow/views/mysql_ha_truncate_data.py:30 -msgid "开始TenDBHA清档场景" -msgstr "Start the TenDBHA clearing scene" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:186 +msgid "This spider-role is not supported,check" +msgstr "" -#: backend/flow/views/mysql_ha_switch.py:30 +#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:45 #, fuzzy -#| msgid "主从切换流程[整机切换]" -msgid "开始执行主从切换[整机切换]的任务" -msgstr "Master-slave switching process [whole machine switching]" +#| msgid "检查源数据库是否在用" +msgid "{} {} 检查库表是否在用" +msgstr "Check if the source database is in use" -#: backend/flow/views/mysql_migrate_cluster.py:46 -#: backend/flow/views/mysql_restore_slave.py:49 -msgid "开始重建slave" -msgstr "Start rebuilding the slave" +#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:50 +#, fuzzy +#| msgid "检查源数据库是否在用" +msgid "{} 检查库表是否在用" +msgstr "Check if the source database is in use" -#: backend/flow/views/mysql_proxy_add.py:30 -msgid "开始添加mysql_proxy实例场景" -msgstr "Start adding mysql_proxy instance scenarios" +#: backend/flow/plugins/components/collections/spider/clear_database_on_remote_service.py:56 +msgid "remote drop 新库完成" +msgstr "remote drop new library completed" -#: backend/flow/views/mysql_proxy_reduce.py:30 -msgid "开始回收mysql_proxy实例场景" -msgstr "Start to recycle the mysql_proxy instance scenario" +#: backend/flow/plugins/components/collections/spider/create_database_like_via_ctl.py:110 +msgid "建立集群备份库表完成" +msgstr "The establishment of the cluster backup library table is completed" -#: backend/flow/views/mysql_proxy_switch.py:30 -msgid "开始替换mysql_proxy实例场景" -msgstr "Start to replace the mysql_proxy instance scenario" +#: backend/flow/plugins/components/collections/spider/drop_spider_table_via_ctl.py:49 +#, fuzzy +#| msgid "删除源数据库完成" +msgid "删除老数据库完成" +msgstr "Delete source database complete" -#: backend/flow/views/mysql_pt_table_sync.py:30 +#: backend/flow/plugins/components/collections/spider/truncate_database_drop_stage_db_via_ctl.py:47 #, fuzzy -#| msgid "执行数据修复" -msgid "开始执行数据修复" -msgstr "perform data repair" +#| msgid "建立备份库完成" +msgid "清理备份库完成" +msgstr "Create a backup db complete" -#: backend/flow/views/mysql_restore_local_slave.py:44 -msgid "开始原地重建slave" -msgstr "Start rebuilding the slave in situ" +#: backend/flow/plugins/components/collections/spider/truncate_database_on_spider_via_ctl.py:145 +msgid "处理集群表完成" +msgstr "Processing cluster table complete" -#: backend/flow/views/mysql_rollback_data.py:48 -msgid "开始重建定点回档数据" -msgstr "Start to rebuild the fixed-point archive data" +#: backend/flow/signal/handlers.py:35 +msgid "【状态信号捕获】{} root_id={}, node_id={}, status:{}" +msgstr "【Status signal capture】{} root_id={}, node_id={}, status:{}" -#: backend/flow/views/mysql_single_apply.py:57 -msgid "开始部署mysql单实例场景" -msgstr "Start deploying mysql single instance scenario" +#: backend/flow/signal/handlers.py:68 +msgid "【状态信号捕获】未查找到FlowTree root_id={}" +msgstr "[Status signal capture] FlowTree root_id={} not found" -#: backend/flow/views/mysql_single_destroy.py:30 -msgid "开始回收mysql单节点版场景" -msgstr "Start to recycle mysql single-node version scenario" +#: backend/flow/utils/cc_manage.py:55 +msgid "查询主机bk_host_id失败[数量不匹配]" +msgstr "Failed to query host bk_host_id [number does not match]" -#: backend/flow/views/mysql_single_destroy.py:46 -msgid "开始禁用mysql单节点版场景" -msgstr "Start disabling the mysql single-node version scenario" +#: backend/flow/utils/cc_manage.py:67 +msgid "查询空闲机模块ID bk_module_id 失败" +msgstr "Failed to query the idle machine module ID bk_module_id" -#: backend/flow/views/mysql_single_destroy.py:62 -msgid "开始启动mysql单节点版场景" -msgstr "Start the mysql single-node version scenario" +#: backend/flow/utils/cloud/cloud_act_payload.py:42 +msgid "单据中不包含DRS的部署信息" +msgstr "The document does not contain the deployment information of DRS" + +#: backend/flow/utils/cloud/cloud_act_payload.py:50 +msgid "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" +msgstr "" +"The DNS service has not been deployed, please deploy the service after the " +"DNS service is deployed" + +#: backend/flow/utils/cloud/cloud_act_payload.py:58 +msgid "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" +msgstr "" +"The Nginx service is not deployed, please deploy the service after the Nginx " +"service is deployed" -#: backend/flow/views/mysql_single_rename_database.py:30 -#: backend/flow/views/mysql_single_truncate_data.py:30 +#: backend/flow/utils/cloud/cloud_db_proxy.py:52 #, fuzzy -#| msgid "开始TenDBHA清档场景" -msgid "开始TenDBSingle清档场景" -msgstr "Start the TenDBHA clearing scene" +#| msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" +msgid "找不到单据类型需要变更的proxy函数,服务信息入库失败" +msgstr "" +"The cmdb function that needs to be changed cannot be found, please contact " +"the system administrator" -#: backend/flow/views/pulsar_destroy.py:39 +#: backend/flow/utils/cloud/cloud_module_operate.py:135 #, fuzzy -#| msgid "开始HDFS集群销毁场景" -msgid "开始pulsar集群销毁场景" -msgstr "Start the HDFS cluster destruction scenario" +#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" +msgid "主机{}转移{}失败,转移参数:{}, 错误信息:{}" +msgstr "" +"The transfer of host {} failed, transfer parameters: {}, error message: {}" -#: backend/flow/views/pulsar_disable.py:39 +#: backend/flow/utils/cloud/cloud_module_operate.py:196 #, fuzzy -#| msgid "HDFS集群禁用" -msgid "开始PULSAR集群禁用场景" -msgstr "HDFS cluster disabled" +#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" +msgid "主机{}转移待回收失败,错误信息:{}" +msgstr "" +"The transfer of host {} failed, transfer parameters: {}, error message: {}" -#: backend/flow/views/pulsar_enable.py:39 -#, fuzzy -#| msgid "HDFS 集群启用" -msgid "开始PULSAR集群启用场景" -msgstr "HDFS cluster enabled" +#: backend/flow/utils/es/es_db_meta.py:94 +msgid "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" +msgstr "" +"The cmdb function {} that needs to be changed cannot be found, please " +"contact the system administrator" -#: backend/flow/views/pulsar_reboot.py:55 -#, fuzzy -#| msgid "开始重启HDFS场景" -msgid "开始重启PULSAR场景" -msgstr "Start to restart the HDFS scene" +#: backend/flow/utils/hdfs/hdfs_db_meta.py:52 +#: backend/flow/utils/influxdb/influxdb_db_meta.py:114 +#: backend/flow/utils/kafka/kafka_db_meta.py:160 +#: backend/flow/utils/redis/redis_db_meta.py:48 +msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" +msgstr "" +"The cmdb function that needs to be changed cannot be found, please contact " +"the system administrator" -#: backend/flow/views/pulsar_replace.py:28 +#: backend/flow/utils/mysql/db_resource.py:106 #, fuzzy -#| msgid "HDFS集群禁用" -msgid "开始PULSAR集群替换场景" -msgstr "HDFS cluster disabled" +#| msgid "在资源池获取资源失败" +msgid " 获取资源失败: {}" +msgstr "Failed to obtain resource from resource pool" -#: backend/flow/views/pulsar_shrink.py:28 -#, fuzzy -#| msgid "HDFS 集群缩容" -msgid "开始PULSAR集群缩容场景" -msgstr "HDFS cluster shrink" +#: backend/flow/utils/mysql/db_table_filter/exception.py:18 +msgid "库表过滤异常" +msgstr "Database table filtering exception" -#: backend/flow/views/rollback_pipeline.py:151 -msgid "导入资源池失败" -msgstr "Failed to import resource pool" +#: backend/flow/utils/mysql/db_table_filter/exception.py:23 +msgid "输入校验异常" +msgstr "input validation exception" -#: backend/flow/views/rollback_pipeline.py:171 -msgid "高可用架构" -msgstr "High availability architecture" +#: backend/flow/utils/mysql/db_table_filter/filter.py:42 +msgid "include patterns 不能为空" +msgstr "include patterns cannot be empty" -#: backend/flow/views/rollback_pipeline.py:172 -msgid "单实例架构" -msgstr "single instance architecture" +#: backend/flow/utils/mysql/db_table_filter/filter.py:48 +msgid "exclude patterns 要么同时为空, 要么都不为空" +msgstr "" +"exclude patterns are either empty at the same time, or none of them are empty" -#: backend/flow/views/spider_cluster_database_table_backup.py:30 -#, fuzzy -#| msgid "库表备份" -msgid "开始TenDBCluster库表备份场景" -msgstr "Database table backup" +#: backend/flow/utils/mysql/db_table_filter/tools.py:30 +msgid "使用通配符时, 只能有一个模式: {}" +msgstr "When using wildcards, there can only be one pattern: {}" -#: backend/flow/views/spider_cluster_destroy.py:34 -#, fuzzy -#| msgid "开始禁用ES场景" -msgid "开始禁用spider集群场景" -msgstr "Start disabling ES scenes" +#: backend/flow/utils/mysql/db_table_filter/tools.py:33 +msgid "% ? 不能独立使用" +msgstr "% ? cannot be used independently" -#: backend/flow/views/spider_cluster_destroy.py:53 -#, fuzzy -#| msgid "开始启用ES场景" -msgid "开始启用spider集群场景" -msgstr "Start to enable ES scene" +#: backend/flow/utils/mysql/db_table_filter/tools.py:36 +msgid "* 只能独立使用" +msgstr "* can only be used independently" -#: backend/flow/views/spider_cluster_rename_database.py:30 -msgid "开始TenDBCluster数据库重命名场景" -msgstr "Start the TenDBCluster database renaming scenario" +#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:27 +msgid "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" +msgstr "" +"The exec_ip variable and the get_trans_data_ip_var variable cannot be " +"assigned at the same time" -#: backend/flow/views/spider_cluster_truncate_database.py:30 +#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:29 +msgid "exec_ip变量和get_trans_data_ip_var变量不能同时为None" +msgstr "" +"The exec_ip variable and the get_trans_data_ip_var variable cannot be None " +"at the same time" + +#: backend/flow/utils/mysql/mysql_act_playload.py:304 +msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" +msgstr "" +"The incoming mysql port list is empty or an illegal value, please contact " +"the system administrator" + +#: backend/flow/utils/mysql/mysql_act_playload.py:348 #, fuzzy -#| msgid "开始TenDBHA清档场景" -msgid "开始TenDBCluster清档场景" -msgstr "Start the TenDBHA clearing scene" +#| msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" +msgid "传入的安装spider端口列表为空或者非法值,请联系系统管理员" +msgstr "" +"The incoming mysql port list is empty or an illegal value, please contact " +"the system administrator" -#: backend/iam_app/dataclass/actions.py:47 -msgid "业务访问" -msgstr "business visit" +#: backend/flow/utils/pulsar/consts.py:20 +msgid "broker默认分区数" +msgstr "broker default number of partitions" -#: backend/iam_app/dataclass/actions.py:56 -msgid "数据库管理" -msgstr "database management" +#: backend/flow/utils/pulsar/consts.py:21 +msgid "broker认证配置" +msgstr "Broker authentication configuration" -#: backend/iam_app/dataclass/actions.py:65 -msgid "平台管理" -msgstr "platform management" +#: backend/flow/utils/pulsar/consts.py:22 +msgid "默认bookie池大小" +msgstr "Default bookie pool size" -#: backend/iam_app/dataclass/actions.py:78 -msgid "动作ID不存在: {}" -msgstr "Action ID does not exist: {}" +#: backend/flow/utils/pulsar/consts.py:23 +msgid "写入副本数" +msgstr "Write replicas" -#: backend/iam_app/dataclass/resources.py:94 -msgid "资源类型ID不存在: {}" -msgstr "Resource type ID does not exist: {}" +#: backend/flow/utils/pulsar/consts.py:24 +msgid "确认写入副本数" +msgstr "Acknowledge the number of replicas written" -#: backend/iam_app/exceptions.py:51 -#, python-brace-format -msgid "当前用户无 [{action_name}] 权限" -msgstr "The current user does not have permission for [{action_name}]" +#: backend/flow/utils/pulsar/consts.py:25 +msgid "数据保留时间,单位为分钟" +msgstr "Data retention time, in minutes" -#: backend/iam_app/handlers/drf_perm.py:162 -#, fuzzy -#| msgid "权限克隆失败,错误信息: {}\n" -msgid "JWT鉴权错误,错误信息: {}" -msgstr "Permission clone failed, error message: {}\n" +#: backend/flow/utils/pulsar/consts.py:26 +msgid "broker服务端口" +msgstr "broker service port" -#: backend/iam_app/handlers/permission.py:74 -#, python-brace-format -msgid "获取系统信息错误:{message}" -msgstr "Error getting system information: {message}" +#: backend/flow/utils/pulsar/consts.py:27 +msgid "访问Pulsar Manager账户名" +msgstr "Access Pulsar Manager account name" -#: backend/iam_app/serializers.py:18 -msgid "资源类型" -msgstr "Resource Type" +#: backend/flow/utils/pulsar/consts.py:28 +msgid "访问Pulsar Manager密码" +msgstr "Access Pulsar Manager Password" -#: backend/iam_app/serializers.py:19 -msgid "资源ID" -msgstr "Resource ID" +#: backend/flow/utils/redis/redis_db_meta.py:56 +msgid "找不到单据类型需要查询的cmdb函数,请联系系统管理员" +msgstr "" +"The cmdb function that needs to be queried for the ticket type cannot be " +"found, please contact the system administrator" -#: backend/iam_app/serializers.py:21 -msgid "动作ID列表" -msgstr "action id list" +#: backend/flow/utils/spider/get_spider_incr.py:45 +msgid "select spider_auto_increment failed: {}" +msgstr "" -#: backend/iam_app/serializers.py:22 -msgid "资源列表" -msgstr "resource list" +#: backend/flow/utils/spider/get_spider_incr.py:49 +msgid "select spider_auto_increment is null, check " +msgstr "" -#: backend/iam_app/views/views.py:27 -msgid "获取系统权限中心信息" -msgstr "Obtaining system authority center information" +#: backend/flow/utils/spider/get_spider_incr.py:65 +msgid "The obtained incr is greater than MAX_SPIDER_MASTER_COUNT, check" +msgstr "" -#: backend/iam_app/views/views.py:34 -msgid "检查当前用户对该动作是否有权限" -msgstr "Check if the current user has permission for the action" +#: backend/flow/views/cloud_dbha_apply.py:39 +#: backend/flow/views/cloud_dns_bind_apply.py:39 +#, fuzzy +#| msgid "开始部署ES场景" +msgid "开始部署dns-bind服务场景" +msgstr "Start deploying ES scenarios" -#: backend/iam_app/views/views.py:51 -msgid "获取权限申请数据" -msgstr "Obtain permission application data" +#: backend/flow/views/cloud_drs_apply.py:44 +#, fuzzy +#| msgid "开始部署ES场景" +msgid "开始部署drs服务场景" +msgstr "Start deploying ES scenarios" -#: backend/redis_dts/constants.py:19 -msgid "tendis ssd备份任务" -msgstr "tendis ssd backup task" +#: backend/flow/views/cloud_nginx_apply.py:44 +#, fuzzy +#| msgid "开始部署ES场景" +msgid "开始部署nginx服务场景" +msgstr "Start deploying ES scenarios" -#: backend/redis_dts/constants.py:20 -msgid "tendis ssd备份拉取任务" -msgstr "tendis ssd backup pull task" +#: backend/flow/views/cloud_nginx_apply.py:54 +#, fuzzy +#| msgid "开始部署ES场景" +msgid "开始替换nginx服务场景" +msgstr "Start deploying ES scenarios" + +#: backend/flow/views/es_apply.py:63 +msgid "开始部署ES场景" +msgstr "Start deploying ES scenarios" + +#: backend/flow/views/es_destroy.py:39 +msgid "开始下架ES场景" +msgstr "Start to remove the ES scene" + +#: backend/flow/views/es_disable.py:39 +msgid "开始禁用ES场景" +msgstr "Start disabling ES scenes" -#: backend/redis_dts/constants.py:21 -msgid "tendis ssd备份解析任务" -msgstr "Tendis ssd backup analysis task" +#: backend/flow/views/es_enable.py:39 +msgid "开始启用ES场景" +msgstr "Start to enable ES scene" -#: backend/redis_dts/constants.py:22 -msgid "tendis ssd数据导入任务" -msgstr "Tendis ssd data import task" +#: backend/flow/views/es_reboot.py:47 +msgid "开始重启ES节点场景" +msgstr "Start restarting the ES node scenario" -#: backend/redis_dts/constants.py:23 -msgid "tendis ssd拉起sync任务" -msgstr "Tendis ssd pulls up the sync task" +#: backend/flow/views/es_replace.py:63 backend/flow/views/es_scale_up.py:52 +msgid "开始扩容ES场景" +msgstr "Start to expand the ES scene" -#: backend/redis_dts/constants.py:24 backend/redis_dts/constants.py:28 -msgid "tendis ssd监视sync任务" -msgstr "Tendis ssd monitor sync task" +#: backend/flow/views/es_shrink.py:52 +msgid "开始缩容ES场景" +msgstr "Start shrinking the ES scene" -#: backend/redis_dts/constants.py:27 -msgid "redis cache拉起redis-shake任务" -msgstr "Redis cache pulls up the redis-shake task" +#: backend/flow/views/hdfs_apply.py:61 +msgid "开始部署HDFS场景" +msgstr "Start deploying HDFS scenarios" -#: backend/redis_dts/constants.py:31 -msgid "tendisplus拉起reids-sync任务" -msgstr "Tendisplus pulls up the reids-sync task" +#: backend/flow/views/hdfs_destroy.py:39 +msgid "开始HDFS集群销毁场景" +msgstr "Start the HDFS cluster destruction scenario" -#: backend/redis_dts/constants.py:33 +#: backend/flow/views/hdfs_disable.py:39 #, fuzzy -#| msgid "tendisplus实例安装 元数据" -msgid "tendisplus全量数据同步" -msgstr "Tendisplus instance installation metadata" +#| msgid "HDFS集群禁用" +msgid "开始HDFS集群禁用场景" +msgstr "HDFS cluster disabled" -#: backend/redis_dts/constants.py:34 +#: backend/flow/views/hdfs_enable.py:39 #, fuzzy -#| msgid "tendisplus实例安装 元数据" -msgid "tendisplus增量数据同步" -msgstr "Tendisplus instance installation metadata" - -#: backend/redis_dts/constants.py:40 -msgid "停止数据同步todo" -msgstr "stop data sync todo" +#| msgid "HDFS 集群启用" +msgid "开始HDFS集群启用场景" +msgstr "HDFS cluster enabled" -#: backend/redis_dts/constants.py:41 -msgid "停止数据同步失败" -msgstr "Failed to stop data sync" +#: backend/flow/views/hdfs_reboot.py:55 +msgid "开始重启HDFS场景" +msgstr "Start to restart the HDFS scene" -#: backend/redis_dts/constants.py:42 -msgid "停止数据同步成功" -msgstr "Stop data synchronization successfully" +#: backend/flow/views/hdfs_replace.py:65 +msgid "开始替换HDFS场景" +msgstr "Start to replace the HDFS scene" -#: backend/redis_dts/constants.py:44 -msgid "强制暂停任务todo" -msgstr "Forcibly suspend task todo" +#: backend/flow/views/hdfs_scale_up.py:42 +msgid "开始扩容HDFS场景" +msgstr "Start expanding the HDFS scene" -#: backend/redis_dts/constants.py:45 +#: backend/flow/views/hdfs_shrink.py:42 #, fuzzy -#| msgid "创建模拟任务失败!" -msgid "强制暂停任务失败" -msgstr "Failed to create simulation task!" +#| msgid "HDFS 集群缩容" +msgid "开始HDFS集群缩容场景" +msgstr "HDFS cluster shrink" -#: backend/redis_dts/constants.py:46 +#: backend/flow/views/influxdb_apply.py:57 #, fuzzy -#| msgid "创建模拟任务成功" -msgid "强制暂停任务成功" -msgstr "Create mock task successfully" +#| msgid "开始部署ES场景" +msgid "开始部署influxdb场景" +msgstr "Start deploying ES scenarios" -#: backend/redis_dts/constants.py:52 +#: backend/flow/views/influxdb_destroy.py:39 #, fuzzy -#| msgid "获取集群部署配置" -msgid "集群节点数变更" -msgstr "Get cluster deployment configuration" +#| msgid "开始下架ES场景" +msgid "开始下架Influxdb场景" +msgstr "Start to remove the ES scene" -#: backend/redis_dts/constants.py:53 +#: backend/flow/views/influxdb_disable.py:39 #, fuzzy -#| msgid "集群类型" -msgid "集群类型变更" -msgstr "cluster type" +#| msgid "开始禁用ES场景" +msgid "开始禁用Influxdb场景" +msgstr "Start disabling ES scenes" -#: backend/redis_dts/constants.py:54 -msgid "数据复制" -msgstr "data replication" +#: backend/flow/views/influxdb_enable.py:39 +#, fuzzy +#| msgid "开始启用ES场景" +msgid "开始启用Influxdb场景" +msgstr "Start to enable ES scene" -#: backend/redis_dts/constants.py:60 -msgid "同一业务不同集群" -msgstr "Different clusters of the same business" +#: backend/flow/views/influxdb_reboot.py:47 +#, fuzzy +#| msgid "开始重启ES节点场景" +msgid "开始重启Influxdb节点场景" +msgstr "Start restarting the ES node scenario" -#: backend/redis_dts/constants.py:61 -msgid "不同业务不同集群" -msgstr "Different business clusters" +#: backend/flow/views/influxdb_replace.py:49 +#, fuzzy +#| msgid "开始替换kafka场景" +msgid "开始替换influxdb场景" +msgstr "Start to replace the kafka scene" -#: backend/redis_dts/constants.py:62 -msgid "复制到其他系统" -msgstr "copy to other system" +#: backend/flow/views/kafka_apply.py:70 +msgid "开始部署kafka场景" +msgstr "Start deploying kafka scenarios" -#: backend/redis_dts/constants.py:63 -msgid "从回档临时环境复制数据" -msgstr "Copy data from the archive staging environment" +#: backend/flow/views/kafka_destroy.py:39 +msgid "开始下架Kafka场景" +msgstr "Start to remove the Kafka scene" -#: backend/redis_dts/constants.py:64 -msgid "用户自建redis迁移到DBM" -msgstr "Migrating user-built redis to DBM" +#: backend/flow/views/kafka_disable.py:39 +msgid "开始禁用Kafka场景" +msgstr "Start disabling the Kafka scene" -#: backend/redis_dts/constants.py:70 -msgid "自动切换" -msgstr "auto switch" +#: backend/flow/views/kafka_enable.py:39 +msgid "开始启用Kafka场景" +msgstr "Start to enable the Kafka scene" -#: backend/redis_dts/constants.py:71 -msgid "用户确认切换" -msgstr "User confirmation switch" +#: backend/flow/views/kafka_reboot.py:47 +msgid "开始重启Kafka节点场景" +msgstr "Start restarting the Kafka node scenario" -#: backend/redis_dts/constants.py:77 -#: backend/ticket/builders/common/constants.py:79 -msgid "自动修复" -msgstr "automatic repair" +#: backend/flow/views/kafka_replace.py:51 +msgid "开始替换kafka场景" +msgstr "Start to replace the kafka scene" -#: backend/redis_dts/constants.py:78 -msgid "用户确认修复" -msgstr "User confirms the fix" +#: backend/flow/views/kafka_scale_up.py:49 +msgid "开始扩容kafka场景" +msgstr "Start to expand the kafka scene" -#: backend/redis_dts/exceptions.py:18 -#, fuzzy -#| msgid "DBMeta模块异常" -msgid "DBDts模块异常" -msgstr "DBMeta module exception" +#: backend/flow/views/kafka_shrink.py:44 +msgid "开始缩容kafka场景" +msgstr "Start shrinking the kafka scene" -#: backend/redis_dts/exceptions.py:23 -#, fuzzy -#| msgid "任务列表" -msgid "获取DTS任务列表异常" -msgstr "task list" +#: backend/flow/views/mysql_add_slave.py:44 +msgid "开始添加slave" +msgstr "Start adding slaves" -#: backend/redis_dts/exceptions.py:29 -msgid "DTS task操作异常" -msgstr "DTS task operation is abnormal" +#: backend/flow/views/mysql_edit_config.py:60 +msgid "开始下发修改的参数" +msgstr "Start sending the modified parameters" -#: backend/redis_dts/models/tb_dts_distribute_lock.py:17 +#: backend/flow/views/mysql_flashback.py:49 #, fuzzy -#| msgid "关键字唯一标识" -msgid "锁的唯一标识" -msgstr "Keyword Unique Identifier" - -#: backend/redis_dts/models/tb_dts_distribute_lock.py:18 -msgid "锁的持有者" -msgstr "lock holder" - -#: backend/redis_dts/models/tb_dts_distribute_lock.py:20 -msgid "锁的过期时间" -msgstr "lock expiration time" +#| msgid "flashback信息" +msgid "开始flashback" +msgstr "flashback information" -#: backend/redis_dts/models/tb_tendis_dts_job.py:17 -#: backend/redis_dts/models/tb_tendis_dts_task.py:19 +#: backend/flow/views/mysql_ha_db_table_backup.py:32 #, fuzzy -#| msgid "单据" -msgid "单据号" -msgstr "tickets" +#| msgid "库表备份" +msgid "开始库表备份场景" +msgstr "Database table backup" -#: backend/redis_dts/models/tb_tendis_dts_job.py:18 -#: backend/redis_dts/models/tb_tendis_dts_task.py:21 -msgid "业务bk_biz_id" -msgstr "Business bk_biz_id" +#: backend/flow/views/mysql_ha_destroy.py:31 +msgid "开始回收mysql主从版场景" +msgstr "Start to recycle the mysql master-slave version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:19 -#: backend/redis_dts/models/tb_tendis_dts_task.py:22 -msgid "云区域id" -msgstr "cloud region id" +#: backend/flow/views/mysql_ha_destroy.py:49 +msgid "开始禁用mysql主从版场景" +msgstr "Start to disable the mysql master-slave version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:20 -#: backend/redis_dts/models/tb_tendis_dts_task.py:20 -msgid "申请人" -msgstr "applicant" +#: backend/flow/views/mysql_ha_destroy.py:65 +msgid "开始启动mysql主从版场景" +msgstr "Start the mysql master-slave version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:25 +#: backend/flow/views/mysql_ha_full_backup.py:32 #, fuzzy -#| msgid "单据类型" -msgid "DTS单据类型" -msgstr "Ticket Type" +#| msgid "全库备份执行" +msgid "开始全库备份场景" +msgstr "Full database backup execution" -#: backend/redis_dts/models/tb_tendis_dts_job.py:32 -msgid "DTS数据复制类型" -msgstr "DTS data replication type" +#: backend/flow/views/mysql_ha_master_fail_over.py:30 +#, fuzzy +#| msgid "主故障切换流程[整机切换]" +msgid "开始执行主故障切换[整机切换]的任务" +msgstr "Main failover process [whole machine switchover]" -#: backend/redis_dts/models/tb_tendis_dts_job.py:36 -msgid "在线切换类型" -msgstr "Online switch type" +#: backend/flow/views/mysql_ha_rename_database.py:30 +#: backend/flow/views/mysql_ha_truncate_data.py:30 +msgid "开始TenDBHA清档场景" +msgstr "Start the TenDBHA clearing scene" -#: backend/redis_dts/models/tb_tendis_dts_job.py:37 +#: backend/flow/views/mysql_ha_switch.py:30 #, fuzzy -#| msgid "数据校验执行" -msgid "是否数据校验" -msgstr "Data validation execution" +#| msgid "主从切换流程[整机切换]" +msgid "开始执行主从切换[整机切换]的任务" +msgstr "Master-slave switching process [whole machine switching]" -#: backend/redis_dts/models/tb_tendis_dts_job.py:38 -#, fuzzy -#| msgid "{}数据修复" -msgid "是否数据修复" -msgstr "{} data repair" +#: backend/flow/views/mysql_migrate_cluster.py:46 +#: backend/flow/views/mysql_restore_slave.py:49 +msgid "开始重建slave" +msgstr "Start rebuilding the slave" -#: backend/redis_dts/models/tb_tendis_dts_job.py:42 -msgid "数据修复模式" -msgstr "Data Repair Mode" +#: backend/flow/views/mysql_proxy_add.py:30 +msgid "开始添加mysql_proxy实例场景" +msgstr "Start adding mysql_proxy instance scenarios" -#: backend/redis_dts/models/tb_tendis_dts_job.py:45 -#, fuzzy -#| msgid "集群类型" -msgid "源集群类型" -msgstr "cluster type" +#: backend/flow/views/mysql_proxy_reduce.py:30 +msgid "开始回收mysql_proxy实例场景" +msgstr "Start to recycle the mysql_proxy instance scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:46 -msgid "回滚单据号" -msgstr "Rollback document number" +#: backend/flow/views/mysql_proxy_switch.py:30 +msgid "开始替换mysql_proxy实例场景" +msgstr "Start to replace the mysql_proxy instance scenario" + +#: backend/flow/views/mysql_pt_table_sync.py:30 +#, fuzzy +#| msgid "执行数据修复" +msgid "开始执行数据修复" +msgstr "perform data repair" -#: backend/redis_dts/models/tb_tendis_dts_job.py:47 -msgid "回滚临时环境实例" -msgstr "Rollback a temporary environment instance" +#: backend/flow/views/mysql_restore_local_slave.py:44 +msgid "开始原地重建slave" +msgstr "Start rebuilding the slave in situ" -#: backend/redis_dts/models/tb_tendis_dts_job.py:48 -msgid "目标业务id" -msgstr "target business id" +#: backend/flow/views/mysql_rollback_data.py:48 +msgid "开始重建定点回档数据" +msgstr "Start to rebuild the fixed-point archive data" -#: backend/redis_dts/models/tb_tendis_dts_job.py:49 -#: backend/redis_dts/models/tb_tendis_dts_task.py:49 -msgid "目的集群" -msgstr "destination cluster" +#: backend/flow/views/mysql_single_apply.py:57 +msgid "开始部署mysql单实例场景" +msgstr "Start deploying mysql single instance scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:51 -#, fuzzy -#| msgid "集群类型" -msgid "目标集群类型" -msgstr "cluster type" +#: backend/flow/views/mysql_single_destroy.py:30 +msgid "开始回收mysql单节点版场景" +msgstr "Start to recycle mysql single-node version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:52 -msgid "key正则(包含key)" -msgstr "key regular (including key)" +#: backend/flow/views/mysql_single_destroy.py:46 +msgid "开始禁用mysql单节点版场景" +msgstr "Start disabling the mysql single-node version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:53 -msgid "key正则(排除key)" -msgstr "key regularization (exclude key)" +#: backend/flow/views/mysql_single_destroy.py:62 +msgid "开始启动mysql单节点版场景" +msgstr "Start the mysql single-node version scenario" -#: backend/redis_dts/models/tb_tendis_dts_job.py:56 -msgid "bill备注" -msgstr "Bill Remarks" +#: backend/flow/views/mysql_single_rename_database.py:30 +#: backend/flow/views/mysql_single_truncate_data.py:30 +#, fuzzy +#| msgid "开始TenDBHA清档场景" +msgid "开始TenDBSingle清档场景" +msgstr "Start the TenDBHA clearing scene" -#: backend/redis_dts/models/tb_tendis_dts_task.py:23 -msgid "执行迁移任务的dts_server" -msgstr "dts_server that executes migration tasks" +#: backend/flow/views/pulsar_destroy.py:39 +#, fuzzy +#| msgid "开始HDFS集群销毁场景" +msgid "开始pulsar集群销毁场景" +msgstr "Start the HDFS cluster destruction scenario" -#: backend/redis_dts/models/tb_tendis_dts_task.py:25 -msgid "源集群优先级,值越大,优先级越高" -msgstr "Source cluster priority, the larger the value, the higher the priority" +#: backend/flow/views/pulsar_disable.py:39 +#, fuzzy +#| msgid "HDFS集群禁用" +msgid "开始PULSAR集群禁用场景" +msgstr "HDFS cluster disabled" -#: backend/redis_dts/models/tb_tendis_dts_task.py:26 +#: backend/flow/views/pulsar_enable.py:39 #, fuzzy -#| msgid "slave" -msgid "源slave_ip" -msgstr "slave" +#| msgid "HDFS 集群启用" +msgid "开始PULSAR集群启用场景" +msgstr "HDFS cluster enabled" -#: backend/redis_dts/models/tb_tendis_dts_task.py:27 -msgid "源slave_port" -msgstr "source slave_port" +#: backend/flow/views/pulsar_reboot.py:55 +#, fuzzy +#| msgid "开始重启HDFS场景" +msgid "开始重启PULSAR场景" +msgstr "Start to restart the HDFS scene" -#: backend/redis_dts/models/tb_tendis_dts_task.py:28 -msgid "源实例密码base64值" -msgstr "Source instance password base64 value" +#: backend/flow/views/pulsar_replace.py:28 +#, fuzzy +#| msgid "HDFS集群禁用" +msgid "开始PULSAR集群替换场景" +msgstr "HDFS cluster disabled" -#: backend/redis_dts/models/tb_tendis_dts_task.py:30 -msgid "源slave db类型" -msgstr "Source slave db type" +#: backend/flow/views/pulsar_shrink.py:28 +#, fuzzy +#| msgid "HDFS 集群缩容" +msgid "开始PULSAR集群缩容场景" +msgstr "HDFS cluster shrink" -#: backend/redis_dts/models/tb_tendis_dts_task.py:32 -msgid "源实例数据量大小,单位Byte" -msgstr "Source instance data size, unit Byte" +#: backend/flow/views/rollback_pipeline.py:151 +msgid "导入资源池失败" +msgstr "Failed to import resource pool" -#: backend/redis_dts/models/tb_tendis_dts_task.py:34 -msgid "源实例所属segment_start" -msgstr "The segment_start to which the source instance belongs" +#: backend/flow/views/rollback_pipeline.py:171 +msgid "高可用架构" +msgstr "High availability architecture" -#: backend/redis_dts/models/tb_tendis_dts_task.py:35 -msgid "源实例所属segment_end" -msgstr "The segment_end to which the source instance belongs" +#: backend/flow/views/rollback_pipeline.py:172 +msgid "单实例架构" +msgstr "single instance architecture" -#: backend/redis_dts/models/tb_tendis_dts_task.py:37 -msgid "源实例权重" -msgstr "Source Instance Weight" +#: backend/flow/views/spider_cluster_database_table_backup.py:30 +#, fuzzy +#| msgid "库表备份" +msgid "开始TenDBCluster库表备份场景" +msgstr "Database table backup" -#: backend/redis_dts/models/tb_tendis_dts_task.py:39 -msgid "源slave_ip上task并发数控制" -msgstr "Task concurrency control on the source slave_ip" +#: backend/flow/views/spider_cluster_destroy.py:34 +#, fuzzy +#| msgid "开始禁用ES场景" +msgid "开始禁用spider集群场景" +msgstr "Start disabling ES scenes" -#: backend/redis_dts/models/tb_tendis_dts_task.py:40 +#: backend/flow/views/spider_cluster_destroy.py:53 #, fuzzy -#| msgid "实例所在的时区" -msgid "源实例所在城市" -msgstr "The time zone where the instance is located" +#| msgid "开始启用ES场景" +msgid "开始启用spider集群场景" +msgstr "Start to enable ES scene" -#: backend/redis_dts/models/tb_tendis_dts_task.py:42 -msgid "源实例slave-keep-log-count的旧值" -msgstr "Old value of source instance slave-keep-log-count" +#: backend/flow/views/spider_cluster_full_backup.py:30 +#, fuzzy +#| msgid "库表备份" +msgid "开始TenDBCluster全库备份场景" +msgstr "Database table backup" -#: backend/redis_dts/models/tb_tendis_dts_task.py:43 -msgid "源实例slave-keep-log-count的新值" -msgstr "The new value of the source instance slave-keep-log-count" +#: backend/flow/views/spider_cluster_rename_database.py:30 +msgid "开始TenDBCluster数据库重命名场景" +msgstr "Start the TenDBCluster database renaming scenario" -#: backend/redis_dts/models/tb_tendis_dts_task.py:44 -msgid "源实例slave-keep-log-count是否恢复" -msgstr "Whether the source instance slave-keep-log-count is restored" +#: backend/flow/views/spider_cluster_truncate_database.py:30 +#, fuzzy +#| msgid "开始TenDBHA清档场景" +msgid "开始TenDBCluster清档场景" +msgstr "Start the TenDBHA clearing scene" -#: backend/redis_dts/models/tb_tendis_dts_task.py:45 -msgid "srcRedis是否包含list类型key" -msgstr "Whether srcRedis contains list type key" +#: backend/iam_app/dataclass/actions.py:47 +msgid "业务访问" +msgstr "business visit" -#: backend/redis_dts/models/tb_tendis_dts_task.py:46 -msgid "包含key(正则)" -msgstr "Contains key (regular)" +#: backend/iam_app/dataclass/actions.py:56 +msgid "数据库管理" +msgstr "database management" -#: backend/redis_dts/models/tb_tendis_dts_task.py:47 -msgid "排除key(正则)" -msgstr "Exclude key (regular)" +#: backend/iam_app/dataclass/actions.py:65 +msgid "平台管理" +msgstr "platform management" -#: backend/redis_dts/models/tb_tendis_dts_task.py:50 -msgid "目的密码base64值" -msgstr "Destination password base64 value" +#: backend/iam_app/dataclass/actions.py:78 +msgid "动作ID不存在: {}" +msgstr "Action ID does not exist: {}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:53 -msgid "tendisssd slave上bakup文件位置" -msgstr "bakup file location on tendisssd slave" +#: backend/iam_app/dataclass/resources.py:94 +msgid "资源类型ID不存在: {}" +msgstr "Resource type ID does not exist: {}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:54 -msgid "backup文件拉取到dts_server本地位置" -msgstr "The backup file is pulled to the local location of dts_server" +#: backend/iam_app/exceptions.py:51 +#, python-brace-format +msgid "当前用户无 [{action_name}] 权限" +msgstr "The current user does not have permission for [{action_name}]" -#: backend/redis_dts/models/tb_tendis_dts_task.py:55 -msgid "tendisdumper得到的sql文件夹" -msgstr "The sql folder obtained by tendisdumper" +#: backend/iam_app/handlers/drf_perm.py:162 +#, fuzzy +#| msgid "权限克隆失败,错误信息: {}\n" +msgid "JWT鉴权错误,错误信息: {}" +msgstr "Permission clone failed, error message: {}\n" -#: backend/redis_dts/models/tb_tendis_dts_task.py:56 -msgid "redis-sync端口" -msgstr "redis-sync port" +#: backend/iam_app/handlers/permission.py:74 +#, python-brace-format +msgid "获取系统信息错误:{message}" +msgstr "Error getting system information: {message}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:57 -msgid "sync的进程id" -msgstr "sync process id" +#: backend/iam_app/serializers.py:18 +msgid "资源类型" +msgstr "Resource Type" -#: backend/redis_dts/models/tb_tendis_dts_task.py:59 -msgid "task重试次数" -msgstr "task retries" +#: backend/iam_app/serializers.py:19 +msgid "资源ID" +msgstr "Resource ID" -#: backend/redis_dts/models/tb_tendis_dts_task.py:61 -msgid "sync操作" -msgstr "sync operation" +#: backend/iam_app/serializers.py:21 +msgid "动作ID列表" +msgstr "action id list" -#: backend/redis_dts/models/tb_tendis_dts_task.py:63 -msgid "杀死syncer" -msgstr "kill syncer" +#: backend/iam_app/serializers.py:22 +msgid "资源列表" +msgstr "resource list" -#: backend/redis_dts/models/tb_tendis_dts_task.py:66 -#, fuzzy -#| msgid "domain信息" -msgid "信息" -msgstr "domain information" +#: backend/iam_app/views/views.py:27 +msgid "获取系统权限中心信息" +msgstr "Obtaining system authority center information" -#: backend/redis_dts/models/tb_tendis_dts_task.py:68 -msgid "被忽略的错误" -msgstr "ignored errors" +#: backend/iam_app/views/views.py:34 +msgid "检查当前用户对该动作是否有权限" +msgstr "Check if the current user has permission for the action" -#: backend/redis_dts/models/tb_tendis_dts_task.py:69 -msgid "sync从该时间点重新同步" -msgstr "sync resynchronizes from this point in time" +#: backend/iam_app/views/views.py:51 +msgid "获取权限申请数据" +msgstr "Obtain permission application data" #: backend/ticket/builders/__init__.py:149 #, python-brace-format msgid "{creator}提交了{title}的单据,请查看详情后进行审批" -msgstr "{creator} has submitted the document for {title}, please review the details before approval" +msgstr "" +"{creator} has submitted the document for {title}, please review the details " +"before approval" #: backend/ticket/builders/__init__.py:154 msgid "单据链接" @@ -12903,7 +13123,7 @@ msgstr "demand information" #: backend/ticket/builders/__init__.py:305 #: backend/ticket/builders/mysql/mysql_import_sqlfile.py:176 -#: backend/ticket/constants.py:306 +#: backend/ticket/constants.py:307 msgid "单据审批" msgstr "Ticket approval" @@ -13220,31 +13440,31 @@ msgstr "" msgid "数据库{}不在所属集群{}中,请重新查验" msgstr "The database {} does not belong to the cluster {}, please check again" -#: backend/ticket/builders/common/bigdata.py:34 +#: backend/ticket/builders/common/bigdata.py:38 msgid "节点列表信息" msgstr "Node List Information" -#: backend/ticket/builders/common/bigdata.py:48 +#: backend/ticket/builders/common/bigdata.py:52 #: backend/ticket/builders/redis/redis_cluster_apply.py:96 msgid "主机{}不在空闲机池,请保证所选的主机均来自空闲机" msgstr "" "The host {} is not in the idle machine pool, please ensure that the selected " "hosts are all from idle machines" -#: backend/ticket/builders/common/bigdata.py:57 +#: backend/ticket/builders/common/bigdata.py:61 msgid "主机{}已经被使用,请重新选择主机" msgstr "The host {} is already in use, please reselect the host" -#: backend/ticket/builders/common/bigdata.py:78 +#: backend/ticket/builders/common/bigdata.py:82 #: backend/ticket/builders/mysql/base.py:175 msgid "集群{}状态转移不合法:{}--->{} is invalid" msgstr "Cluster {} state transfer is invalid: {}--->{} is invalid" -#: backend/ticket/builders/common/bigdata.py:86 +#: backend/ticket/builders/common/bigdata.py:90 msgid "资源池规格" msgstr "Resource pool specification" -#: backend/ticket/builders/common/bigdata.py:106 +#: backend/ticket/builders/common/bigdata.py:110 #: backend/ticket/builders/influxdb/influxdb_apply.py:29 #: backend/ticket/builders/mysql/mysql_single_apply.py:48 #: backend/ticket/builders/redis/redis_cluster_apply.py:33 @@ -13252,81 +13472,81 @@ msgstr "Resource pool specification" msgid "城市代码" msgstr "city ​​code" -#: backend/ticket/builders/common/bigdata.py:108 +#: backend/ticket/builders/common/bigdata.py:112 #: backend/ticket/builders/redis/redis_cluster_apply.py:31 #: backend/ticket/serializers.py:77 msgid "业务英文缩写" msgstr "business abbreviation" -#: backend/ticket/builders/common/bigdata.py:109 +#: backend/ticket/builders/common/bigdata.py:113 msgid "集群名称(英文数字及下划线)" msgstr "Cluster name (alphanumeric and underscore)" -#: backend/ticket/builders/common/bigdata.py:110 +#: backend/ticket/builders/common/bigdata.py:114 #: backend/ticket/builders/redis/redis_cluster_apply.py:42 msgid "集群别名(一般为中文别名)" msgstr "Cluster alias (usually Chinese alias)" -#: backend/ticket/builders/common/bigdata.py:114 +#: backend/ticket/builders/common/bigdata.py:118 msgid "资源申请规格" msgstr "Resource Application Specifications" -#: backend/ticket/builders/common/bigdata.py:152 +#: backend/ticket/builders/common/bigdata.py:156 msgid "主机{}出现角色互斥,{}与{}冲突" msgstr "Host {} has a role mutual exclusion, and {} conflicts with {}" -#: backend/ticket/builders/common/bigdata.py:166 -#: backend/ticket/builders/common/bigdata.py:287 +#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:291 msgid "旧节点信息集合" msgstr "Collection of old node information" -#: backend/ticket/builders/common/bigdata.py:166 -#: backend/ticket/builders/common/bigdata.py:168 -#: backend/ticket/builders/common/bigdata.py:287 -#: backend/ticket/builders/common/bigdata.py:289 +#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:172 +#: backend/ticket/builders/common/bigdata.py:291 +#: backend/ticket/builders/common/bigdata.py:293 msgid "节点信息" msgstr "node information" -#: backend/ticket/builders/common/bigdata.py:168 -#: backend/ticket/builders/common/bigdata.py:289 +#: backend/ticket/builders/common/bigdata.py:172 +#: backend/ticket/builders/common/bigdata.py:293 msgid "新节点信息集合" msgstr "New node information collection" -#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:174 msgid "规格类型" msgstr "Specification type" -#: backend/ticket/builders/common/bigdata.py:177 -#: backend/ticket/builders/common/bigdata.py:298 +#: backend/ticket/builders/common/bigdata.py:181 +#: backend/ticket/builders/common/bigdata.py:302 msgid "替换前后角色类型不一致,请保证替换前后角色类型和数量一致!" msgstr "" "The types of characters before and after the replacement are inconsistent, " "please ensure that the types and numbers of characters before and after the " "replacement are the same!" -#: backend/ticket/builders/common/bigdata.py:185 -#: backend/ticket/builders/common/bigdata.py:306 +#: backend/ticket/builders/common/bigdata.py:189 +#: backend/ticket/builders/common/bigdata.py:310 msgid "角色{}替换前后数量不一致,请保证替换前后角色类型和数量一致!" msgstr "" "The number of roles {} before and after replacement is inconsistent, please " "ensure that the type and number of characters before and after replacement " "are consistent!" -#: backend/ticket/builders/common/bigdata.py:204 +#: backend/ticket/builders/common/bigdata.py:208 msgid "实例名" msgstr "instance name" -#: backend/ticket/builders/common/bigdata.py:215 -#: backend/ticket/builders/common/bigdata.py:281 +#: backend/ticket/builders/common/bigdata.py:219 +#: backend/ticket/builders/common/bigdata.py:285 msgid "实例{}不存在, 请重新确认实例的合法性" msgstr "" "Instance {} does not exist, please reconfirm the legitimacy of the instance" -#: backend/ticket/builders/common/bigdata.py:220 +#: backend/ticket/builders/common/bigdata.py:224 msgid "无法进行重启操作,原因:{}" msgstr "Unable to perform restart operation, reason: {}" -#: backend/ticket/builders/common/bigdata.py:291 +#: backend/ticket/builders/common/bigdata.py:295 #, fuzzy #| msgid "机器规格" msgid "规格" @@ -13536,39 +13756,40 @@ msgid "资源规格" msgstr "resource specification" #: backend/ticket/builders/influxdb/influxdb_apply.py:75 -#: backend/ticket/constants.py:210 +#: backend/ticket/constants.py:211 msgid "InfluxDB 实例部署" msgstr "InfluxDB instance deployment" #: backend/ticket/builders/influxdb/influxdb_destroy.py:37 -#: backend/ticket/constants.py:214 +#: backend/ticket/constants.py:215 #, fuzzy #| msgid "InfluxDB 实例部署" msgid "InfluxDB 实例删除" msgstr "InfluxDB instance deployment" #: backend/ticket/builders/influxdb/influxdb_disable.py:37 +#: backend/ticket/constants.py:214 #, fuzzy #| msgid "InfluxDB 实例部署" msgid "InfluxDB 实例禁用" msgstr "InfluxDB instance deployment" #: backend/ticket/builders/influxdb/influxdb_enable.py:37 -#: backend/ticket/constants.py:212 +#: backend/ticket/constants.py:213 #, fuzzy #| msgid "HDFS 实例重启" msgid "InfluxDB 实例启用" msgstr "HDFS instance restart" #: backend/ticket/builders/influxdb/influxdb_reboot.py:39 -#: backend/ticket/constants.py:211 +#: backend/ticket/constants.py:212 #, fuzzy #| msgid "HDFS 实例重启" msgid "InfluxDB 实例重启" msgstr "HDFS instance restart" #: backend/ticket/builders/influxdb/influxdb_replace.py:46 -#: backend/ticket/constants.py:215 +#: backend/ticket/constants.py:216 #, fuzzy #| msgid "HDFS 实例重启" msgid "InfluxDB 实例替换" @@ -13604,7 +13825,7 @@ msgstr "" "number of Brokers" #: backend/ticket/builders/kafka/kafka_apply.py:133 -#: backend/ticket/constants.py:174 +#: backend/ticket/constants.py:175 msgid "Kafka 集群部署" msgstr "Kafka cluster deployment" @@ -13615,27 +13836,26 @@ msgid "Kafka 集群销毁" msgstr "Kafka cluster" #: backend/ticket/builders/kafka/kafka_disable.py:37 -#: backend/ticket/constants.py:180 msgid "Kafka 集群停用" msgstr "Kafka cluster down" #: backend/ticket/builders/kafka/kafka_enable.py:37 -#: backend/ticket/constants.py:179 +#: backend/ticket/constants.py:180 msgid "Kafka 集群启用" msgstr "Kafka cluster enabled" #: backend/ticket/builders/kafka/kafka_reboot.py:39 -#: backend/ticket/constants.py:177 +#: backend/ticket/constants.py:178 msgid "Kafka 实例重启" msgstr "Kafka instance restart" #: backend/ticket/builders/kafka/kafka_replace.py:48 -#: backend/ticket/constants.py:178 +#: backend/ticket/constants.py:179 msgid "Kafka 集群替换" msgstr "Kafka cluster replacement" #: backend/ticket/builders/kafka/kafka_scale_up.py:65 -#: backend/ticket/constants.py:175 +#: backend/ticket/constants.py:176 msgid "Kafka 集群扩容" msgstr "Kafka cluster expansion" @@ -13644,21 +13864,27 @@ msgid "缩容仅支持Broker" msgstr "Scaling only supports Broker" #: backend/ticket/builders/kafka/kafka_shrink.py:77 -#: backend/ticket/constants.py:176 +#: backend/ticket/constants.py:177 msgid "Kafka 集群缩容" msgstr "Kafka cluster shrink" #: backend/ticket/builders/mysql/base.py:98 msgid "matser实例状态异常,暂时无法执行该单据类型:{}" -msgstr "The state of the matser instance is abnormal, and this document type cannot be executed temporarily: {}" +msgstr "" +"The state of the matser instance is abnormal, and this document type cannot " +"be executed temporarily: {}" #: backend/ticket/builders/mysql/base.py:104 msgid "slave实例状态异常,暂时无法执行该单据类型:{}" -msgstr "The status of the slave instance is abnormal, and the document type cannot be executed temporarily: {}" +msgstr "" +"The status of the slave instance is abnormal, and the document type cannot " +"be executed temporarily: {}" #: backend/ticket/builders/mysql/base.py:110 msgid "proxy实例状态异常,暂时无法执行该单据类型:{}" -msgstr "The status of the proxy instance is abnormal, and the document type cannot be executed temporarily: {}" +msgstr "" +"The status of the proxy instance is abnormal, and the document type cannot " +"be executed temporarily: {}" #: backend/ticket/builders/mysql/base.py:120 msgid "请保证所选集群{}与新增机器{}在同一云区域下" @@ -14341,27 +14567,33 @@ msgstr "" #: backend/ticket/builders/pulsar/pulsar_apply.py:71 msgid "最小成功写入副本数量不得大于副本数量" -msgstr "The minimum number of successfully written replicas must not be greater than the number of replicas" +msgstr "" +"The minimum number of successfully written replicas must not be greater than " +"the number of replicas" #: backend/ticket/builders/pulsar/pulsar_apply.py:98 +#: backend/ticket/constants.py:202 #, fuzzy #| msgid "{}集群部署" msgid "Pulsar 集群部署" -msgstr "{} cluster deployment" +msgstr "Pulsar cluster deployment" #: backend/ticket/builders/pulsar/pulsar_destroy.py:37 +#: backend/ticket/constants.py:209 #, fuzzy #| msgid "Pulsar集群" msgid "Pulsar 集群删除" msgstr "Pulsar cluster" #: backend/ticket/builders/pulsar/pulsar_disable.py:37 +#: backend/ticket/constants.py:208 #, fuzzy #| msgid "Pulsar集群" msgid "Pulsar 集群禁用" msgstr "Pulsar cluster" #: backend/ticket/builders/pulsar/pulsar_enable.py:37 +#: backend/ticket/constants.py:207 #, fuzzy #| msgid "Pulsar集群" msgid "Pulsar 集群启用" @@ -14374,12 +14606,14 @@ msgid "Pulsar 集群重启" msgstr "Pulsar cluster" #: backend/ticket/builders/pulsar/pulsar_replace.py:47 +#: backend/ticket/constants.py:206 #, fuzzy #| msgid "Pulsar集群" msgid "Pulsar 集群替换" msgstr "Pulsar cluster" #: backend/ticket/builders/pulsar/pulsar_scale_up.py:47 +#: backend/ticket/constants.py:203 #, fuzzy #| msgid "ES集群扩容" msgid "Pulsar 集群扩容" @@ -14406,6 +14640,7 @@ msgid "缩容不支持ZooKeeper" msgstr "Scaling does not support ZooKeeper" #: backend/ticket/builders/pulsar/pulsar_shrink.py:85 +#: backend/ticket/constants.py:204 #, fuzzy #| msgid "ES集群扩容" msgid "Pulsar 集群缩容" @@ -14838,351 +15073,319 @@ msgstr "Redis cluster disabled" msgid "TenDB Cluster 集群销毁" msgstr "TendisplusCluster cluster" -#: backend/ticket/constants.py:157 +#: backend/ticket/constants.py:155 +#, fuzzy +#| msgid "库表备份" +msgid "Spider 全备" +msgstr "Database table backup" + +#: backend/ticket/constants.py:158 msgid "Redis 单节点部署" msgstr "Redis single node deployment" -#: backend/ticket/constants.py:158 +#: backend/ticket/constants.py:159 msgid "Redis 集群部署" msgstr "Redis cluster deployment" -#: backend/ticket/constants.py:159 +#: backend/ticket/constants.py:160 msgid "Redis 提取 Key" msgstr "Redis Extract Key" -#: backend/ticket/constants.py:160 +#: backend/ticket/constants.py:161 msgid "Redis 删除 key" msgstr "Redis delete key" -#: backend/ticket/constants.py:161 +#: backend/ticket/constants.py:162 msgid "Redis 集群备份" msgstr "Redis cluster backup" -#: backend/ticket/constants.py:162 +#: backend/ticket/constants.py:163 msgid "Redis 集群启用" msgstr "Redis cluster enabled" -#: backend/ticket/constants.py:163 +#: backend/ticket/constants.py:164 msgid "Redis 集群禁用" msgstr "Redis cluster disabled" -#: backend/ticket/constants.py:164 +#: backend/ticket/constants.py:165 #, fuzzy #| msgid "ES 集群删除" msgid "Redis 集群删除" msgstr "ES cluster deletion" -#: backend/ticket/constants.py:165 +#: backend/ticket/constants.py:166 msgid "Redis 集群清档" msgstr "Redis cluster clear file" -#: backend/ticket/constants.py:166 +#: backend/ticket/constants.py:167 msgid "Redis 扩缩容" msgstr "Redis scaling" -#: backend/ticket/constants.py:167 +#: backend/ticket/constants.py:168 msgid "Proxy 扩缩容" msgstr "Proxy expansion and contraction" -#: backend/ticket/constants.py:168 +#: backend/ticket/constants.py:169 msgid "redis集群 slave 裁撤替换" msgstr "redis cluster slave abolition and replacement" -#: backend/ticket/constants.py:169 +#: backend/ticket/constants.py:170 msgid "redis集群 master 裁撤替换" msgstr "redis cluster master abolition and replacement" -#: backend/ticket/constants.py:170 +#: backend/ticket/constants.py:171 msgid "redis集群 proxy 裁撤替换" msgstr "redis cluster proxy abolition and replacement" -#: backend/ticket/constants.py:171 +#: backend/ticket/constants.py:172 msgid "Redis 新建DTS任务" msgstr "Redis new DTS task" #: backend/ticket/constants.py:181 +#, fuzzy +#| msgid "Kafka 集群停用" +msgid "Kafka 集群禁用" +msgstr "Kafka cluster down" + +#: backend/ticket/constants.py:182 msgid "Kafka 集群删除" msgstr "Kafka cluster deletion" -#: backend/ticket/constants.py:183 +#: backend/ticket/constants.py:184 msgid "HDFS 集群部署" msgstr "HDFS cluster deployment" -#: backend/ticket/constants.py:184 +#: backend/ticket/constants.py:185 msgid "HDFS 集群扩容" msgstr "HDFS cluster expansion" -#: backend/ticket/constants.py:185 +#: backend/ticket/constants.py:186 msgid "HDFS 集群缩容" msgstr "HDFS cluster shrink" -#: backend/ticket/constants.py:186 +#: backend/ticket/constants.py:187 msgid "HDFS 实例重启" msgstr "HDFS instance restart" -#: backend/ticket/constants.py:187 +#: backend/ticket/constants.py:188 msgid "HDFS 集群替换" msgstr "HDFS cluster replacement" -#: backend/ticket/constants.py:188 +#: backend/ticket/constants.py:189 msgid "HDFS 集群启用" msgstr "HDFS cluster enabled" -#: backend/ticket/constants.py:189 -msgid "HDFS 集群停用" -msgstr "HDFS cluster decommissioning" - #: backend/ticket/constants.py:190 +#, fuzzy +#| msgid "HDFS集群禁用" +msgid "HDFS 集群禁用" +msgstr "HDFS cluster disabled" + +#: backend/ticket/constants.py:191 msgid "HDFS 集群删除" msgstr "HDFS cluster deletion" -#: backend/ticket/constants.py:192 +#: backend/ticket/constants.py:193 msgid "ES 集群部署" msgstr "ES cluster deployment" -#: backend/ticket/constants.py:193 +#: backend/ticket/constants.py:194 msgid "ES 集群扩容" msgstr "ES cluster expansion" -#: backend/ticket/constants.py:194 +#: backend/ticket/constants.py:195 msgid "ES 集群缩容" msgstr "ES cluster shrinkage" -#: backend/ticket/constants.py:195 +#: backend/ticket/constants.py:196 msgid "ES 实例重启" msgstr "ES instance restart" -#: backend/ticket/constants.py:196 +#: backend/ticket/constants.py:197 msgid "ES 集群替换" msgstr "ES cluster replacement" -#: backend/ticket/constants.py:197 +#: backend/ticket/constants.py:198 msgid "ES 集群启用" msgstr "ES cluster enabled" -#: backend/ticket/constants.py:198 -msgid "ES 集群停用" -msgstr "ES cluster decommissioning" - #: backend/ticket/constants.py:199 -msgid "ES 集群删除" -msgstr "ES cluster deletion" - -#: backend/ticket/constants.py:201 -#, fuzzy -#| msgid "ES 集群部署" -msgid "PULSAR 集群部署" -msgstr "ES cluster deployment" - -#: backend/ticket/constants.py:202 -#, fuzzy -#| msgid "ES 集群扩容" -msgid "PULSAR 集群扩容" -msgstr "ES cluster expansion" - -#: backend/ticket/constants.py:203 -#, fuzzy -#| msgid "ES 集群缩容" -msgid "PULSAR 集群缩容" -msgstr "ES cluster shrinkage" - -#: backend/ticket/constants.py:204 -#, fuzzy -#| msgid "ES 实例重启" -msgid "PULSAR 实例重启" -msgstr "ES instance restart" - -#: backend/ticket/constants.py:205 -#, fuzzy -#| msgid "ES 集群替换" -msgid "PULSAR 集群替换" -msgstr "ES cluster replacement" - -#: backend/ticket/constants.py:206 -#, fuzzy -#| msgid "ES 集群启用" -msgid "PULSAR 集群启用" -msgstr "ES cluster enabled" - -#: backend/ticket/constants.py:207 #, fuzzy #| msgid "ES 集群停用" -msgid "PULSAR 集群停用" +msgid "ES 集群禁用" msgstr "ES cluster decommissioning" -#: backend/ticket/constants.py:208 -#, fuzzy -#| msgid "ES 集群删除" -msgid "PULSAR 集群删除" +#: backend/ticket/constants.py:200 +msgid "ES 集群删除" msgstr "ES cluster deletion" -#: backend/ticket/constants.py:213 +#: backend/ticket/constants.py:205 #, fuzzy -#| msgid "InfluxDB 实例部署" -msgid "InfluxDB 实例停用" -msgstr "InfluxDB instance deployment" +#| msgid "ES 实例重启" +msgid "Pulsar 实例重启" +msgstr "ES instance restart" -#: backend/ticket/constants.py:218 +#: backend/ticket/constants.py:219 msgid "云区域服务部署" msgstr "Cloud Region Service Deployment" -#: backend/ticket/constants.py:219 +#: backend/ticket/constants.py:220 msgid "云区域Nginx 服务部署" msgstr "Nginx Service Deployment in Cloud Regions" -#: backend/ticket/constants.py:220 +#: backend/ticket/constants.py:221 #, fuzzy #| msgid "云区域Nginx 服务部署" msgid "云区域nginx 服务重装" msgstr "Nginx Service Deployment in Cloud Regions" -#: backend/ticket/constants.py:221 +#: backend/ticket/constants.py:222 #, fuzzy #| msgid "云区域Nginx 服务部署" msgid "云区域nginx 服务替换" msgstr "Nginx Service Deployment in Cloud Regions" -#: backend/ticket/constants.py:222 +#: backend/ticket/constants.py:223 msgid "云区域dns 服务部署" msgstr "Cloud zone dns service deployment" -#: backend/ticket/constants.py:223 +#: backend/ticket/constants.py:224 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务添加" msgstr "Cloud zone dns service deployment" -#: backend/ticket/constants.py:224 +#: backend/ticket/constants.py:225 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务裁撤" msgstr "Cloud zone dns service deployment" -#: backend/ticket/constants.py:225 +#: backend/ticket/constants.py:226 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务替换" msgstr "Cloud zone dns service deployment" -#: backend/ticket/constants.py:226 +#: backend/ticket/constants.py:227 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务重装" msgstr "Cloud zone dns service deployment" -#: backend/ticket/constants.py:227 +#: backend/ticket/constants.py:228 msgid "云区域dbha 服务部署" msgstr "Cloud region dbha service deployment" -#: backend/ticket/constants.py:228 +#: backend/ticket/constants.py:229 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务重装" msgstr "Cloud region dbha service deployment" -#: backend/ticket/constants.py:229 +#: backend/ticket/constants.py:230 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务替换" msgstr "Cloud region dbha service deployment" -#: backend/ticket/constants.py:230 +#: backend/ticket/constants.py:231 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务新增" msgstr "Cloud region dbha service deployment" -#: backend/ticket/constants.py:231 +#: backend/ticket/constants.py:232 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务删除" msgstr "Cloud region dbha service deployment" -#: backend/ticket/constants.py:232 +#: backend/ticket/constants.py:233 msgid "云区域drs 服务部署" msgstr "Cloud zone drs service deployment" -#: backend/ticket/constants.py:233 +#: backend/ticket/constants.py:234 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务重启" msgstr "Cloud zone drs service deployment" -#: backend/ticket/constants.py:234 +#: backend/ticket/constants.py:235 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务新增" msgstr "Cloud zone drs service deployment" -#: backend/ticket/constants.py:235 +#: backend/ticket/constants.py:236 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务删除" msgstr "Cloud zone drs service deployment" -#: backend/ticket/constants.py:236 +#: backend/ticket/constants.py:237 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务替换" msgstr "Cloud zone drs service deployment" -#: backend/ticket/constants.py:308 +#: backend/ticket/constants.py:309 msgid "生产部署" msgstr "production deployment" -#: backend/ticket/constants.py:310 +#: backend/ticket/constants.py:311 msgid "快速执行" msgstr "fast execution" -#: backend/ticket/constants.py:312 +#: backend/ticket/constants.py:313 msgid "结果忽略执行" msgstr "result ignore execution" -#: backend/ticket/constants.py:316 +#: backend/ticket/constants.py:317 msgid "交付" msgstr "Deliver" -#: backend/ticket/constants.py:318 +#: backend/ticket/constants.py:319 msgid "描述任务信息" msgstr "Describe task information" -#: backend/ticket/constants.py:324 +#: backend/ticket/constants.py:325 msgid "资源交付" msgstr "resource delivery" -#: backend/ticket/constants.py:326 +#: backend/ticket/constants.py:327 msgid "资源批量申请" msgstr "Resource Batch Application" -#: backend/ticket/constants.py:328 +#: backend/ticket/constants.py:329 msgid "资源批量交付" msgstr "Batch delivery of resources" -#: backend/ticket/constants.py:334 +#: backend/ticket/constants.py:335 msgid "前置动作" msgstr "pre-action" -#: backend/ticket/constants.py:335 +#: backend/ticket/constants.py:336 msgid "后继动作" msgstr "subsequent action" -#: backend/ticket/constants.py:341 +#: backend/ticket/constants.py:342 msgid "自动重试" msgstr "automatic retry" -#: backend/ticket/constants.py:342 +#: backend/ticket/constants.py:343 msgid "手动重试" msgstr "Manual retry" -#: backend/ticket/constants.py:348 +#: backend/ticket/constants.py:349 msgid "通用错误代码" msgstr "generic error code" -#: backend/ticket/constants.py:349 +#: backend/ticket/constants.py:350 msgid "自动互斥重试错误代码" msgstr "Automatic mutex retry error code" -#: backend/ticket/constants.py:350 +#: backend/ticket/constants.py:351 msgid "手动互斥重试错误代码" msgstr "Manual mutex retry error code" @@ -15236,7 +15439,7 @@ msgstr "Duplicate document submission" msgid "单据{ticket_type}提交重复" msgstr "Ticket {ticket_type} executes mutual exclusion" -#: backend/ticket/flow_manager/base.py:149 +#: backend/ticket/flow_manager/base.py:94 msgid "{}流程已跳过" msgstr "{} process skipped" @@ -15248,18 +15451,18 @@ msgstr "successful delivery" msgid "{}执行{}" msgstr "{}implement{}" -#: backend/ticket/flow_manager/inner.py:81 +#: backend/ticket/flow_manager/inner.py:82 #, python-brace-format msgid "任务{status_display}" msgstr "task {status_display}" -#: backend/ticket/flow_manager/inner.py:205 +#: backend/ticket/flow_manager/inner.py:206 msgid "该任务流程跳过,相关信息可在历史任务中查看" msgstr "" "The task process is skipped, and relevant information can be viewed in the " "historical task" -#: backend/ticket/flow_manager/inner.py:225 +#: backend/ticket/flow_manager/inner.py:226 #, python-brace-format msgid "(执行结果可忽略)任务状态: {status_display}" msgstr "(The execution result can be ignored) Task status: {status_display}" @@ -15304,23 +15507,25 @@ msgstr "Permission clone failed, error message: {}\n" #: backend/ticket/flow_manager/resource.py:166 #: backend/ticket/flow_manager/resource.py:206 msgid "资源申请下一个节点不为部署节点,请重新编排" -msgstr "The next node for resource application is not a deployment node, please re-arrange" +msgstr "" +"The next node for resource application is not a deployment node, please re-" +"arrange" -#: backend/ticket/flow_manager/timer.py:55 +#: backend/ticket/flow_manager/timer.py:56 msgid "定时时间{},已超时{},需手动触发。暂停状态:{}" msgstr "" "Timing time {}, has timed out {} and needs to be triggered manually. " "Suspended state: {}" -#: backend/ticket/flow_manager/timer.py:62 +#: backend/ticket/flow_manager/timer.py:63 msgid "定时节点已触发" msgstr "Timing node has been triggered" -#: backend/ticket/flow_manager/timer.py:64 +#: backend/ticket/flow_manager/timer.py:65 msgid "定时时间{},倒计时:{}" msgstr "Timing time {}, countdown: {}" -#: backend/ticket/flow_manager/timer.py:95 +#: backend/ticket/flow_manager/timer.py:96 msgid "【{}】定时流程待确认,是否继续?" msgstr "" "【{}】The scheduled process is to be confirmed. Do you want to continue?" @@ -15402,7 +15607,7 @@ msgstr "Ticket is being created automatically, ticket details: {}" msgid "单据{}正在初始化流程" msgstr "Ticket {} is initializing the process" -#: backend/ticket/models/ticket.py:246 backend/ticket/models/ticket.py:296 +#: backend/ticket/models/ticket.py:246 backend/ticket/models/ticket.py:302 #: backend/ticket/models/todo.py:31 msgid "关联流程任务" msgstr "Associate Process Task" @@ -15455,8 +15660,8 @@ msgstr "operate" msgid "待办操作记录" msgstr "To-do operation record" -#: backend/ticket/serializers.py:71 backend/ticket/views.py:149 -#: backend/ticket/views.py:150 +#: backend/ticket/serializers.py:71 backend/ticket/views.py:172 +#: backend/ticket/views.py:173 msgid "单据详情" msgstr "Ticket details" @@ -15562,67 +15767,75 @@ msgstr "Confirm execution" msgid "终止单据" msgstr "Termination ticket" -#: backend/ticket/views.py:126 +#: backend/ticket/views.py:136 +#, fuzzy +#| msgid "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" +msgid "实例{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" +msgstr "" +"The same type of document [{}] already exists in the cluster {} and is " +"running, please confirm whether to submit it repeatedly" + +#: backend/ticket/views.py:149 msgid "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" msgstr "" "The same type of document [{}] already exists in the cluster {} and is " "running, please confirm whether to submit it repeatedly" -#: backend/ticket/views.py:166 +#: backend/ticket/views.py:189 msgid "单据列表" msgstr "Ticket list" -#: backend/ticket/views.py:183 +#: backend/ticket/views.py:208 msgid "获取单据流程" msgstr "Obtain ticket process" -#: backend/ticket/views.py:185 +#: backend/ticket/views.py:210 msgid "流程信息" msgstr "process information" -#: backend/ticket/views.py:196 +#: backend/ticket/views.py:221 msgid "单据回调" msgstr "Ticket callback" -#: backend/ticket/views.py:209 +#: backend/ticket/views.py:234 msgid "单据流程重试" msgstr "Ticket process retry" -#: backend/ticket/views.py:223 +#: backend/ticket/views.py:248 msgid "获取单据类型列表" msgstr "Get a list of ticket types" -#: backend/ticket/views.py:232 +#: backend/ticket/views.py:257 msgid "节点列表" msgstr "node list" -#: backend/ticket/views.py:261 +#: backend/ticket/views.py:286 msgid "待办单据列表" msgstr "To-Do List" -#: backend/ticket/views.py:299 +#: backend/ticket/views.py:325 msgid "待办处理" msgstr "pending" -#: backend/ticket/views.py:320 +#: backend/ticket/views.py:346 msgid "待办单据数" msgstr "Number of pending tickets" -#: backend/ticket/views.py:344 +#: backend/ticket/views.py:370 msgid "查询集群变更单据事件" msgstr "Query cluster change ticket events" -#: backend/ticket/views.py:380 +#: backend/ticket/views.py:406 #, fuzzy #| msgid "查询集群变更单据事件" msgid "查询集群实例变更单据事件" msgstr "Query cluster change ticket events" -#: backend/ticket/views.py:416 +#: backend/ticket/views.py:442 msgid "快速部署云区域组件" msgstr "Quickly deploy cloud zone components" -#: backend/ticket/views.py:484 +#: backend/ticket/views.py:514 msgid "云区域组件快速部署单据" msgstr "Quick Deployment Document for Cloud Region Components" @@ -15665,317 +15878,3 @@ msgstr "The log version file was not found, please contact the administrator" #: backend/version_log/views.py:69 msgid "日志详情获取成功" msgstr "Log details obtained successfully" - -#~ msgid "{}-接口结果返回异常" -#~ msgstr "{} - interface result returns exception" - -#~ msgid "写入{}服务元信息" -#~ msgstr "Write {} service meta information" - -#~ msgid "cluster[{}] master_ip[{}] master_port[{}]的分区任务" -#~ msgstr "Cluster[{}] master_ip[{}] master_port[{}] partition tasks" - -#~ msgid "下载定点恢复的binlog文件到{}" -#~ msgstr "Download the binlog file for fixed-point recovery to {}" - -#~ msgid "定点恢复之前滚binlog{}" -#~ msgstr "Roll binlog{} before fixed-point recovery" - -#, fuzzy -#~| msgid "安装mysql-crond" -#~ msgid "安装mysql-monitor" -#~ msgstr "Install mysql-crond" - -#, fuzzy -#~| msgid "清理实例级别周边配置" -#~ msgid "清理mysql/spider实例周边配置" -#~ msgstr "Clean up instance-level perimeter configuration" - -#, fuzzy -#~| msgid "清理实例级别周边配置" -#~ msgid "清理中控实例周边配置" -#~ msgstr "Clean up instance-level perimeter configuration" - -#~ msgid "未完成{}场景的定义" -#~ msgstr "Definition of {} scene not completed" - -#~ msgid "实例的ip 地址" -#~ msgstr "instance ip address" - -#~ msgid "实例的port 端口信息" -#~ msgstr "port port information of the instance" - -#~ msgid "实例状态" -#~ msgstr "instance status" - -#~ msgid "实例版本" -#~ msgstr "instance version" - -#~ msgid "在资源池获取资源失败" -#~ msgstr "Failed to obtain resource from resource pool" - -#~ msgid "识别不了单据类型所需要的拼接上下文过程,异常退出[{}]" -#~ msgstr "" -#~ "Unable to recognize the splicing context process required by the ticket " -#~ "type, exit abnormally[{}]" - -#~ msgid "在资源池获取资源成功" -#~ msgstr "Successfully obtained resources from the resource pool" - -#~ msgid "没有找到对应操作方法,请联系系统管理员:[{}]" -#~ msgstr "" -#~ "No corresponding operation method was found, please contact the system " -#~ "administrator: [{}]" - -#~ msgid "申请测试语义实例超时,退出" -#~ msgstr "Application test semantic instance timed out, exit" - -#~ msgid "目前暂时没有可用的测试语义实例,等待10秒重新申请" -#~ msgstr "" -#~ "Currently there is no test semantic instance available, wait 10 seconds " -#~ "to reapply" - -#~ msgid "申请到实例被其他流程已申请到,等待10秒重新申请" -#~ msgstr "" -#~ "The applied instance has already been applied by other processes, wait 10 " -#~ "seconds to reapply" - -#, fuzzy -#~| msgid "权限不足" -#~ msgid "权限不足,无法访问!" -#~ msgstr "Insufficient permissions" - -#~ msgid "节点IP" -#~ msgstr "Node IP" - -#~ msgid "资源池自动分配" -#~ msgstr "Resource pool automatic allocation" - -#~ msgid "集群名字" -#~ msgstr "cluster name" - -#~ msgid "分组名称" -#~ msgstr "Group Name" - -#~ msgid "集群名称" -#~ msgstr "cluster name" - -#~ msgid "旧实例信息" -#~ msgstr "Old instance information" - -#~ msgid "新实例信息" -#~ msgstr "new instance information" - -#~ msgid "重启实例" -#~ msgstr "restart instance" - -#~ msgid "Http端口" -#~ msgstr "HTTP port" - -#~ msgid "{}. 新从库机器信息" -#~ msgstr "{}. New slave machine information" - -#~ msgid "{}. 目标集群" -#~ msgstr "{}. target cluster" - -#~ msgid "{}. 集群" -#~ msgstr "{}.cluster" - -#~ msgid "{}. slave列表" -#~ msgstr "{}.slave list" - -#~ msgid "{}. 匹配DB列表" -#~ msgstr "{}. Match DB list" - -#~ msgid "{}. 忽略DB列表" -#~ msgstr "{}. Ignore DB list" - -#~ msgid "{}. 匹配Table列表" -#~ msgstr "{}. Match Table list" - -#~ msgid "{}. 忽略Table列表" -#~ msgstr "{}. Ignore the Table list" - -#~ msgid "运行时长" -#~ msgstr "run time" - -#~ msgid "是否自动修复" -#~ msgstr "Whether to automatically repair" - -#~ msgid "{}. 集群ID" -#~ msgstr "{}. Cluster ID" - -#~ msgid "{}. 备份新机器IP" -#~ msgstr "{}. Backup new machine IP" - -#~ msgid "{}. 备份源" -#~ msgstr "{}. Backup source" - -#~ msgid "{}. 回档时间" -#~ msgstr "{}. Rollback time" - -#~ msgid "{}. 备份文件ID" -#~ msgstr "{}. Backup file ID" - -#~ msgid "{}. 目标库列表" -#~ msgstr "{}. List of target libraries" - -#~ msgid "{}. 忽略库列表" -#~ msgstr "{}. Ignore db list" - -#~ msgid "{}. 目标table列表" -#~ msgstr "{}. target table list" - -#~ msgid "{}. 忽略table列表" -#~ msgstr "{}. Ignore table list" - -#~ msgid "{}. 起止时间" -#~ msgstr "{}. Start and end time" - -#~ msgid "{}. flashback工具地址" -#~ msgstr "{}. flashback tool address" - -#~ msgid "{}. 记录文件" -#~ msgstr "{}.log file" - -#~ msgid "容灾要求" -#~ msgstr "Disaster recovery requirements" - -#~ msgid "{}. 清档类型" -#~ msgstr "{}.Clear type" - -#~ msgid "{}.是否强制执行" -#~ msgstr "{}.Whether to enforce" - -#~ msgid "备份文件tag(备份保存时间)" -#~ msgstr "Backup file tag (backup save time)" - -#~ msgid "重命名数据库列表信息" -#~ msgstr "Rename database list information" - -#~ msgid "{}. 目标主库 IP" -#~ msgstr "{}. The IP of the target Master" - -#~ msgid "{}. 目标从库 IP" -#~ msgstr "{}. Target slave IP" - -#~ msgid "{}. 新主库-主机信息" -#~ msgstr "{}. New master - host information" - -#~ msgid "{}. 新从库-主机信息" -#~ msgstr "{}. New slave host information" - -#, fuzzy -#~| msgid "{}. 匹配DB列表" -#~ msgid "{}. 配置ID列表" -#~ msgstr "{}. Match DB list" - -#~ msgid "{}-变更的集群" -#~ msgstr "{} - changed cluster" - -#~ msgid "{}-旧Proxy实例信息" -#~ msgstr "{} - Old Proxy instance information" - -#~ msgid "{}-新Proxy机器信息" -#~ msgstr "{}-New Proxy machine information" - -#~ msgid "{}. 从库实例信息" -#~ msgstr "{}. Slave instance information" - -#~ msgid "{}. 所属集群" -#~ msgstr "{}. The cluster to which it belongs" - -#~ msgid "{}. 目标从库实例信息" -#~ msgstr "{}. Target slave instance information" - -#~ msgid "{}. 关联集群" -#~ msgstr "{}. Association cluster" - -#~ msgid "集群数量" -#~ msgstr "number of clusters" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 角色: {}\n" -#~ " 备份类型: {}\n" -#~ msgstr "" -#~ "Cluster[{}]: {}\n" -#~ " Role: {}\n" -#~ " Backup Type: {}\n" - -#~ msgid "备份规则" -#~ msgstr "backup rules" - -#~ msgid "备份结束" -#~ msgstr "end of backup" - -#~ msgid "结束" -#~ msgstr "Finish" - -#~ msgid "集群名:【{}】 已存在,请修改" -#~ msgstr "Cluster name: [{}] already exists, please modify" - -#~ msgid "集群容量" -#~ msgstr "cluster capacity" - -#~ msgid "{}({} x {}分片)" -#~ msgstr "{} ({} x {} slices)" - -#~ msgid "集群架构" -#~ msgstr "cluster architecture" - -#~ msgid "Proxy代理端口" -#~ msgstr "Proxy proxy port" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" -#~ " 文件匹配: {}\n" -#~ msgstr "" -#~ "Cluster[{}]: {}\n" -#~ "Regular match: include -> ({}), exclude -> ({})\n" -#~ "File match: {}\n" - -#~ msgid "删除规则" -#~ msgstr "delete rule" - -#~ msgid "删除结果" -#~ msgstr "delete result" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" -#~ msgstr "" -#~ "Cluster[{}]: {}\n" -#~ " Regex match: Include -> ({}), Exclude -> ({})\n" - -#~ msgid "提取规则" -#~ msgstr "extraction rules" - -#~ msgid "提取结果" -#~ msgstr "extract results" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 集群架构: {}\n" -#~ " 强制清档: {}\n" -#~ " 清档前备份: {}\n" -#~ " 目标DB: {}\n" -#~ msgstr "" -#~ "Cluster [{}]: {}\n" -#~ " Cluster structure: {}\n" -#~ " Forced to clear files: {}\n" -#~ " Backup before clearing files: {}\n" -#~ " Target DB: {}\n" - -#~ msgid "是" -#~ msgstr "yes" - -#~ msgid "否" -#~ msgstr "no" - -#~ msgid "全部" -#~ msgstr "all" - -#~ msgid "清档规则" -#~ msgstr "clearance rules" diff --git a/dbm-ui/locale/zh_hans/LC_MESSAGES/django.mo b/dbm-ui/locale/zh_hans/LC_MESSAGES/django.mo index f8e8ea0af6666797f469251e32bb8a00a1e28182..5fac22875dc232100f8263a6f26d99597b6035d4 100644 GIT binary patch delta 62791 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\n" "Language-Team: LANGUAGE \n" @@ -56,7 +56,7 @@ msgstr "系统错误,请联系管理员({error})" #: backend/db_services/mysql/resources/tendbha/query.py:46 #: backend/db_services/mysql/resources/tendbsingle/query.py:42 #: backend/db_services/redis/resources/redis_cluster/query.py:61 -#: backend/redis_dts/serializers.py:17 +#: backend/db_services/redis_dts/serializers.py:17 #: backend/ticket/builders/mysql/mysql_import_sqlfile.py:66 msgid "创建人" msgstr "创建人" @@ -72,11 +72,10 @@ msgstr "创建人" #: backend/db_services/mysql/resources/tendbsingle/query.py:43 #: backend/db_services/mysql/sql_import/serializers.py:143 #: backend/db_services/redis/resources/redis_cluster/query.py:62 -#: backend/flow/models.py:45 -#: backend/redis_dts/models/tb_dts_distribute_lock.py:19 -#: backend/redis_dts/models/tb_tendis_dts_job.py:57 -#: backend/redis_dts/models/tb_tendis_dts_task.py:70 -#: backend/ticket/models/ticket.py:43 +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:19 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:57 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:70 +#: backend/flow/models.py:45 backend/ticket/models/ticket.py:43 msgid "创建时间" msgstr "创建时间" @@ -90,9 +89,9 @@ msgstr "修改人" #: backend/db_services/bigdata/resources/query.py:50 #: backend/db_services/dbconfig/serializers.py:66 #: backend/db_services/redis/resources/redis_cluster/query.py:64 -#: backend/flow/models.py:47 backend/redis_dts/models/tb_tendis_dts_job.py:58 -#: backend/redis_dts/models/tb_tendis_dts_task.py:71 -#: backend/ticket/models/ticket.py:44 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:58 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:71 +#: backend/flow/models.py:47 backend/ticket/models/ticket.py:44 msgid "更新时间" msgstr "更新时间" @@ -354,6 +353,12 @@ msgstr "根据条件查询业务下的模块" msgid "根据模块ID查询主机和模块的关系" msgstr "根据模块ID查询主机和模块的关系" +#: backend/components/cc/client.py:261 +#, fuzzy +#| msgid "[dbmeta]查询entry信息" +msgid "查询主机业务关系信息" +msgstr "[dbmeta]查询entry信息" + #: backend/components/cmsi/client.py:19 msgid "消息管理" msgstr "消息管理" @@ -711,8 +716,8 @@ msgstr "查询切换详情" msgid "ITSM流程管理" msgstr "ITSM流程管理" -#: backend/components/itsm/client.py:27 backend/ticket/views.py:174 -#: backend/ticket/views.py:176 +#: backend/components/itsm/client.py:27 backend/ticket/views.py:199 +#: backend/ticket/views.py:201 msgid "创建单据" msgstr "创建单据" @@ -999,7 +1004,7 @@ msgstr "初始化配置异常,错误信息:{}" #: backend/configuration/constants.py:21 #: backend/db_services/mysql/permission/constants.py:47 -#: backend/flow/consts.py:239 +#: backend/flow/consts.py:245 msgid "MySQL" msgstr "MySQL" @@ -1013,7 +1018,7 @@ msgstr "tendbcluster" msgid "Redis" msgstr "Redis" -#: backend/configuration/constants.py:24 backend/flow/consts.py:124 +#: backend/configuration/constants.py:24 backend/flow/consts.py:130 msgid "Kafka" msgstr "Kafka" @@ -1025,7 +1030,7 @@ msgstr "HDFS" msgid "ElasticSearch" msgstr "ElasticSearch" -#: backend/configuration/constants.py:27 backend/flow/consts.py:126 +#: backend/configuration/constants.py:27 backend/flow/consts.py:132 msgid "Pulsar" msgstr "Pulsar" @@ -1429,7 +1434,7 @@ msgstr "公开仓库" msgid "私有仓库" msgstr "私有仓库" -#: backend/core/storages/constants.py:31 backend/flow/consts.py:234 +#: backend/core/storages/constants.py:31 backend/flow/consts.py:240 msgid "服务器文件" msgstr "服务器文件" @@ -1602,7 +1607,7 @@ msgstr "日志列表" #: backend/db_services/ipchooser/constants.py:82 #: backend/db_services/ipchooser/mock_data.py:43 #: backend/db_services/ipchooser/mock_data.py:62 -#: backend/db_services/ipchooser/mock_data.py:98 +#: backend/db_services/ipchooser/mock_data.py:98 backend/ticket/handler.py:53 msgid "集群" msgstr "集群" @@ -1622,7 +1627,7 @@ msgstr "实例角色" #: backend/db_event/serializers.py:51 backend/db_event/serializers.py:66 #: backend/db_proxy/views/redis_dts/serializers.py:23 -#: backend/redis_dts/serializers.py:18 +#: backend/db_services/redis_dts/serializers.py:18 #: backend/ticket/builders/mysql/mysql_data_repair.py:36 #: backend/ticket/builders/mysql/mysql_flashback.py:28 #: backend/ticket/serializers.py:111 @@ -1632,7 +1637,7 @@ msgstr "开始时间" #: backend/db_event/serializers.py:52 backend/db_event/serializers.py:53 #: backend/db_event/serializers.py:67 #: backend/db_proxy/views/redis_dts/serializers.py:24 -#: backend/redis_dts/serializers.py:19 +#: backend/db_services/redis_dts/serializers.py:19 #: backend/ticket/builders/mysql/mysql_data_repair.py:37 #: backend/ticket/builders/mysql/mysql_flashback.py:29 #: backend/ticket/serializers.py:112 @@ -1837,7 +1842,7 @@ msgstr "访问入口(主)" msgid "Bookkeeper 节点" msgstr "Bookkeeper 节点" -#: backend/db_meta/api/cluster/tendbcluster/decommission.py:94 +#: backend/db_meta/api/cluster/tendbcluster/decommission.py:80 #: backend/db_meta/api/cluster/tendbha/decommission.py:79 msgid "{} 与 {} 的 {} 有同步关系" msgstr "{} 与 {} 的 {} 有同步关系" @@ -2058,7 +2063,7 @@ msgid "机房 ID" msgstr "机房 ID" #: backend/db_meta/api/storage_instance/apis.py:190 -#: backend/db_meta/models/cluster.py:49 backend/db_meta/models/machine.py:46 +#: backend/db_meta/models/cluster.py:50 backend/db_meta/models/machine.py:46 #: backend/db_proxy/models.py:28 backend/db_proxy/models.py:47 #: backend/db_services/ipchooser/serializers/base.py:90 msgid "云区域 ID" @@ -2069,8 +2074,8 @@ msgid "网络设备 ID" msgstr "网络设备 ID" #: backend/db_meta/enums/access_layer.py:16 -#: backend/db_meta/enums/machine_type.py:18 backend/flow/consts.py:246 -#: backend/flow/consts.py:507 backend/ticket/builders/common/constants.py:62 +#: backend/db_meta/enums/machine_type.py:18 backend/flow/consts.py:252 +#: backend/flow/consts.py:514 backend/ticket/builders/common/constants.py:62 #: backend/ticket/constants.py:23 msgid "proxy" msgstr "proxy" @@ -2126,7 +2131,7 @@ msgstr "destroy" msgid "normal" msgstr "normal" -#: backend/db_meta/enums/cluster_status.py:20 backend/flow/consts.py:417 +#: backend/db_meta/enums/cluster_status.py:20 backend/flow/consts.py:424 msgid "ABNORMAL" msgstr "ABNORMAL" @@ -2138,7 +2143,7 @@ msgstr "tendbsingle" msgid "tendbha" msgstr "tendbha" -#: backend/db_meta/enums/cluster_type.py:18 backend/flow/consts.py:128 +#: backend/db_meta/enums/cluster_type.py:18 backend/flow/consts.py:134 msgid "tendbcluster" msgstr "tendbcluster" @@ -2213,18 +2218,18 @@ msgstr "Mongo副本集" msgid "Mongo分片集群" msgstr "Mongo分片集群" -#: backend/db_meta/enums/comm.py:17 backend/flow/consts.py:641 +#: backend/db_meta/enums/comm.py:17 backend/flow/consts.py:649 #, fuzzy #| msgid "msms" msgid "sms" msgstr "msms" -#: backend/db_meta/enums/comm.py:18 backend/flow/consts.py:640 +#: backend/db_meta/enums/comm.py:18 backend/flow/consts.py:648 msgid "mms" msgstr "mms" #: backend/db_meta/enums/comm.py:22 backend/db_meta/enums/machine_type.py:24 -#: backend/flow/consts.py:170 backend/flow/consts.py:247 +#: backend/flow/consts.py:176 backend/flow/consts.py:253 msgid "redis" msgstr "redis" @@ -2232,13 +2237,13 @@ msgstr "redis" msgid "mongodb" msgstr "mongodb" -#: backend/db_meta/enums/instance_inner_role.py:16 backend/flow/consts.py:508 -#: backend/flow/consts.py:520 backend/ticket/builders/common/constants.py:41 +#: backend/db_meta/enums/instance_inner_role.py:16 backend/flow/consts.py:515 +#: backend/flow/consts.py:527 backend/ticket/builders/common/constants.py:41 #: backend/ticket/builders/common/constants.py:60 msgid "master" msgstr "master" -#: backend/db_meta/enums/instance_inner_role.py:17 backend/flow/consts.py:509 +#: backend/db_meta/enums/instance_inner_role.py:17 backend/flow/consts.py:516 #: backend/ticket/builders/common/constants.py:61 msgid "slave" msgstr "slave" @@ -2307,15 +2312,15 @@ msgid "es_client" msgstr "es_client" #: backend/db_meta/enums/instance_role.py:39 -#: backend/db_meta/enums/machine_type.py:33 backend/flow/consts.py:575 +#: backend/db_meta/enums/machine_type.py:33 backend/flow/consts.py:582 #: backend/ticket/builders/common/constants.py:51 #: backend/ticket/builders/common/constants.py:56 msgid "broker" msgstr "broker" #: backend/db_meta/enums/instance_role.py:40 -#: backend/db_meta/enums/machine_type.py:34 backend/flow/consts.py:569 -#: backend/flow/consts.py:576 backend/ticket/builders/common/constants.py:47 +#: backend/db_meta/enums/machine_type.py:34 backend/flow/consts.py:576 +#: backend/flow/consts.py:583 backend/ticket/builders/common/constants.py:47 #: backend/ticket/builders/common/constants.py:50 #: backend/ticket/builders/common/constants.py:55 msgid "zookeeper" @@ -2339,8 +2344,8 @@ msgid "hdfs_datanode" msgstr "hdfs_datanode" #: backend/db_meta/enums/instance_role.py:47 -#: backend/db_meta/enums/machine_type.py:42 backend/flow/consts.py:183 -#: backend/flow/consts.py:255 +#: backend/db_meta/enums/machine_type.py:42 backend/flow/consts.py:189 +#: backend/flow/consts.py:261 msgid "influxdb" msgstr "influxdb" @@ -2422,12 +2427,12 @@ msgid "spider_mnt" msgstr "spider" #: backend/db_meta/enums/instance_status.py:16 backend/db_proxy/constants.py:35 -#: backend/flow/consts.py:430 +#: backend/flow/consts.py:437 msgid "running" msgstr "running" #: backend/db_meta/enums/instance_status.py:17 backend/db_proxy/constants.py:36 -#: backend/flow/consts.py:432 +#: backend/flow/consts.py:439 msgid "unavailable" msgstr "unavailable" @@ -2435,7 +2440,8 @@ msgstr "unavailable" msgid "restoring" msgstr "restoring" -#: backend/db_meta/enums/machine_type.py:16 backend/flow/consts.py:258 +#: backend/db_meta/enums/machine_type.py:16 backend/flow/consts.py:264 +#: backend/flow/consts.py:721 msgid "spider" msgstr "spider" @@ -2451,13 +2457,13 @@ msgstr "backend" msgid "single" msgstr "single" -#: backend/db_meta/enums/machine_type.py:22 backend/flow/consts.py:177 -#: backend/flow/consts.py:250 +#: backend/db_meta/enums/machine_type.py:22 backend/flow/consts.py:183 +#: backend/flow/consts.py:256 msgid "predixy" msgstr "predixy" -#: backend/db_meta/enums/machine_type.py:23 backend/flow/consts.py:176 -#: backend/flow/consts.py:249 +#: backend/db_meta/enums/machine_type.py:23 backend/flow/consts.py:182 +#: backend/flow/consts.py:255 msgid "twemproxy" msgstr "twemproxy" @@ -2465,11 +2471,11 @@ msgstr "twemproxy" msgid "tendiscache" msgstr "tendiscache" -#: backend/db_meta/enums/machine_type.py:26 backend/flow/consts.py:172 +#: backend/db_meta/enums/machine_type.py:26 backend/flow/consts.py:178 msgid "tendisssd" msgstr "tendisssd" -#: backend/db_meta/enums/machine_type.py:27 backend/flow/consts.py:171 +#: backend/db_meta/enums/machine_type.py:27 backend/flow/consts.py:177 msgid "tendisplus" msgstr "tendisplus" @@ -2495,13 +2501,19 @@ msgstr "DBMeta模块异常" #: backend/db_meta/exceptions.py:23 backend/db_meta/exceptions.py:101 #: backend/flow/engine/bamboo/scene/hdfs/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:22 #: backend/flow/engine/bamboo/scene/pulsar/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:22 msgid "通用异常" msgstr "通用异常" #: backend/db_meta/exceptions.py:24 backend/db_meta/exceptions.py:102 #: backend/flow/engine/bamboo/scene/hdfs/exceptions.py:24 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:23 #: backend/flow/engine/bamboo/scene/pulsar/exceptions.py:24 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:23 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:29 +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:35 #, python-brace-format msgid "{message}" msgstr "{message}" @@ -2511,8 +2523,10 @@ msgid "新建TenDBHA前置检查异常" msgstr "新建TenDBHA前置检查异常" #: backend/db_meta/exceptions.py:30 backend/db_meta/exceptions.py:66 +#: backend/db_services/redis_dts/exceptions.py:24 +#: backend/db_services/redis_dts/exceptions.py:30 +#: backend/flow/engine/exceptions.py:33 #: backend/flow/utils/mysql/db_table_filter/exception.py:24 -#: backend/redis_dts/exceptions.py:24 backend/redis_dts/exceptions.py:30 #, python-brace-format msgid "{msg}" msgstr "{msg}" @@ -2709,7 +2723,8 @@ msgstr "访问入口请求转发和IP绑定混用" #, python-brace-format msgid "" "访问入口 {entry} 绑定到 {bind_cnt} 台机器, 转发到 {forward_to} 不能同时存在" -msgstr "访问入口 {entry} 绑定到 {bind_cnt} 台机器, 转发到 {forward_to} 不能同时存在" +msgstr "" +"访问入口 {entry} 绑定到 {bind_cnt} 台机器, 转发到 {forward_to} 不能同时存在" #: backend/db_meta/exceptions.py:167 #, fuzzy @@ -2755,57 +2770,57 @@ msgstr "运维人员" msgid "CMDB业务信息缓存表" msgstr "CMDB业务信息缓存表" -#: backend/db_meta/models/cluster.py:40 +#: backend/db_meta/models/cluster.py:41 msgid "集群英文名" msgstr "集群英文名" -#: backend/db_meta/models/cluster.py:41 +#: backend/db_meta/models/cluster.py:42 #: backend/db_services/bigdata/resources/query.py:41 #: backend/db_services/redis/resources/redis_cluster/query.py:55 msgid "集群别名" msgstr "集群别名" -#: backend/db_meta/models/cluster.py:46 +#: backend/db_meta/models/cluster.py:47 msgid "主版本号" msgstr "主版本号" -#: backend/db_meta/models/cluster.py:50 +#: backend/db_meta/models/cluster.py:51 msgid "地域" msgstr "地域" -#: backend/db_meta/models/cluster.py:51 +#: backend/db_meta/models/cluster.py:52 msgid "集群所在的时区" msgstr "集群所在的时区" -#: backend/db_meta/models/cluster.py:52 +#: backend/db_meta/models/cluster.py:53 msgid "部署方法ID" msgstr "部署方法ID" -#: backend/db_meta/models/cluster.py:94 +#: backend/db_meta/models/cluster.py:95 msgid "当前操作「{}」与集群{}的操作「{}」存在执行互斥" msgstr "当前操作「{}」与集群{}的操作「{}」存在执行互斥" -#: backend/db_meta/models/cluster.py:102 +#: backend/db_meta/models/cluster.py:103 msgid "集群运行状态异常,请检查!" msgstr "集群运行状态异常,请检查!" -#: backend/db_meta/models/cluster.py:105 +#: backend/db_meta/models/cluster.py:106 msgid "集群已被禁用,请先启用!" msgstr "集群已被禁用,请先启用!" -#: backend/db_meta/models/cluster.py:151 +#: backend/db_meta/models/cluster.py:152 msgid "{} 未实现 status flag" msgstr "{} 未实现 status flag" -#: backend/db_meta/models/cluster.py:171 +#: backend/db_meta/models/cluster.py:172 msgid "{} 未实现 main_storage_instance" msgstr "{} 未实现 main_storage_instance" -#: backend/db_meta/models/cluster.py:195 +#: backend/db_meta/models/cluster.py:196 msgid "{} 类型集群没有中控节点" msgstr "{} 类型集群没有中控节点" -#: backend/db_meta/models/cluster.py:212 +#: backend/db_meta/models/cluster.py:216 msgid "find primary show slave status failed: {}" msgstr "find primary show slave status failed: {}" @@ -2843,9 +2858,9 @@ msgid "分组ID" msgstr "分组ID" #: backend/db_meta/models/group.py:35 -#: backend/ticket/builders/common/bigdata.py:205 -#: backend/ticket/builders/common/bigdata.py:271 -#: backend/ticket/models/ticket.py:294 backend/ticket/serializers.py:225 +#: backend/ticket/builders/common/bigdata.py:209 +#: backend/ticket/builders/common/bigdata.py:275 +#: backend/ticket/models/ticket.py:300 backend/ticket/serializers.py:225 msgid "实例ID" msgstr "实例ID" @@ -2861,26 +2876,25 @@ msgstr "实例结构和状态变更中,请稍后!" msgid "实例运行状态异常,请检查!" msgstr "实例运行状态异常,请检查!" -#: backend/db_meta/models/instance.py:83 backend/db_meta/models/instance.py:150 +#: backend/db_meta/models/instance.py:83 backend/db_meta/models/instance.py:157 #: backend/db_package/models.py:26 -#: backend/ticket/builders/common/bigdata.py:111 +#: backend/ticket/builders/common/bigdata.py:115 #: backend/ticket/builders/influxdb/influxdb_apply.py:31 #: backend/ticket/builders/redis/redis_cluster_apply.py:37 msgid "版本号" msgstr "版本号" #: backend/db_meta/models/instance.py:100 -#: backend/db_meta/models/instance.py:168 +#: backend/db_meta/models/instance.py:175 msgid "实例所在的时区" msgstr "实例所在的时区" #: backend/db_meta/models/instance.py:101 -#: backend/db_meta/models/instance.py:169 +#: backend/db_meta/models/instance.py:176 msgid "对应在cc的服务实例的id" msgstr "对应在cc的服务实例的id" #: backend/db_meta/models/instance.py:102 -#: backend/db_meta/models/storage_instance_ext.py:27 msgid "多 slave 的备选标志" msgstr "多 slave 的备选标志" @@ -3089,7 +3103,7 @@ msgstr "仪表盘" #: backend/db_services/mysql/remote_service/serializers.py:36 #: backend/db_services/partition/serializers.py:44 #: backend/db_services/partition/serializers.py:98 -#: backend/ticket/builders/common/bigdata.py:66 +#: backend/ticket/builders/common/bigdata.py:70 #: backend/ticket/builders/mysql/base.py:165 #: backend/ticket/builders/mysql/mysql_checksum.py:37 #: backend/ticket/builders/mysql/mysql_data_repair.py:28 @@ -3340,9 +3354,9 @@ msgstr "集群名" #: backend/ticket/builders/cloud/service_apply.py:40 #: backend/ticket/builders/cloud/service_apply.py:49 #: backend/ticket/builders/common/base.py:29 -#: backend/ticket/builders/common/bigdata.py:113 -#: backend/ticket/builders/common/bigdata.py:207 -#: backend/ticket/builders/common/bigdata.py:273 +#: backend/ticket/builders/common/bigdata.py:117 +#: backend/ticket/builders/common/bigdata.py:211 +#: backend/ticket/builders/common/bigdata.py:277 #: backend/ticket/builders/influxdb/influxdb_apply.py:37 #: backend/ticket/builders/mysql/mysql_partition.py:48 #: backend/ticket/builders/mysql/mysql_single_apply.py:46 @@ -3434,6 +3448,7 @@ msgstr "逻辑城市名" #: backend/db_proxy/views/db_meta/serializers.py:92 #: backend/db_services/mysql/resources/tendbsingle/query.py:40 +#: backend/ticket/handler.py:64 msgid "实例" msgstr "实例" @@ -3550,8 +3565,8 @@ msgstr "[dbmeta]fake重置dbha集群" #: backend/db_proxy/views/gcs_dns/serializers.py:86 #: backend/db_services/mysql/cluster/serializers.py:45 #: backend/db_services/mysql/instance/serializers.py:42 -#: backend/ticket/builders/common/bigdata.py:209 -#: backend/ticket/builders/common/bigdata.py:275 +#: backend/ticket/builders/common/bigdata.py:213 +#: backend/ticket/builders/common/bigdata.py:279 msgid "实例列表" msgstr "实例列表" @@ -3940,7 +3955,7 @@ msgstr "DTS_server IP" #: backend/db_proxy/views/redis_dts/serializers.py:34 #: backend/db_proxy/views/redis_dts/serializers.py:93 #: backend/db_proxy/views/redis_dts/serializers.py:99 -#: backend/redis_dts/serializers.py:23 +#: backend/db_services/redis_dts/serializers.py:23 msgid "任务ID" msgstr "任务ID" @@ -3948,9 +3963,9 @@ msgstr "任务ID" #: backend/db_proxy/views/redis_dts/serializers.py:35 #: backend/db_proxy/views/redis_dts/serializers.py:94 #: backend/db_proxy/views/redis_dts/serializers.py:100 -#: backend/redis_dts/models/tb_tendis_dts_job.py:43 -#: backend/redis_dts/models/tb_tendis_dts_task.py:24 -#: backend/redis_dts/serializers.py:24 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:43 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:24 +#: backend/db_services/redis_dts/serializers.py:24 #, fuzzy #| msgid "集群" msgid "源集群" @@ -3962,14 +3977,15 @@ msgstr "集群" #: backend/db_proxy/views/redis_dts/serializers.py:101 #: backend/db_services/mysql/permission/authorize/models.py:28 #: backend/db_services/mysql/permission/authorize/serializers.py:28 -#: backend/redis_dts/serializers.py:25 +#: backend/db_services/redis_dts/serializers.py:25 msgid "目标集群" msgstr "目标集群" #: backend/db_proxy/views/redis_dts/serializers.py:41 #: backend/db_proxy/views/redis_dts/serializers.py:47 #: backend/db_proxy/views/redis_dts/serializers.py:114 -#: backend/redis_dts/serializers.py:30 backend/redis_dts/serializers.py:36 +#: backend/db_services/redis_dts/serializers.py:30 +#: backend/db_services/redis_dts/serializers.py:36 #, fuzzy #| msgid "动作ID列表" msgid "子任务ID列表" @@ -3978,8 +3994,8 @@ msgstr "动作ID列表" #: backend/db_proxy/views/redis_dts/serializers.py:49 #: backend/db_services/dbconfig/serializers.py:27 #: backend/db_services/dbresource/serializers.py:144 -#: backend/redis_dts/serializers.py:38 backend/ticket/serializers.py:220 -#: backend/ticket/serializers.py:228 +#: backend/db_services/redis_dts/serializers.py:38 +#: backend/ticket/serializers.py:220 backend/ticket/serializers.py:228 msgid "操作类型" msgstr "操作类型" @@ -4011,7 +4027,7 @@ msgid "task类型列表" msgstr "获取单据类型列表" #: backend/db_proxy/views/redis_dts/serializers.py:80 -#: backend/redis_dts/models/tb_tendis_dts_task.py:52 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:52 msgid "task类型" msgstr "task类型" @@ -4020,8 +4036,8 @@ msgid "限制条数" msgstr "限制条数" #: backend/db_proxy/views/redis_dts/serializers.py:82 -#: backend/redis_dts/models/tb_tendis_dts_job.py:55 -#: backend/redis_dts/models/tb_tendis_dts_task.py:65 +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:55 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:65 #, fuzzy #| msgid "查询任务状态" msgid "任务状态" @@ -4052,7 +4068,8 @@ msgstr "子任务ID" msgid "dtsserver是否在黑名单中" msgstr "dtsserver是否在黑名单中" -#: backend/db_proxy/views/redis_dts/views.py:77 backend/redis_dts/views.py:32 +#: backend/db_proxy/views/redis_dts/views.py:77 +#: backend/db_services/redis_dts/views.py:32 msgid "获取DTS历史任务以及其对应task cnt" msgstr "获取DTS历史任务以及其对应task cnt" @@ -4062,21 +4079,27 @@ msgstr "获取DTS历史任务以及其对应task cnt" msgid "获取dts任务详情" msgstr "任务详情" -#: backend/db_proxy/views/redis_dts/views.py:99 backend/redis_dts/views.py:43 +#: backend/db_proxy/views/redis_dts/views.py:99 +#: backend/db_services/redis_dts/views.py:43 msgid "获取迁移任务task列表,失败的排在前面" msgstr "获取迁移任务task列表,失败的排在前面" -#: backend/db_proxy/views/redis_dts/views.py:109 backend/redis_dts/views.py:54 +#: backend/db_proxy/views/redis_dts/views.py:109 +#: backend/db_services/redis_dts/views.py:54 msgid "" "dts task操作,目前支持 同步完成(syncStopTodo)、强制终止(ForceKillTaskTodo) 两" "个操作" -msgstr "dts task操作,目前支持 同步完成(syncStopTodo)、强制终止(ForceKillTaskTodo) 两个操作" +msgstr "" +"dts task操作,目前支持 同步完成(syncStopTodo)、强制终止(ForceKillTaskTodo) 两" +"个操作" -#: backend/db_proxy/views/redis_dts/views.py:121 backend/redis_dts/views.py:65 +#: backend/db_proxy/views/redis_dts/views.py:121 +#: backend/db_services/redis_dts/views.py:65 msgid "dts tasks重新开始" msgstr "dts tasks重新开始" -#: backend/db_proxy/views/redis_dts/views.py:131 backend/redis_dts/views.py:76 +#: backend/db_proxy/views/redis_dts/views.py:131 +#: backend/db_services/redis_dts/views.py:76 msgid "dts tasks重试当前步骤" msgstr "dts tasks重试当前步骤" @@ -4405,8 +4428,8 @@ msgid "实例地址(ip:port)" msgstr "实例地址(ip:port)" #: backend/db_services/dbbase/resources/serializers.py:48 -#: backend/ticket/builders/common/bigdata.py:202 -#: backend/ticket/builders/common/bigdata.py:269 +#: backend/ticket/builders/common/bigdata.py:206 +#: backend/ticket/builders/common/bigdata.py:273 msgid "IP" msgstr "IP" @@ -4767,8 +4790,8 @@ msgstr "主机ID" #: backend/db_services/mysql/cluster/serializers.py:42 #: backend/db_services/mysql/instance/serializers.py:39 #: backend/ticket/builders/common/base.py:31 -#: backend/ticket/builders/common/bigdata.py:206 -#: backend/ticket/builders/common/bigdata.py:272 +#: backend/ticket/builders/common/bigdata.py:210 +#: backend/ticket/builders/common/bigdata.py:276 msgid "主机ID" msgstr "主机ID" @@ -4887,7 +4910,7 @@ msgid "查询资源导入任务" msgstr "查询资源导入任务" #: backend/db_services/dbresource/views/resource.py:182 -#: backend/ticket/builders/__init__.py:333 backend/ticket/constants.py:322 +#: backend/ticket/builders/__init__.py:333 backend/ticket/constants.py:323 msgid "资源申请" msgstr "资源申请" @@ -5028,10 +5051,10 @@ msgid "标准型S5" msgstr "标准型S5" #: backend/db_services/infras/serializers.py:56 -#: backend/ticket/builders/common/bigdata.py:85 -#: backend/ticket/builders/common/bigdata.py:112 -#: backend/ticket/builders/common/bigdata.py:165 -#: backend/ticket/builders/common/bigdata.py:286 +#: backend/ticket/builders/common/bigdata.py:89 +#: backend/ticket/builders/common/bigdata.py:116 +#: backend/ticket/builders/common/bigdata.py:169 +#: backend/ticket/builders/common/bigdata.py:290 #: backend/ticket/builders/influxdb/influxdb_apply.py:32 #: backend/ticket/builders/mysql/mysql_single_apply.py:57 #: backend/ticket/builders/pulsar/pulsar_shrink.py:31 @@ -5165,6 +5188,10 @@ msgstr "空闲机池" msgid "空闲机" msgstr "空闲机" +#: backend/db_services/ipchooser/query/resource.py:467 +msgid "直连区域" +msgstr "" + #: backend/db_services/ipchooser/serializers/base.py:18 msgid "数据起始位置" msgstr "数据起始位置" @@ -5346,8 +5373,8 @@ msgstr "IP地址" #: backend/db_services/mysql/cluster/serializers.py:43 #: backend/db_services/mysql/instance/serializers.py:40 #: backend/ticket/builders/common/base.py:36 -#: backend/ticket/builders/common/bigdata.py:203 -#: backend/ticket/builders/common/bigdata.py:270 +#: backend/ticket/builders/common/bigdata.py:207 +#: backend/ticket/builders/common/bigdata.py:274 msgid "端口号" msgstr "端口号" @@ -5433,7 +5460,7 @@ msgstr "「接口调用异常」{}" #: backend/db_services/mysql/permission/authorize/models.py:24 #: backend/db_services/mysql/permission/clone/models.py:25 #: backend/ticket/models/ticket.py:45 backend/ticket/models/ticket.py:247 -#: backend/ticket/models/ticket.py:297 backend/ticket/models/todo.py:32 +#: backend/ticket/models/ticket.py:303 backend/ticket/models/todo.py:32 msgid "关联工单" msgstr "关联工单" @@ -6342,1586 +6369,1986 @@ msgstr "基于正则" msgid "基于文件" msgstr "基于文件" -#: backend/db_services/taskflow/exceptions.py:18 -msgid "任务流程模块异常" -msgstr "任务流程模块异常" +#: backend/db_services/redis_dts/constants.py:19 +msgid "tendis ssd备份任务" +msgstr "tendis ssd备份任务" -#: backend/db_services/taskflow/exceptions.py:23 -msgid "重试节点异常" -msgstr "重试节点异常" +#: backend/db_services/redis_dts/constants.py:20 +msgid "tendis ssd备份拉取任务" +msgstr "tendis ssd备份拉取任务" -#: backend/db_services/taskflow/exceptions.py:28 -msgid "回调节点异常" -msgstr "回调节点异常" +#: backend/db_services/redis_dts/constants.py:21 +msgid "tendis ssd备份解析任务" +msgstr "tendis ssd备份解析任务" -#: backend/db_services/taskflow/exceptions.py:33 -msgid "跳过节点异常" -msgstr "跳过节点异常" +#: backend/db_services/redis_dts/constants.py:22 +msgid "tendis ssd数据导入任务" +msgstr "tendis ssd数据导入任务" -#: backend/db_services/taskflow/exceptions.py:38 -msgid "强制失败节点异常" -msgstr "强制失败节点异常" +#: backend/db_services/redis_dts/constants.py:23 +msgid "tendis ssd拉起sync任务" +msgstr "tendis ssd拉起sync任务" -#: backend/db_services/taskflow/exceptions.py:43 -msgid "撤销流程异常" -msgstr "撤销流程异常" +#: backend/db_services/redis_dts/constants.py:24 +#: backend/db_services/redis_dts/constants.py:28 +msgid "tendis ssd监视sync任务" +msgstr "tendis ssd监视sync任务" -#: backend/db_services/taskflow/handlers.py:78 -msgid "人工强制失败" -msgstr "人工强制失败" +#: backend/db_services/redis_dts/constants.py:27 +msgid "redis cache拉起redis-shake任务" +msgstr "redis cache拉起redis-shake任务" -#: backend/db_services/taskflow/handlers.py:125 -msgid "节点尚未运行,请稍后查看" -msgstr "节点尚未运行,请稍后查看" +#: backend/db_services/redis_dts/constants.py:31 +msgid "tendisplus拉起reids-sync任务" +msgstr "tendisplus拉起reids-sync任务" -#: backend/db_services/taskflow/handlers.py:127 -msgid "节点日志仅保留7天" -msgstr "节点日志仅保留7天" +#: backend/db_services/redis_dts/constants.py:33 +#, fuzzy +#| msgid "tendisplus实例安装 元数据" +msgid "tendisplus全量数据同步" +msgstr "tendisplus实例安装 元数据" -#: backend/db_services/taskflow/handlers.py:152 -msgid "日志上报中,请稍后查看" -msgstr "日志上报中,请稍后查看" +#: backend/db_services/redis_dts/constants.py:34 +#, fuzzy +#| msgid "tendisplus实例安装 元数据" +msgid "tendisplus增量数据同步" +msgstr "tendisplus实例安装 元数据" -#: backend/db_services/taskflow/serializers.py:21 -#: backend/ticket/serializers.py:73 -msgid "单据类型名称" -msgstr "单据类型名称" +#: backend/db_services/redis_dts/constants.py:40 +msgid "停止数据同步todo" +msgstr "停止数据同步todo" -#: backend/db_services/taskflow/serializers.py:22 -#: backend/ticket/serializers.py:75 backend/ticket/serializers.py:113 -#: backend/ticket/serializers.py:166 -msgid "耗时" -msgstr "耗时" +#: backend/db_services/redis_dts/constants.py:41 +msgid "停止数据同步失败" +msgstr "停止数据同步失败" -#: backend/db_services/taskflow/serializers.py:48 backend/flow/models.py:39 -msgid "节点ID" -msgstr "节点ID" +#: backend/db_services/redis_dts/constants.py:42 +msgid "停止数据同步成功" +msgstr "停止数据同步成功" -#: backend/db_services/taskflow/serializers.py:52 -msgid "回调描述" -msgstr "回调描述" +#: backend/db_services/redis_dts/constants.py:44 +msgid "强制暂停任务todo" +msgstr "强制暂停任务todo" -#: backend/db_services/taskflow/serializers.py:56 -msgid "版本ID" -msgstr "版本ID" +#: backend/db_services/redis_dts/constants.py:45 +#, fuzzy +#| msgid "创建模拟任务失败!" +msgid "强制暂停任务失败" +msgstr "创建模拟任务失败!" -#: backend/db_services/taskflow/serializers.py:57 -msgid "是否下载日志" -msgstr "是否下载日志" +#: backend/db_services/redis_dts/constants.py:46 +#, fuzzy +#| msgid "创建模拟任务成功" +msgid "强制暂停任务成功" +msgstr "创建模拟任务成功" -#: backend/db_services/taskflow/serializers.py:67 -msgid "目标目录列表" -msgstr "目标目录列表" +#: backend/db_services/redis_dts/constants.py:52 +#, fuzzy +#| msgid "获取集群节点" +msgid "集群节点数变更" +msgstr "获取集群节点" -#: backend/db_services/taskflow/task.py:54 -msgid "存在执行互斥,正在进行重试,当前重试次数为{}" -msgstr "存在执行互斥,正在进行重试,当前重试次数为{}" +#: backend/db_services/redis_dts/constants.py:53 +#, fuzzy +#| msgid "集群类型" +msgid "集群类型变更" +msgstr "集群类型" -#: backend/db_services/taskflow/task.py:58 -msgid "自动重试次数已超过最大重试次数{}, 请重新手动重试" -msgstr "自动重试次数已超过最大重试次数{}, 请重新手动重试" +#: backend/db_services/redis_dts/constants.py:54 +msgid "数据复制" +msgstr "数据复制" -#: backend/db_services/taskflow/task.py:72 -msgid "执行互斥错误信息: {}" -msgstr "执行互斥错误信息: {}" +#: backend/db_services/redis_dts/constants.py:60 +msgid "同一业务不同集群" +msgstr "同一业务不同集群" -#: backend/db_services/taskflow/task.py:79 -msgid "存在执行互斥将自动进行重试..." -msgstr "存在执行互斥将自动进行重试..." +#: backend/db_services/redis_dts/constants.py:61 +msgid "不同业务不同集群" +msgstr "不同业务不同集群" -#: backend/db_services/taskflow/task.py:89 -msgid "重试成功" -msgstr "重试成功" +#: backend/db_services/redis_dts/constants.py:62 +msgid "复制到其他系统" +msgstr "复制到其他系统" -#: backend/db_services/taskflow/views/flow.py:61 -msgid "任务列表" -msgstr "任务列表" +#: backend/db_services/redis_dts/constants.py:63 +msgid "从回档临时环境复制数据" +msgstr "从回档临时环境复制数据" -#: backend/db_services/taskflow/views/flow.py:68 -msgid "任务详情" -msgstr "任务详情" +#: backend/db_services/redis_dts/constants.py:64 +msgid "用户自建redis迁移到DBM" +msgstr "用户自建redis迁移到DBM" -#: backend/db_services/taskflow/views/flow.py:78 -msgid "撤销流程" -msgstr "撤销流程" +#: backend/db_services/redis_dts/constants.py:70 +msgid "自动切换" +msgstr "自动切换" -#: backend/db_services/taskflow/views/flow.py:87 -msgid "重试节点" -msgstr "重试节点" +#: backend/db_services/redis_dts/constants.py:71 +msgid "用户确认切换" +msgstr "用户确认切换" -#: backend/db_services/taskflow/views/flow.py:94 -msgid "非超级用户,暂不允许调用此接口" -msgstr "非超级用户,暂不允许调用此接口" +#: backend/db_services/redis_dts/constants.py:77 +#: backend/ticket/builders/common/constants.py:79 +msgid "自动修复" +msgstr "自动修复" -#: backend/db_services/taskflow/views/flow.py:101 -msgid "跳过节点" -msgstr "跳过节点" +#: backend/db_services/redis_dts/constants.py:78 +msgid "用户确认修复" +msgstr "用户确认修复" -#: backend/db_services/taskflow/views/flow.py:111 -msgid "强制失败节点" -msgstr "强制失败节点" +#: backend/db_services/redis_dts/exceptions.py:18 +#, fuzzy +#| msgid "DBMeta模块异常" +msgid "DBDts模块异常" +msgstr "DBMeta模块异常" -#: backend/db_services/taskflow/views/flow.py:121 -msgid "节点版本列表" -msgstr "节点版本列表" +#: backend/db_services/redis_dts/exceptions.py:23 +#, fuzzy +#| msgid "任务列表" +msgid "获取DTS任务列表异常" +msgstr "任务列表" -#: backend/db_services/taskflow/views/flow.py:132 -msgid "节点日志" -msgstr "节点日志" +#: backend/db_services/redis_dts/exceptions.py:29 +msgid "DTS task操作异常" +msgstr "DTS task操作异常" -#: backend/db_services/taskflow/views/flow.py:154 -msgid "回调节点" -msgstr "回调节点" +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:17 +#, fuzzy +#| msgid "关键字唯一标识" +msgid "锁的唯一标识" +msgstr "关键字唯一标识" -#: backend/db_services/taskflow/views/redis.py:49 -msgid "结果文件列表" -msgstr "结果文件列表" +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:18 +msgid "锁的持有者" +msgstr "锁的持有者" -#: backend/db_services/taskflow/views/redis.py:94 -msgid "打包下载结果文件列表" -msgstr "打包下载结果文件列表" +#: backend/db_services/redis_dts/models/tb_dts_distribute_lock.py:20 +msgid "锁的过期时间" +msgstr "锁的过期时间" -#: backend/db_services/taskflow/views/redis.py:122 -msgid "指定目录下载(返回下载链接)" -msgstr "指定目录下载(返回下载链接)" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:17 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:19 +#, fuzzy +#| msgid "单据" +msgid "单据号" +msgstr "单据" -#: backend/db_services/user/serializers.py:16 -msgid "模糊搜索" -msgstr "模糊搜索" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:18 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:21 +msgid "业务bk_biz_id" +msgstr "业务bk_biz_id" -#: backend/db_services/user/serializers.py:18 -msgid "不分页,即将下架,请不要使用,并尽快迁移" -msgstr "不分页,即将下架,请不要使用,并尽快迁移" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:19 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:22 +msgid "云区域id" +msgstr "云区域id" -#: backend/db_services/version/constants.py:23 -msgid "MySQL-5.6" -msgstr "MySQL-5.6" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:20 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:20 +msgid "申请人" +msgstr "申请人" -#: backend/db_services/version/constants.py:24 -msgid "MySQL-5.7" -msgstr "MySQL-5.7" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:25 +#, fuzzy +#| msgid "单据类型" +msgid "DTS单据类型" +msgstr "单据类型" -#: backend/db_services/version/constants.py:25 -msgid "MySQL-8.0" -msgstr "MySQL-8.0" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:32 +msgid "DTS数据复制类型" +msgstr "DTS数据复制类型" -#: backend/db_services/version/constants.py:31 -msgid "Redis-6" -msgstr "Redis-6" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:36 +msgid "在线切换类型" +msgstr "在线切换类型" -#: backend/db_services/version/constants.py:37 -msgid "Tendisplus-2.5" -msgstr "Tendisplus-2.5" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:37 +#, fuzzy +#| msgid "数据校验执行" +msgid "是否数据校验" +msgstr "数据校验执行" -#: backend/db_services/version/constants.py:38 -msgid "Tendisplus-2.6" -msgstr "Tendisplus-2.6" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:38 +#, fuzzy +#| msgid "{}数据修复" +msgid "是否数据修复" +msgstr "{}数据修复" -#: backend/db_services/version/constants.py:44 -msgid "TendisSSD-1.2" -msgstr "TendisSSD-1.2" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:42 +msgid "数据修复模式" +msgstr "数据修复模式" -#: backend/db_services/version/constants.py:45 -msgid "TendisSSD-1.3" -msgstr "TendisSSD-1.3" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:45 +#, fuzzy +#| msgid "集群类型" +msgid "源集群类型" +msgstr "集群类型" -#: backend/db_services/version/constants.py:51 -msgid "TwemproxyLatest" -msgstr "TwemproxyLatest" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:46 +msgid "回滚单据号" +msgstr "回滚单据号" -#: backend/db_services/version/constants.py:57 -msgid "PredixyLatest" -msgstr "PredixyLatest" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:47 +msgid "回滚临时环境实例" +msgstr "回滚临时环境实例" -#: backend/db_services/version/serializers.py:20 -msgid "查询关键字" -msgstr "查询关键字" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:48 +msgid "目标业务id" +msgstr "目标业务id" -#: backend/db_services/version/views.py:27 -msgid "查询数据库版本列表" -msgstr "查询数据库版本列表" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:49 +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:49 +msgid "目的集群" +msgstr "目的集群" -#: backend/exceptions.py:48 -msgid "系统异常" -msgstr "系统异常" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:51 +#, fuzzy +#| msgid "集群类型" +msgid "目标集群类型" +msgstr "集群类型" -#: backend/exceptions.py:103 -msgid "系统错误" -msgstr "系统错误" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:52 +msgid "key正则(包含key)" +msgstr "key正则(包含key)" -#: backend/exceptions.py:113 -msgid "参数验证失败" -msgstr "参数验证失败" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:53 +msgid "key正则(排除key)" +msgstr "key正则(排除key)" -#: backend/exceptions.py:118 -msgid "远程服务请求结果异常" -msgstr "远程服务请求结果异常" +#: backend/db_services/redis_dts/models/tb_tendis_dts_job.py:56 +msgid "bill备注" +msgstr "bill备注" -#: backend/exceptions.py:123 -msgid "组件调用异常" -msgstr "组件调用异常" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:23 +msgid "执行迁移任务的dts_server" +msgstr "执行迁移任务的dts_server" -#: backend/exceptions.py:128 -msgid "业务不存在" -msgstr "业务不存在" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:25 +msgid "源集群优先级,值越大,优先级越高" +msgstr "源集群优先级,值越大,优先级越高" -#: backend/exceptions.py:133 -msgid "语言不支持" -msgstr "语言不支持" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:26 +#, fuzzy +#| msgid "slave" +msgid "源slave_ip" +msgstr "slave" -#: backend/exceptions.py:138 -msgid "权限不足" -msgstr "权限不足" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:27 +msgid "源slave_port" +msgstr "源slave_port" -#: backend/exceptions.py:165 -msgid "服务不稳定,请检查组件健康状况" -msgstr "服务不稳定,请检查组件健康状况" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:28 +msgid "源实例密码base64值" +msgstr "源实例密码base64值" -#: backend/flow/consts.py:101 -msgid "创建态" -msgstr "创建态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:30 +msgid "源slave db类型" +msgstr "源slave db类型" -#: backend/flow/consts.py:102 -msgid "准备态" -msgstr "准备态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:32 +msgid "源实例数据量大小,单位Byte" +msgstr "源实例数据量大小,单位Byte" -#: backend/flow/consts.py:103 -msgid "运行态" -msgstr "运行态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:34 +msgid "源实例所属segment_start" +msgstr "源实例所属segment_start" -#: backend/flow/consts.py:104 -msgid "暂停态" -msgstr "暂停态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:35 +msgid "源实例所属segment_end" +msgstr "源实例所属segment_end" -#: backend/flow/consts.py:105 -msgid "闭塞态" -msgstr "闭塞态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:37 +msgid "源实例权重" +msgstr "源实例权重" -#: backend/flow/consts.py:106 -msgid "完成态" -msgstr "完成态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:39 +msgid "源slave_ip上task并发数控制" +msgstr "源slave_ip上task并发数控制" -#: backend/flow/consts.py:107 -msgid "失败态" -msgstr "失败态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:40 +#, fuzzy +#| msgid "实例所在的时区" +msgid "源实例所在城市" +msgstr "实例所在的时区" -#: backend/flow/consts.py:108 -msgid "取消态" -msgstr "取消态" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:42 +msgid "源实例slave-keep-log-count的旧值" +msgstr "源实例slave-keep-log-count的旧值" -#: backend/flow/consts.py:116 -msgid "共用参数" -msgstr "共用参数" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:43 +msgid "源实例slave-keep-log-count的新值" +msgstr "源实例slave-keep-log-count的新值" -#: backend/flow/consts.py:117 -msgid "redis共用参数" -msgstr "redis共用参数" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:44 +msgid "源实例slave-keep-log-count是否恢复" +msgstr "源实例slave-keep-log-count是否恢复" -#: backend/flow/consts.py:118 -msgid "TenDBHA" -msgstr "TenDBHA" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:45 +msgid "srcRedis是否包含list类型key" +msgstr "srcRedis是否包含list类型key" -#: backend/flow/consts.py:119 -msgid "RedisCache 主从版" -msgstr "RedisCache 主从版" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:46 +msgid "包含key(正则)" +msgstr "包含key(正则)" -#: backend/flow/consts.py:120 -msgid "twemproxy + RedisInstance架构" -msgstr "twemproxy + RedisInstance架构" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:47 +msgid "排除key(正则)" +msgstr "排除key(正则)" -#: backend/flow/consts.py:121 -msgid "predixy + tendisplus架构" -msgstr "predixy + tendisplus架构" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:50 +msgid "目的密码base64值" +msgstr "目的密码base64值" -#: backend/flow/consts.py:122 -msgid "Es" -msgstr "Es" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:53 +msgid "tendisssd slave上bakup文件位置" +msgstr "tendisssd slave上bakup文件位置" -#: backend/flow/consts.py:123 -msgid "tendb" -msgstr "tendb" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:54 +msgid "backup文件拉取到dts_server本地位置" +msgstr "backup文件拉取到dts_server本地位置" -#: backend/flow/consts.py:125 -msgid "Hdfs" -msgstr "Hdfs" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:55 +msgid "tendisdumper得到的sql文件夹" +msgstr "tendisdumper得到的sql文件夹" -#: backend/flow/consts.py:127 -msgid "Influxdb" -msgstr "Influxdb" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:56 +msgid "redis-sync端口" +msgstr "redis-sync端口" -#: backend/flow/consts.py:132 -msgid "初始化帐户" -msgstr "初始化帐户" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:57 +msgid "sync的进程id" +msgstr "sync的进程id" -#: backend/flow/consts.py:133 -msgid "实例和帐户" -msgstr "实例和帐户" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:59 +msgid "task重试次数" +msgstr "task重试次数" -#: backend/flow/consts.py:134 -msgid "系统配置" -msgstr "系统配置" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:61 +msgid "sync操作" +msgstr "sync操作" -#: backend/flow/consts.py:135 -msgid "实例配置" -msgstr "实例配置" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:63 +msgid "杀死syncer" +msgstr "杀死syncer" -#: backend/flow/consts.py:136 -msgid "默认配置" -msgstr "默认配置" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:66 +#, fuzzy +#| msgid "domain信息" +msgid "信息" +msgstr "domain信息" -#: backend/flow/consts.py:137 -msgid "proxyconfig" -msgstr "proxyconfig" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:68 +msgid "被忽略的错误" +msgstr "被忽略的错误" -#: backend/flow/consts.py:138 -msgid "ES实例配置" -msgstr "ES实例配置" +#: backend/db_services/redis_dts/models/tb_tendis_dts_task.py:69 +msgid "sync从该时间点重新同步" +msgstr "sync从该时间点重新同步" -#: backend/flow/consts.py:139 -msgid "act配置" -msgstr "act配置" +#: backend/db_services/taskflow/exceptions.py:18 +msgid "任务流程模块异常" +msgstr "任务流程模块异常" -#: backend/flow/consts.py:140 -msgid "系统配置类型" -msgstr "系统配置类型" +#: backend/db_services/taskflow/exceptions.py:23 +msgid "重试节点异常" +msgstr "重试节点异常" -#: backend/flow/consts.py:141 -msgid "Kafka实例配置" -msgstr "Kafka实例配置" +#: backend/db_services/taskflow/exceptions.py:28 +msgid "回调节点异常" +msgstr "回调节点异常" -#: backend/flow/consts.py:142 -msgid "HDFS集群配置" -msgstr "HDFS集群配置" +#: backend/db_services/taskflow/exceptions.py:33 +msgid "跳过节点异常" +msgstr "跳过节点异常" -#: backend/flow/consts.py:143 -msgid "HDFS实例hdfs-site配置" -msgstr "HDFS实例hdfs-site配置" +#: backend/db_services/taskflow/exceptions.py:38 +msgid "强制失败节点异常" +msgstr "强制失败节点异常" -#: backend/flow/consts.py:144 -msgid "HDFS实例core-site配置" -msgstr "HDFS实例core-site配置" +#: backend/db_services/taskflow/exceptions.py:43 +msgid "撤销流程异常" +msgstr "撤销流程异常" -#: backend/flow/consts.py:145 -msgid "HDFS实例安装配置" -msgstr "HDFS实例安装配置" - -#: backend/flow/consts.py:149 -msgid "系统" -msgstr "系统" +#: backend/db_services/taskflow/handlers.py:78 +msgid "人工强制失败" +msgstr "人工强制失败" -#: backend/flow/consts.py:150 -msgid "twemproxy config file" -msgstr "twemproxy config file" +#: backend/db_services/taskflow/handlers.py:125 +msgid "节点尚未运行,请稍后查看" +msgstr "节点尚未运行,请稍后查看" -#: backend/flow/consts.py:151 -msgid "predixy config file" -msgstr "predixy config file" +#: backend/db_services/taskflow/handlers.py:127 +msgid "节点日志仅保留7天" +msgstr "节点日志仅保留7天" -#: backend/flow/consts.py:152 -msgid "redis config file" -msgstr "redis config file" +#: backend/db_services/taskflow/handlers.py:152 +msgid "日志上报中,请稍后查看" +msgstr "日志上报中,请稍后查看" -#: backend/flow/consts.py:153 -msgid "全备配置" -msgstr "全备配置" +#: backend/db_services/taskflow/serializers.py:21 +#: backend/ticket/serializers.py:73 +msgid "单据类型名称" +msgstr "单据类型名称" -#: backend/flow/consts.py:154 -msgid "增备配置" -msgstr "增备配置" +#: backend/db_services/taskflow/serializers.py:22 +#: backend/ticket/serializers.py:75 backend/ticket/serializers.py:113 +#: backend/ticket/serializers.py:166 +msgid "耗时" +msgstr "耗时" -#: backend/flow/consts.py:155 -msgid "心跳配置" -msgstr "心跳配置" +#: backend/db_services/taskflow/serializers.py:48 backend/flow/models.py:39 +msgid "节点ID" +msgstr "节点ID" -#: backend/flow/consts.py:156 -msgid "监控配置" -msgstr "监控配置" +#: backend/db_services/taskflow/serializers.py:52 +msgid "回调描述" +msgstr "回调描述" -#: backend/flow/consts.py:157 -msgid "基本配置" -msgstr "基本配置" +#: backend/db_services/taskflow/serializers.py:56 +msgid "版本ID" +msgstr "版本ID" -#: backend/flow/consts.py:158 -msgid "热key配置" -msgstr "热key配置" +#: backend/db_services/taskflow/serializers.py:57 +msgid "是否下载日志" +msgstr "是否下载日志" -#: backend/flow/consts.py:159 -msgid "大key配置" -msgstr "大key配置" +#: backend/db_services/taskflow/serializers.py:67 +msgid "目标目录列表" +msgstr "目标目录列表" -#: backend/flow/consts.py:163 -msgid "MASTER" -msgstr "MASTER" +#: backend/db_services/taskflow/task.py:54 +msgid "存在执行互斥,正在进行重试,当前重试次数为{}" +msgstr "存在执行互斥,正在进行重试,当前重试次数为{}" -#: backend/flow/consts.py:164 -msgid "SLAVE" -msgstr "SLAVE" +#: backend/db_services/taskflow/task.py:58 +msgid "自动重试次数已超过最大重试次数{}, 请重新手动重试" +msgstr "自动重试次数已超过最大重试次数{}, 请重新手动重试" -#: backend/flow/consts.py:168 backend/flow/consts.py:245 -msgid "mysql" -msgstr "mysql" +#: backend/db_services/taskflow/task.py:72 +msgid "执行互斥错误信息: {}" +msgstr "执行互斥错误信息: {}" -#: backend/flow/consts.py:169 -msgid "mysql-proxy" -msgstr "mysql-proxy" +#: backend/db_services/taskflow/task.py:79 +msgid "存在执行互斥将自动进行重试..." +msgstr "存在执行互斥将自动进行重试..." -#: backend/flow/consts.py:173 -msgid "dbbackup" -msgstr "dbbackup" +#: backend/db_services/taskflow/task.py:89 +msgid "重试成功" +msgstr "重试成功" -#: backend/flow/consts.py:174 -msgid "actuator" -msgstr "actuator" +#: backend/db_services/taskflow/views/flow.py:61 +msgid "任务列表" +msgstr "任务列表" -#: backend/flow/consts.py:175 -msgid "最新版本" -msgstr "最新版本" +#: backend/db_services/taskflow/views/flow.py:68 +msgid "任务详情" +msgstr "任务详情" -#: backend/flow/consts.py:178 -msgid "redis_tools" -msgstr "redis_tools" +#: backend/db_services/taskflow/views/flow.py:78 +msgid "撤销流程" +msgstr "撤销流程" -#: backend/flow/consts.py:179 backend/flow/consts.py:251 -msgid "es" -msgstr "es" +#: backend/db_services/taskflow/views/flow.py:87 +msgid "重试节点" +msgstr "重试节点" -#: backend/flow/consts.py:180 backend/flow/consts.py:252 -msgid "kafka" -msgstr "kafka" +#: backend/db_services/taskflow/views/flow.py:94 +msgid "非超级用户,暂不允许调用此接口" +msgstr "非超级用户,暂不允许调用此接口" -#: backend/flow/consts.py:181 backend/flow/consts.py:253 -msgid "hdfs" -msgstr "hdfs" +#: backend/db_services/taskflow/views/flow.py:101 +msgid "跳过节点" +msgstr "跳过节点" -#: backend/flow/consts.py:182 backend/flow/consts.py:254 -msgid "pulsar" -msgstr "pulsar" +#: backend/db_services/taskflow/views/flow.py:111 +msgid "强制失败节点" +msgstr "强制失败节点" -#: backend/flow/consts.py:184 -msgid "dbmon" -msgstr "dbmon" +#: backend/db_services/taskflow/views/flow.py:121 +msgid "节点版本列表" +msgstr "节点版本列表" -#: backend/flow/consts.py:185 -msgid "mysql-checksum" -msgstr "mysql-checksum" +#: backend/db_services/taskflow/views/flow.py:132 +msgid "节点日志" +msgstr "节点日志" -#: backend/flow/consts.py:186 -msgid "Binlog 滚动备份工具" -msgstr "Binlog 滚动备份工具" +#: backend/db_services/taskflow/views/flow.py:154 +msgid "回调节点" +msgstr "回调节点" -#: backend/flow/consts.py:187 -msgid "DBA 工具集" -msgstr "DBA 工具集" +#: backend/db_services/taskflow/views/redis.py:49 +msgid "结果文件列表" +msgstr "结果文件列表" -#: backend/flow/consts.py:188 -msgid "mysql-crond" -msgstr "mysql-crond" +#: backend/db_services/taskflow/views/redis.py:94 +msgid "打包下载结果文件列表" +msgstr "打包下载结果文件列表" -#: backend/flow/consts.py:189 -msgid "MySQL 监控" -msgstr "MySQL 监控" +#: backend/db_services/taskflow/views/redis.py:122 +msgid "指定目录下载(返回下载链接)" +msgstr "指定目录下载(返回下载链接)" -#: backend/flow/consts.py:190 -msgid "nginx 服务" -msgstr "nginx 服务" +#: backend/db_services/user/serializers.py:16 +msgid "模糊搜索" +msgstr "模糊搜索" -#: backend/flow/consts.py:191 -msgid "dns-bind 服务" -msgstr "dns-bind 服务" +#: backend/db_services/user/serializers.py:18 +msgid "不分页,即将下架,请不要使用,并尽快迁移" +msgstr "不分页,即将下架,请不要使用,并尽快迁移" -#: backend/flow/consts.py:192 -msgid "dns-pull-crond服务" -msgstr "dns-pull-crond服务" +#: backend/db_services/version/constants.py:23 +msgid "MySQL-5.6" +msgstr "MySQL-5.6" -#: backend/flow/consts.py:193 -msgid "cloud-dbha服务" -msgstr "cloud-dbha服务" +#: backend/db_services/version/constants.py:24 +msgid "MySQL-5.7" +msgstr "MySQL-5.7" -#: backend/flow/consts.py:194 -msgid "cloud-drs服务" -msgstr "cloud-drs服务" +#: backend/db_services/version/constants.py:25 +msgid "MySQL-8.0" +msgstr "MySQL-8.0" -#: backend/flow/consts.py:195 -msgid "cloud-drs-tmysqlparse服务" -msgstr "cloud-drs-tmysqlparse服务" +#: backend/db_services/version/constants.py:31 +msgid "Redis-6" +msgstr "Redis-6" -#: backend/flow/consts.py:196 -msgid "spider节点名称" -msgstr "spider节点名称" +#: backend/db_services/version/constants.py:37 +msgid "Tendisplus-2.5" +msgstr "Tendisplus-2.5" -#: backend/flow/consts.py:197 -msgid "spider中控节点名称" -msgstr "spider中控节点名称" +#: backend/db_services/version/constants.py:38 +msgid "Tendisplus-2.6" +msgstr "Tendisplus-2.6" -#: backend/flow/consts.py:201 -msgid "nginx服务" -msgstr "nginx服务" +#: backend/db_services/version/constants.py:44 +msgid "TendisSSD-1.2" +msgstr "TendisSSD-1.2" -#: backend/flow/consts.py:202 -msgid "dns服务" -msgstr "dns服务" +#: backend/db_services/version/constants.py:45 +msgid "TendisSSD-1.3" +msgstr "TendisSSD-1.3" -#: backend/flow/consts.py:203 -msgid "drs服务" -msgstr "drs服务" +#: backend/db_services/version/constants.py:51 +msgid "TwemproxyLatest" +msgstr "TwemproxyLatest" -#: backend/flow/consts.py:204 -msgid "dbha服务" -msgstr "dbha服务" +#: backend/db_services/version/constants.py:57 +msgid "PredixyLatest" +msgstr "PredixyLatest" -#: backend/flow/consts.py:208 -msgid "pull-crond.conf" -msgstr "pull-crond.conf" +#: backend/db_services/version/serializers.py:20 +msgid "查询关键字" +msgstr "查询关键字" -#: backend/flow/consts.py:209 -msgid "ha-gm.conf" -msgstr "ha-gm.conf" +#: backend/db_services/version/views.py:27 +msgid "查询数据库版本列表" +msgstr "查询数据库版本列表" -#: backend/flow/consts.py:210 -msgid "ha-agent.conf" -msgstr "ha-agent.conf" +#: backend/dbm_init/management/commands/cloud_component.py:38 +#, fuzzy +#| msgid "下发文件job启动失败,错误信息: {}" +msgid "云区域组件初始化失败,错误信息:{}" +msgstr "下发文件job启动失败,错误信息: {}" -#: backend/flow/consts.py:211 -msgid "drs.env" -msgstr "drs.env" +#: backend/exceptions.py:48 +msgid "系统异常" +msgstr "系统异常" -#: backend/flow/consts.py:215 -msgid "GM" -msgstr "GM" +#: backend/exceptions.py:103 +msgid "系统错误" +msgstr "系统错误" -#: backend/flow/consts.py:216 -msgid "AGENT" -msgstr "AGENT" +#: backend/exceptions.py:113 +msgid "参数验证失败" +msgstr "参数验证失败" -#: backend/flow/consts.py:217 -msgid "mysql-monitor" -msgstr "mysql-monitor" +#: backend/exceptions.py:118 +msgid "远程服务请求结果异常" +msgstr "远程服务请求结果异常" -#: backend/flow/consts.py:227 -msgid "nginx服务模块" -msgstr "nginx服务模块" +#: backend/exceptions.py:123 +msgid "组件调用异常" +msgstr "组件调用异常" -#: backend/flow/consts.py:228 -msgid "dns服务模块" -msgstr "dns服务模块" +#: backend/exceptions.py:128 +msgid "业务不存在" +msgstr "业务不存在" -#: backend/flow/consts.py:229 -msgid "drs服务模块" -msgstr "drs服务模块" +#: backend/exceptions.py:133 +msgid "语言不支持" +msgstr "语言不支持" -#: backend/flow/consts.py:230 -msgid "dbha服务模块" -msgstr "dbha服务模块" +#: backend/exceptions.py:138 +msgid "权限不足" +msgstr "权限不足" -#: backend/flow/consts.py:235 -msgid "蓝盾制品库" -msgstr "蓝盾制品库" +#: backend/exceptions.py:165 +msgid "服务不稳定,请检查组件健康状况" +msgstr "服务不稳定,请检查组件健康状况" -#: backend/flow/consts.py:240 -msgid "V1" -msgstr "V1" +#: backend/flow/consts.py:107 +msgid "创建态" +msgstr "创建态" -#: backend/flow/consts.py:248 -msgid "tendis" -msgstr "tendis" +#: backend/flow/consts.py:108 +msgid "准备态" +msgstr "准备态" -#: backend/flow/consts.py:256 -msgid "bkdbmon" -msgstr "bkdbmon" +#: backend/flow/consts.py:109 +msgid "运行态" +msgstr "运行态" -#: backend/flow/consts.py:257 -msgid "download" -msgstr "download" +#: backend/flow/consts.py:110 +msgid "暂停态" +msgstr "暂停态" -#: backend/flow/consts.py:259 -msgid "spiderctl" -msgstr "spiderctl" +#: backend/flow/consts.py:111 +msgid "闭塞态" +msgstr "闭塞态" -#: backend/flow/consts.py:263 backend/flow/consts.py:306 -msgid "sysinit" -msgstr "sysinit" +#: backend/flow/consts.py:112 +msgid "完成态" +msgstr "完成态" -#: backend/flow/consts.py:264 -msgid "deploy" -msgstr "deploy" +#: backend/flow/consts.py:113 +msgid "失败态" +msgstr "失败态" -#: backend/flow/consts.py:265 -msgid "find-local-backup" -msgstr "find-local-backup" +#: backend/flow/consts.py:114 +msgid "取消态" +msgstr "取消态" -#: backend/flow/consts.py:266 -msgid "restore-dr" -msgstr "restore-dr" +#: backend/flow/consts.py:122 +msgid "共用参数" +msgstr "共用参数" -#: backend/flow/consts.py:267 -msgid "recover-binlog" -msgstr "recover-binlog" +#: backend/flow/consts.py:123 +msgid "redis共用参数" +msgstr "redis共用参数" -#: backend/flow/consts.py:268 -msgid "grant-repl" -msgstr "grant-repl" +#: backend/flow/consts.py:124 +msgid "TenDBHA" +msgstr "TenDBHA" -#: backend/flow/consts.py:269 -msgid "change-master" -msgstr "change-master" +#: backend/flow/consts.py:125 +msgid "RedisCache 主从版" +msgstr "RedisCache 主从版" -#: backend/flow/consts.py:270 -msgid "set-backend" -msgstr "set-backend" +#: backend/flow/consts.py:126 +msgid "twemproxy + RedisInstance架构" +msgstr "twemproxy + RedisInstance架构" -#: backend/flow/consts.py:271 -msgid "uninstall" -msgstr "uninstall" +#: backend/flow/consts.py:127 +msgid "predixy + tendisplus架构" +msgstr "predixy + tendisplus架构" -#: backend/flow/consts.py:272 -msgid "deploy-dbbackup" -msgstr "deploy-dbbackup" +#: backend/flow/consts.py:128 +msgid "Es" +msgstr "Es" -#: backend/flow/consts.py:273 -msgid "install-monitor" -msgstr "install-monitor" +#: backend/flow/consts.py:129 +msgid "tendb" +msgstr "tendb" -#: backend/flow/consts.py:274 -msgid "deploy-rotate" -msgstr "deploy-rotate" +#: backend/flow/consts.py:131 +msgid "Hdfs" +msgstr "Hdfs" -#: backend/flow/consts.py:275 backend/flow/consts.py:281 -msgid "semantic-dumpschema" -msgstr "semantic-dumpschema" +#: backend/flow/consts.py:133 +msgid "Influxdb" +msgstr "Influxdb" -#: backend/flow/consts.py:276 -msgid "import-sqlfile" -msgstr "import-sqlfile" +#: backend/flow/consts.py:138 +msgid "初始化帐户" +msgstr "初始化帐户" -#: backend/flow/consts.py:277 -msgid "clone-client-grant" -msgstr "clone-client-grant" +#: backend/flow/consts.py:139 +msgid "实例和帐户" +msgstr "实例和帐户" -#: backend/flow/consts.py:278 -msgid "clone-proxy-user" -msgstr "clone-proxy-user" +#: backend/flow/consts.py:140 +msgid "系统配置" +msgstr "系统配置" -#: backend/flow/consts.py:279 -msgid "clear-crontab" -msgstr "clear-crontab" +#: backend/flow/consts.py:141 +msgid "实例配置" +msgstr "实例配置" -#: backend/flow/consts.py:280 -msgid "semantic-check" -msgstr "semantic-check" +#: backend/flow/consts.py:142 +msgid "默认配置" +msgstr "默认配置" -#: backend/flow/consts.py:282 -msgid "backup-truncate-database" -msgstr "backup-truncate-database" +#: backend/flow/consts.py:143 +msgid "proxyconfig" +msgstr "proxyconfig" -#: backend/flow/consts.py:283 -msgid "restart" -msgstr "restart" +#: backend/flow/consts.py:144 +msgid "ES实例配置" +msgstr "ES实例配置" -#: backend/flow/consts.py:284 -msgid "clean-mysql" -msgstr "clean-mysql" +#: backend/flow/consts.py:145 +msgid "act配置" +msgstr "act配置" -#: backend/flow/consts.py:285 -msgid "backup-database-table" -msgstr "backup-database-table" +#: backend/flow/consts.py:146 +msgid "系统配置类型" +msgstr "系统配置类型" -#: backend/flow/consts.py:286 -msgid "set-backend-toward-slave" -msgstr "set-backend-toward-slave" +#: backend/flow/consts.py:147 +msgid "Kafka实例配置" +msgstr "Kafka实例配置" -#: backend/flow/consts.py:287 -msgid "pt-table-checksum" -msgstr "pt-table-checksum" +#: backend/flow/consts.py:148 +msgid "HDFS集群配置" +msgstr "HDFS集群配置" -#: backend/flow/consts.py:288 -msgid "执行分区" -msgstr "执行分区" +#: backend/flow/consts.py:149 +msgid "HDFS实例hdfs-site配置" +msgstr "HDFS实例hdfs-site配置" -#: backend/flow/consts.py:289 -msgid "ibs-recover" -msgstr "ibs-recover" +#: backend/flow/consts.py:150 +msgid "HDFS实例core-site配置" +msgstr "HDFS实例core-site配置" -#: backend/flow/consts.py:290 -msgid "数据修复指令" -msgstr "数据修复指令" +#: backend/flow/consts.py:151 +msgid "HDFS实例安装配置" +msgstr "HDFS实例安装配置" -#: backend/flow/consts.py:291 -msgid "flashback-binlog" -msgstr "flashback-binlog" +#: backend/flow/consts.py:155 +msgid "系统" +msgstr "系统" -#: backend/flow/consts.py:292 -msgid "full-backup" -msgstr "full-backup" +#: backend/flow/consts.py:156 +msgid "twemproxy config file" +msgstr "twemproxy config file" -#: backend/flow/consts.py:293 -msgid "install-checksum" -msgstr "install-checksum" +#: backend/flow/consts.py:157 +msgid "predixy config file" +msgstr "predixy config file" -#: backend/flow/consts.py:294 -msgid "mycnf-change" -msgstr "mycnf-change" +#: backend/flow/consts.py:158 +msgid "redis config file" +msgstr "redis config file" -#: backend/flow/consts.py:295 -msgid "安装rotate-binlog程序" -msgstr "安装rotate-binlog程序" +#: backend/flow/consts.py:159 +msgid "全备配置" +msgstr "全备配置" -#: backend/flow/consts.py:296 -msgid "安装dba-toolkit程序" -msgstr "安装dba-toolkit程序" +#: backend/flow/consts.py:160 +msgid "增备配置" +msgstr "增备配置" -#: backend/flow/consts.py:297 -msgid "deploy-mysql-crond" -msgstr "deploy-mysql-crond" +#: backend/flow/consts.py:161 +msgid "心跳配置" +msgstr "心跳配置" -#: backend/flow/consts.py:298 -msgid "mysql实例的周边配置清理" -msgstr "mysql实例的周边配置清理" +#: backend/flow/consts.py:162 +msgid "监控配置" +msgstr "监控配置" -#: backend/flow/consts.py:299 -msgid "初始化spider集群节点关系" -msgstr "初始化spider集群节点关系" +#: backend/flow/consts.py:163 +msgid "基本配置" +msgstr "基本配置" -#: backend/flow/consts.py:300 -#, fuzzy -#| msgid "spider中控节点名称" -msgid "添加spider临时节点" -msgstr "spider中控节点名称" +#: backend/flow/consts.py:164 +msgid "热key配置" +msgstr "热key配置" -#: backend/flow/consts.py:301 -#, fuzzy -#| msgid "restart" -msgid "restart-spider" -msgstr "restart" +#: backend/flow/consts.py:165 +msgid "大key配置" +msgstr "大key配置" -#: backend/flow/consts.py:302 -msgid "添加spider-slave集群的相关路由信息" -msgstr "添加spider-slave集群的相关路由信息" +#: backend/flow/consts.py:169 +msgid "MASTER" +msgstr "MASTER" -#: backend/flow/consts.py:307 -msgid "install" -msgstr "install" +#: backend/flow/consts.py:170 +msgid "SLAVE" +msgstr "SLAVE" -#: backend/flow/consts.py:308 -msgid "replica_batch" -msgstr "replica_batch" +#: backend/flow/consts.py:174 backend/flow/consts.py:251 +#: backend/flow/consts.py:723 +msgid "mysql" +msgstr "mysql" -#: backend/flow/consts.py:309 -msgid "replicaof" -msgstr "replicaof" +#: backend/flow/consts.py:175 +msgid "mysql-proxy" +msgstr "mysql-proxy" -#: backend/flow/consts.py:310 -msgid "clustermeet_slotsassign" -msgstr "clustermeet_slotsassign" +#: backend/flow/consts.py:179 +msgid "dbbackup" +msgstr "dbbackup" -#: backend/flow/consts.py:311 -msgid "keyspattern" -msgstr "keyspattern" +#: backend/flow/consts.py:180 +msgid "actuator" +msgstr "actuator" -#: backend/flow/consts.py:312 -msgid "keysdelete_regex" -msgstr "keysdelete_regex" +#: backend/flow/consts.py:181 +msgid "最新版本" +msgstr "最新版本" -#: backend/flow/consts.py:313 -msgid "keysdelete_files" -msgstr "keysdelete_files" +#: backend/flow/consts.py:184 +msgid "redis_tools" +msgstr "redis_tools" -#: backend/flow/consts.py:314 -msgid "backup" -msgstr "backup" +#: backend/flow/consts.py:185 backend/flow/consts.py:257 +msgid "es" +msgstr "es" -#: backend/flow/consts.py:315 -msgid "flush_data" -msgstr "flush_data" +#: backend/flow/consts.py:186 backend/flow/consts.py:258 +msgid "kafka" +msgstr "kafka" -#: backend/flow/consts.py:316 -msgid "shutdown" -msgstr "shutdown" +#: backend/flow/consts.py:187 backend/flow/consts.py:259 +msgid "hdfs" +msgstr "hdfs" -#: backend/flow/consts.py:317 -msgid "open" -msgstr "open" +#: backend/flow/consts.py:188 backend/flow/consts.py:260 +msgid "pulsar" +msgstr "pulsar" -#: backend/flow/consts.py:318 -msgid "close" -msgstr "close" +#: backend/flow/consts.py:190 +msgid "dbmon" +msgstr "dbmon" -#: backend/flow/consts.py:319 -msgid "operate" -msgstr "operate" +#: backend/flow/consts.py:191 +msgid "mysql-checksum" +msgstr "mysql-checksum" -#: backend/flow/consts.py:320 -msgid "capturer" -msgstr "capturer" +#: backend/flow/consts.py:192 +msgid "Binlog 滚动备份工具" +msgstr "Binlog 滚动备份工具" -#: backend/flow/consts.py:321 -msgid "kill_conn" -msgstr "kill_conn" +#: backend/flow/consts.py:193 +msgid "DBA 工具集" +msgstr "DBA 工具集" -#: backend/flow/consts.py:322 -msgid "param_sync" -msgstr "param_sync" +#: backend/flow/consts.py:194 +msgid "mysql-crond" +msgstr "mysql-crond" -#: backend/flow/consts.py:323 -#, fuzzy -#| msgid "semantic-check" -msgid "sync_check" -msgstr "semantic-check" +#: backend/flow/consts.py:195 +msgid "MySQL 监控" +msgstr "MySQL 监控" -#: backend/flow/consts.py:324 -#, fuzzy -#| msgid "hdfs_datanode" -msgid "dts_datacheck" -msgstr "hdfs_datanode" +#: backend/flow/consts.py:196 +msgid "nginx 服务" +msgstr "nginx 服务" -#: backend/flow/consts.py:325 -msgid "dts_datarepaire" -msgstr "dts_datarepaire" +#: backend/flow/consts.py:197 +msgid "dns-bind 服务" +msgstr "dns-bind 服务" -#: backend/flow/consts.py:329 backend/flow/consts.py:352 -#: backend/flow/consts.py:372 backend/flow/consts.py:391 -#: backend/flow/consts.py:541 -msgid "init" -msgstr "init" +#: backend/flow/consts.py:198 +msgid "dns-pull-crond服务" +msgstr "dns-pull-crond服务" -#: backend/flow/consts.py:330 backend/flow/consts.py:353 -#: backend/flow/consts.py:373 backend/flow/consts.py:392 -#: backend/flow/consts.py:542 -msgid "decompress_pkg" -msgstr "decompress_pkg" +#: backend/flow/consts.py:199 +msgid "cloud-dbha服务" +msgstr "cloud-dbha服务" -#: backend/flow/consts.py:331 backend/flow/consts.py:354 -#: backend/flow/consts.py:374 backend/flow/consts.py:393 -msgid "install_supervisor" -msgstr "install_supervisor" +#: backend/flow/consts.py:200 +msgid "cloud-drs服务" +msgstr "cloud-drs服务" -#: backend/flow/consts.py:332 -msgid "install_master" -msgstr "install_master" +#: backend/flow/consts.py:201 +msgid "cloud-drs-tmysqlparse服务" +msgstr "cloud-drs-tmysqlparse服务" -#: backend/flow/consts.py:333 -msgid "install_hot" -msgstr "install_hot" +#: backend/flow/consts.py:202 +msgid "spider节点名称" +msgstr "spider节点名称" -#: backend/flow/consts.py:334 -msgid "install_cold" -msgstr "install_cold" +#: backend/flow/consts.py:203 +msgid "spider中控节点名称" +msgstr "spider中控节点名称" -#: backend/flow/consts.py:335 -msgid "install_client" -msgstr "install_client" +#: backend/flow/consts.py:207 +msgid "nginx服务" +msgstr "nginx服务" -#: backend/flow/consts.py:336 -msgid "init_grant" -msgstr "init_grant" +#: backend/flow/consts.py:208 +msgid "dns服务" +msgstr "dns服务" -#: backend/flow/consts.py:337 -msgid "install_exporter" -msgstr "install_exporter" +#: backend/flow/consts.py:209 +msgid "drs服务" +msgstr "drs服务" -#: backend/flow/consts.py:338 -msgid "install_kibana" -msgstr "install_kibana" +#: backend/flow/consts.py:210 +msgid "dbha服务" +msgstr "dbha服务" -#: backend/flow/consts.py:339 backend/flow/consts.py:376 -msgid "install_telegraf" -msgstr "install_telegraf" +#: backend/flow/consts.py:214 +msgid "pull-crond.conf" +msgstr "pull-crond.conf" -#: backend/flow/consts.py:340 backend/flow/consts.py:359 -#: backend/flow/consts.py:378 backend/flow/consts.py:400 -msgid "start_process" -msgstr "start_process" +#: backend/flow/consts.py:215 +msgid "ha-gm.conf" +msgstr "ha-gm.conf" -#: backend/flow/consts.py:341 backend/flow/consts.py:360 -#: backend/flow/consts.py:379 backend/flow/consts.py:401 -msgid "stop_process" -msgstr "stop_process" +#: backend/flow/consts.py:216 +msgid "ha-agent.conf" +msgstr "ha-agent.conf" -#: backend/flow/consts.py:342 backend/flow/consts.py:361 -#: backend/flow/consts.py:380 backend/flow/consts.py:402 -msgid "restart_process" -msgstr "restart_process" +#: backend/flow/consts.py:217 +msgid "drs.env" +msgstr "drs.env" -#: backend/flow/consts.py:343 backend/flow/consts.py:362 -#: backend/flow/consts.py:381 backend/flow/consts.py:403 -msgid "clean_data" -msgstr "clean_data" +#: backend/flow/consts.py:221 +msgid "GM" +msgstr "GM" -#: backend/flow/consts.py:344 -msgid "exclude_node" -msgstr "exclude_node" +#: backend/flow/consts.py:222 +msgid "AGENT" +msgstr "AGENT" -#: backend/flow/consts.py:345 -msgid "check_shards" -msgstr "check_shards" +#: backend/flow/consts.py:223 +msgid "mysql-monitor" +msgstr "mysql-monitor" -#: backend/flow/consts.py:346 -msgid "check_connections" -msgstr "check_connections" +#: backend/flow/consts.py:233 +msgid "nginx服务模块" +msgstr "nginx服务模块" -#: backend/flow/consts.py:347 -msgid "check_nodes" -msgstr "check_nodes" +#: backend/flow/consts.py:234 +msgid "dns服务模块" +msgstr "dns服务模块" -#: backend/flow/consts.py:348 -msgid "replace_master" -msgstr "replace_master" +#: backend/flow/consts.py:235 +msgid "drs服务模块" +msgstr "drs服务模块" -#: backend/flow/consts.py:355 backend/flow/consts.py:394 -msgid "install_zookeeper" -msgstr "install_zookeeper" +#: backend/flow/consts.py:236 +msgid "dbha服务模块" +msgstr "dbha服务模块" -#: backend/flow/consts.py:356 -msgid "init_kafkaUser" -msgstr "init_kafkaUser" +#: backend/flow/consts.py:241 +msgid "蓝盾制品库" +msgstr "蓝盾制品库" -#: backend/flow/consts.py:357 backend/flow/consts.py:397 -msgid "install_broker" -msgstr "install_broker" +#: backend/flow/consts.py:246 +msgid "V1" +msgstr "V1" -#: backend/flow/consts.py:358 -msgid "install_manager" -msgstr "install_manager" +#: backend/flow/consts.py:254 +msgid "tendis" +msgstr "tendis" -#: backend/flow/consts.py:363 -msgid "reduce_broker" -msgstr "reduce_broker" +#: backend/flow/consts.py:262 +msgid "bkdbmon" +msgstr "bkdbmon" -#: backend/flow/consts.py:364 -msgid "check_reassign" -msgstr "check_reassign" +#: backend/flow/consts.py:263 +msgid "download" +msgstr "download" -#: backend/flow/consts.py:365 -msgid "reconfig_add" -msgstr "reconfig_add" +#: backend/flow/consts.py:265 +msgid "spiderctl" +msgstr "spiderctl" -#: backend/flow/consts.py:366 -msgid "restart_broker" -msgstr "restart_broker" - -#: backend/flow/consts.py:367 -msgid "reconfig_remove" -msgstr "reconfig_remove" +#: backend/flow/consts.py:269 backend/flow/consts.py:313 +msgid "sysinit" +msgstr "sysinit" -#: backend/flow/consts.py:368 -msgid "replace_broker" -msgstr "replace_broker" +#: backend/flow/consts.py:270 +msgid "deploy" +msgstr "deploy" -#: backend/flow/consts.py:375 -msgid "install_influxdb" -msgstr "install_influxdb" +#: backend/flow/consts.py:271 +msgid "find-local-backup" +msgstr "find-local-backup" -#: backend/flow/consts.py:377 -msgid "init_user" -msgstr "init_user" +#: backend/flow/consts.py:272 +msgid "restore-dr" +msgstr "restore-dr" -#: backend/flow/consts.py:385 -#, fuzzy -#| msgid "check_connections" -msgid "check_broker_config" -msgstr "check_connections" +#: backend/flow/consts.py:273 +msgid "recover-binlog" +msgstr "recover-binlog" -#: backend/flow/consts.py:386 -msgid "check_namespace_config" -msgstr "check_namespace_config" +#: backend/flow/consts.py:274 +msgid "grant-repl" +msgstr "grant-repl" -#: backend/flow/consts.py:387 -msgid "check_under_replicated" -msgstr "check_under_replicated" +#: backend/flow/consts.py:275 +msgid "change-master" +msgstr "change-master" -#: backend/flow/consts.py:388 -msgid "check_ledger_metadata" -msgstr "check_ledger_metadata" +#: backend/flow/consts.py:276 +msgid "set-backend" +msgstr "set-backend" -#: backend/flow/consts.py:389 -msgid "set_bookie_readonly" -msgstr "set_bookie_readonly" +#: backend/flow/consts.py:277 +msgid "uninstall" +msgstr "uninstall" -#: backend/flow/consts.py:390 -msgid "decommission_bookie" -msgstr "decommission_bookie" +#: backend/flow/consts.py:278 +msgid "deploy-dbbackup" +msgstr "deploy-dbbackup" -#: backend/flow/consts.py:395 -msgid "init_cluster" -msgstr "init_cluster" +#: backend/flow/consts.py:279 +msgid "install-monitor" +msgstr "install-monitor" -#: backend/flow/consts.py:396 -msgid "install_bookkeeper" -msgstr "install_bookkeeper" +#: backend/flow/consts.py:280 +msgid "deploy-rotate" +msgstr "deploy-rotate" -#: backend/flow/consts.py:398 -#, fuzzy -#| msgid "install_manager" -msgid "install_pulsar_manager" -msgstr "install_manager" +#: backend/flow/consts.py:281 backend/flow/consts.py:287 +msgid "semantic-dumpschema" +msgstr "semantic-dumpschema" -#: backend/flow/consts.py:399 -#, fuzzy -#| msgid "pulsar_manager" -msgid "init_pulsar_manager" -msgstr "pulsar_manager" +#: backend/flow/consts.py:282 +msgid "import-sqlfile" +msgstr "import-sqlfile" -#: backend/flow/consts.py:404 -msgid "add_hosts" -msgstr "add_hosts" +#: backend/flow/consts.py:283 +msgid "clone-client-grant" +msgstr "clone-client-grant" -#: backend/flow/consts.py:405 -#, fuzzy -#| msgid "dfs-host" -msgid "modify_hosts" -msgstr "dfs-host" +#: backend/flow/consts.py:284 +msgid "clone-proxy-user" +msgstr "clone-proxy-user" -#: backend/flow/consts.py:409 -msgid "NOT_RUNNING" -msgstr "NOT_RUNNING" +#: backend/flow/consts.py:285 +msgid "clear-crontab" +msgstr "clear-crontab" -#: backend/flow/consts.py:410 backend/flow/consts.py:468 -msgid "RUNNING" -msgstr "RUNNING" +#: backend/flow/consts.py:286 +msgid "semantic-check" +msgstr "semantic-check" -#: backend/flow/consts.py:411 backend/flow/consts.py:469 -msgid "SUCCESS" -msgstr "SUCCESS" +#: backend/flow/consts.py:288 +msgid "backup-truncate-database" +msgstr "backup-truncate-database" -#: backend/flow/consts.py:412 backend/flow/consts.py:470 -msgid "FAILED" -msgstr "FAILED" +#: backend/flow/consts.py:289 +msgid "restart" +msgstr "restart" -#: backend/flow/consts.py:413 -msgid "SKIPPED" -msgstr "SKIPPED" +#: backend/flow/consts.py:290 +msgid "clean-mysql" +msgstr "clean-mysql" -#: backend/flow/consts.py:414 -msgid "IGNORED" -msgstr "IGNORED" +#: backend/flow/consts.py:291 +msgid "backup-database-table" +msgstr "backup-database-table" -#: backend/flow/consts.py:415 -msgid "WAITING" -msgstr "WAITING" +#: backend/flow/consts.py:292 +msgid "set-backend-toward-slave" +msgstr "set-backend-toward-slave" -#: backend/flow/consts.py:416 -msgid "NORMAL" -msgstr "NORMAL" +#: backend/flow/consts.py:293 +msgid "pt-table-checksum" +msgstr "pt-table-checksum" -#: backend/flow/consts.py:418 -msgid "步骤强制终止中" -msgstr "步骤强制终止中" +#: backend/flow/consts.py:294 +msgid "执行分区" +msgstr "执行分区" -#: backend/flow/consts.py:419 -msgid "步骤强制终止成功" -msgstr "步骤强制终止成功" +#: backend/flow/consts.py:295 +msgid "ibs-recover" +msgstr "ibs-recover" -#: backend/flow/consts.py:423 -msgid "准备中" -msgstr "准备中" +#: backend/flow/consts.py:296 +msgid "数据修复指令" +msgstr "数据修复指令" -#: backend/flow/consts.py:424 -msgid "运行中" -msgstr "运行中" +#: backend/flow/consts.py:297 +msgid "flashback-binlog" +msgstr "flashback-binlog" -#: backend/flow/consts.py:425 -msgid "完成" -msgstr "完成" +#: backend/flow/consts.py:298 +msgid "full-backup" +msgstr "full-backup" -#: backend/flow/consts.py:426 -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:94 -#: backend/ticket/constants.py:66 backend/ticket/constants.py:76 -msgid "失败" -msgstr "失败" +#: backend/flow/consts.py:299 +msgid "install-checksum" +msgstr "install-checksum" -#: backend/flow/consts.py:431 -msgid "available" -msgstr "available" +#: backend/flow/consts.py:300 +msgid "mycnf-change" +msgstr "mycnf-change" -#: backend/flow/consts.py:433 -msgid "locked" -msgstr "locked" +#: backend/flow/consts.py:301 +#, fuzzy +#| msgid "安装rotate-binlog程序" +msgid "安装mysql-rotatebinlog程序" +msgstr "安装rotate-binlog程序" -#: backend/flow/consts.py:437 -msgid "cluster no" -msgstr "cluster no" +#: backend/flow/consts.py:302 +msgid "安装dba-toolkit程序" +msgstr "安装dba-toolkit程序" -#: backend/flow/consts.py:438 -msgid "cluster yes" -msgstr "cluster yes" +#: backend/flow/consts.py:303 +msgid "deploy-mysql-crond" +msgstr "deploy-mysql-crond" -#: backend/flow/consts.py:442 backend/flow/consts.py:450 -msgid "create" -msgstr "create" +#: backend/flow/consts.py:304 +msgid "mysql实例的周边配置清理" +msgstr "mysql实例的周边配置清理" -#: backend/flow/consts.py:443 -msgid "cluster_delete" -msgstr "cluster_delete" +#: backend/flow/consts.py:305 +msgid "初始化spider集群节点关系" +msgstr "初始化spider集群节点关系" -#: backend/flow/consts.py:444 -msgid "recycle_record" -msgstr "recycle_record" +#: backend/flow/consts.py:306 +#, fuzzy +#| msgid "spider中控节点名称" +msgid "添加spider临时节点" +msgstr "spider中控节点名称" -#: backend/flow/consts.py:445 backend/flow/consts.py:451 -msgid "update" -msgstr "update" +#: backend/flow/consts.py:307 +#, fuzzy +#| msgid "restart" +msgid "restart-spider" +msgstr "restart" -#: backend/flow/consts.py:446 -msgid "select" -msgstr "select" +#: backend/flow/consts.py:308 +msgid "添加spider-slave集群的相关路由信息" +msgstr "添加spider-slave集群的相关路由信息" -#: backend/flow/consts.py:452 -msgid "delete" -msgstr "delete" +#: backend/flow/consts.py:309 +#, fuzzy +#| msgid "sql备份信息" +msgid "mysql备份请求" +msgstr "sql备份信息" -#: backend/flow/consts.py:456 -msgid "kibana" -msgstr "kibana" +#: backend/flow/consts.py:314 +msgid "install" +msgstr "install" -#: backend/flow/consts.py:457 -msgid "kafka_manager" -msgstr "kafka_manager" +#: backend/flow/consts.py:315 +msgid "replica_batch" +msgstr "replica_batch" -#: backend/flow/consts.py:458 -msgid "pulsar_manager" -msgstr "pulsar_manager" +#: backend/flow/consts.py:316 +msgid "replicaof" +msgstr "replicaof" -#: backend/flow/consts.py:459 -msgid "ha_proxy" -msgstr "ha_proxy" +#: backend/flow/consts.py:317 +msgid "clustermeet_slotsassign" +msgstr "clustermeet_slotsassign" -#: backend/flow/consts.py:463 -msgid "KIBANA_PORT" -msgstr "KIBANA_PORT" +#: backend/flow/consts.py:318 +msgid "keyspattern" +msgstr "keyspattern" -#: backend/flow/consts.py:464 -msgid "KAFKA_MANAGER_PORT" -msgstr "KAFKA_MANAGER_PORT" +#: backend/flow/consts.py:319 +msgid "keysdelete_regex" +msgstr "keysdelete_regex" -#: backend/flow/consts.py:474 -msgid "proxy默认实例个数" -msgstr "proxy默认实例个数" +#: backend/flow/consts.py:320 +msgid "keysdelete_files" +msgstr "keysdelete_files" -#: backend/flow/consts.py:475 -msgid "redis角色数" -msgstr "redis角色数" +#: backend/flow/consts.py:321 +msgid "backup" +msgstr "backup" -#: backend/flow/consts.py:479 -msgid "DB安装目录" -msgstr "DB安装目录" +#: backend/flow/consts.py:322 +msgid "flush_data" +msgstr "flush_data" -#: backend/flow/consts.py:483 -msgid "gcs 安装路径" -msgstr "gcs 安装路径" +#: backend/flow/consts.py:323 +msgid "shutdown" +msgstr "shutdown" -#: backend/flow/consts.py:484 -msgid "key生命周期路径" -msgstr "key生命周期路径" +#: backend/flow/consts.py:324 +msgid "open" +msgstr "open" -#: backend/flow/consts.py:488 -msgid "truncate_table" -msgstr "truncate_table" +#: backend/flow/consts.py:325 +msgid "close" +msgstr "close" -#: backend/flow/consts.py:489 -msgid "drop_database" -msgstr "drop_database" +#: backend/flow/consts.py:326 +msgid "operate" +msgstr "operate" -#: backend/flow/consts.py:490 -msgid "drop_table" -msgstr "drop_table" +#: backend/flow/consts.py:327 +msgid "capturer" +msgstr "capturer" -#: backend/flow/consts.py:513 -msgid "TendataModuleDefault" -msgstr "TendataModuleDefault" +#: backend/flow/consts.py:328 +msgid "kill_conn" +msgstr "kill_conn" -#: backend/flow/consts.py:517 backend/ticket/builders/common/constants.py:38 -msgid "hot" -msgstr "hot" +#: backend/flow/consts.py:329 +msgid "param_sync" +msgstr "param_sync" -#: backend/flow/consts.py:518 backend/ticket/builders/common/constants.py:39 -msgid "cold" -msgstr "cold" +#: backend/flow/consts.py:330 +#, fuzzy +#| msgid "semantic-check" +msgid "sync_check" +msgstr "semantic-check" -#: backend/flow/consts.py:519 backend/ticket/builders/common/constants.py:40 -msgid "client" -msgstr "client" +#: backend/flow/consts.py:331 +#, fuzzy +#| msgid "hdfs_datanode" +msgid "dts_datacheck" +msgstr "hdfs_datanode" -#: backend/flow/consts.py:524 -msgid "redis key删除正则方式" -msgstr "redis key删除正则方式" +#: backend/flow/consts.py:332 +msgid "dts_datarepaire" +msgstr "dts_datarepaire" -#: backend/flow/consts.py:525 -msgid "redis key删除文件方式" -msgstr "redis key删除文件方式" +#: backend/flow/consts.py:336 backend/flow/consts.py:359 +#: backend/flow/consts.py:379 backend/flow/consts.py:398 +#: backend/flow/consts.py:548 +msgid "init" +msgstr "init" -#: backend/flow/consts.py:529 -msgid "get" -msgstr "get" +#: backend/flow/consts.py:337 backend/flow/consts.py:360 +#: backend/flow/consts.py:380 backend/flow/consts.py:399 +#: backend/flow/consts.py:549 +msgid "decompress_pkg" +msgstr "decompress_pkg" -#: backend/flow/consts.py:530 -msgid "release" -msgstr "release" +#: backend/flow/consts.py:338 backend/flow/consts.py:361 +#: backend/flow/consts.py:381 backend/flow/consts.py:400 +msgid "install_supervisor" +msgstr "install_supervisor" -#: backend/flow/consts.py:534 -msgid "覆盖写入上下文变量" -msgstr "覆盖写入上下文变量" +#: backend/flow/consts.py:339 +msgid "install_master" +msgstr "install_master" -#: backend/flow/consts.py:535 -msgid "追加写入上下文变量" -msgstr "追加写入上下文变量" +#: backend/flow/consts.py:340 +msgid "install_hot" +msgstr "install_hot" -#: backend/flow/consts.py:539 -msgid "install-supervisor" -msgstr "install-supervisor" +#: backend/flow/consts.py:341 +msgid "install_cold" +msgstr "install_cold" -#: backend/flow/consts.py:540 -msgid "render-config" -msgstr "render-config" +#: backend/flow/consts.py:342 +msgid "install_client" +msgstr "install_client" -#: backend/flow/consts.py:543 -msgid "install-zookeeper" -msgstr "install-zookeeper" +#: backend/flow/consts.py:343 +msgid "init_grant" +msgstr "init_grant" -#: backend/flow/consts.py:544 -msgid "install-journalnode" -msgstr "install-journalnode" +#: backend/flow/consts.py:344 +msgid "install_exporter" +msgstr "install_exporter" -#: backend/flow/consts.py:545 -msgid "install-nn1" -msgstr "install-nn1" +#: backend/flow/consts.py:345 +msgid "install_kibana" +msgstr "install_kibana" -#: backend/flow/consts.py:546 -msgid "install-nn2" -msgstr "install-nn2" +#: backend/flow/consts.py:346 backend/flow/consts.py:383 +msgid "install_telegraf" +msgstr "install_telegraf" -#: backend/flow/consts.py:547 -msgid "install-dn" -msgstr "install-dn" +#: backend/flow/consts.py:347 backend/flow/consts.py:366 +#: backend/flow/consts.py:385 backend/flow/consts.py:407 +msgid "start_process" +msgstr "start_process" -#: backend/flow/consts.py:548 -msgid "install-zkfc" -msgstr "install-zkfc" +#: backend/flow/consts.py:348 backend/flow/consts.py:367 +#: backend/flow/consts.py:386 backend/flow/consts.py:408 +msgid "stop_process" +msgstr "stop_process" -#: backend/flow/consts.py:549 -msgid "install-telegraf" -msgstr "install-telegraf" +#: backend/flow/consts.py:349 backend/flow/consts.py:368 +#: backend/flow/consts.py:387 backend/flow/consts.py:409 +msgid "restart_process" +msgstr "restart_process" -#: backend/flow/consts.py:550 -msgid "install-haproxy" -msgstr "install-haproxy" +#: backend/flow/consts.py:350 backend/flow/consts.py:369 +#: backend/flow/consts.py:388 backend/flow/consts.py:410 +msgid "clean_data" +msgstr "clean_data" -#: backend/flow/consts.py:551 -msgid "update-hosts" -msgstr "update-hosts" +#: backend/flow/consts.py:351 +msgid "exclude_node" +msgstr "exclude_node" -#: backend/flow/consts.py:552 -msgid "stop-process" -msgstr "stop-process" +#: backend/flow/consts.py:352 +msgid "check_shards" +msgstr "check_shards" -#: backend/flow/consts.py:553 -msgid "start-component" -msgstr "start-component" +#: backend/flow/consts.py:353 +msgid "check_connections" +msgstr "check_connections" -#: backend/flow/consts.py:554 -msgid "clean-data" -msgstr "clean-data" +#: backend/flow/consts.py:354 +msgid "check_nodes" +msgstr "check_nodes" -#: backend/flow/consts.py:555 -msgid "dfs-host" -msgstr "dfs-host" +#: backend/flow/consts.py:355 +msgid "replace_master" +msgstr "replace_master" -#: backend/flow/consts.py:566 backend/ticket/builders/common/constants.py:45 -msgid "namenode" -msgstr "namenode" +#: backend/flow/consts.py:362 backend/flow/consts.py:401 +msgid "install_zookeeper" +msgstr "install_zookeeper" -#: backend/flow/consts.py:567 backend/ticket/builders/common/constants.py:44 -msgid "datanode" -msgstr "datanode" +#: backend/flow/consts.py:363 +msgid "init_kafkaUser" +msgstr "init_kafkaUser" -#: backend/flow/consts.py:568 -msgid "journalnode" -msgstr "journalnode" +#: backend/flow/consts.py:364 backend/flow/consts.py:404 +msgid "install_broker" +msgstr "install_broker" -#: backend/flow/consts.py:570 -msgid "zkfc" -msgstr "zkfc" +#: backend/flow/consts.py:365 +msgid "install_manager" +msgstr "install_manager" -#: backend/flow/consts.py:574 backend/ticket/builders/common/constants.py:54 -msgid "bookkeeper" -msgstr "bookkeeper" +#: backend/flow/consts.py:370 +msgid "reduce_broker" +msgstr "reduce_broker" -#: backend/flow/consts.py:581 -msgid "常规备份" -msgstr "常规备份" +#: backend/flow/consts.py:371 +msgid "check_reassign" +msgstr "check_reassign" -#: backend/flow/consts.py:582 -msgid "长期备份" -msgstr "长期备份" +#: backend/flow/consts.py:372 +msgid "reconfig_add" +msgstr "reconfig_add" -#: backend/flow/consts.py:586 -msgid "KAFKA_REPLACE" -msgstr "KAFKA_REPLACE" +#: backend/flow/consts.py:373 +msgid "restart_broker" +msgstr "restart_broker" -#: backend/flow/consts.py:587 -msgid "KAFKA_SCALE_UP" -msgstr "KAFKA_SCALE_UP" +#: backend/flow/consts.py:374 +msgid "reconfig_remove" +msgstr "reconfig_remove" -#: backend/flow/consts.py:591 -#, fuzzy -#| msgid "KAFKA_REPLACE" -msgid "INFLUXDB_REPLACE" -msgstr "KAFKA_REPLACE" +#: backend/flow/consts.py:375 +msgid "replace_broker" +msgstr "replace_broker" -#: backend/flow/consts.py:595 -msgid "逻辑备份" -msgstr "逻辑备份" +#: backend/flow/consts.py:382 +msgid "install_influxdb" +msgstr "install_influxdb" -#: backend/flow/consts.py:599 -msgid "全备-保留25天" -msgstr "全备-保留25天" +#: backend/flow/consts.py:384 +msgid "init_user" +msgstr "init_user" -#: backend/flow/consts.py:600 -msgid "长久存储-保留三年" -msgstr "长久存储-保留三年" +#: backend/flow/consts.py:392 +#, fuzzy +#| msgid "check_connections" +msgid "check_broker_config" +msgstr "check_connections" -#: backend/flow/consts.py:608 -msgid "Mysql的进程名称" -msgstr "Mysql的进程名称" +#: backend/flow/consts.py:393 +msgid "check_namespace_config" +msgstr "check_namespace_config" -#: backend/flow/consts.py:609 -msgid "Mysql-proxy进程名称" -msgstr "Mysql-proxy进程名称" +#: backend/flow/consts.py:394 +msgid "check_under_replicated" +msgstr "check_under_replicated" -#: backend/flow/consts.py:610 -msgid "ES的进程名称" -msgstr "ES的进程名称" +#: backend/flow/consts.py:395 +msgid "check_ledger_metadata" +msgstr "check_ledger_metadata" -#: backend/flow/consts.py:611 -msgid "HDFS-NameNode的进程名称" -msgstr "HDFS-NameNode的进程名称" +#: backend/flow/consts.py:396 +msgid "set_bookie_readonly" +msgstr "set_bookie_readonly" -#: backend/flow/consts.py:612 -msgid "HDFS-DataNode的进程名称" -msgstr "HDFS-DataNode的进程名称" +#: backend/flow/consts.py:397 +msgid "decommission_bookie" +msgstr "decommission_bookie" -#: backend/flow/consts.py:613 -msgid "Pulsar的进程名称" -msgstr "Pulsar的进程名称" +#: backend/flow/consts.py:402 +msgid "init_cluster" +msgstr "init_cluster" -#: backend/flow/consts.py:621 -msgid "远程备份+时间" -msgstr "远程备份+时间" +#: backend/flow/consts.py:403 +msgid "install_bookkeeper" +msgstr "install_bookkeeper" -#: backend/flow/consts.py:622 -msgid "远程备份+备份ID" -msgstr "远程备份+备份ID" +#: backend/flow/consts.py:405 +#, fuzzy +#| msgid "install_manager" +msgid "install_pulsar_manager" +msgstr "install_manager" -#: backend/flow/consts.py:623 -msgid "本地备份+时间" -msgstr "本地备份+时间" +#: backend/flow/consts.py:406 +#, fuzzy +#| msgid "pulsar_manager" +msgid "init_pulsar_manager" +msgstr "pulsar_manager" -#: backend/flow/consts.py:624 -msgid "本地备份+备份ID" -msgstr "本地备份+备份ID" +#: backend/flow/consts.py:411 +msgid "add_hosts" +msgstr "add_hosts" -#: backend/flow/consts.py:632 -msgid "手动单据发起" -msgstr "手动单据发起" +#: backend/flow/consts.py:412 +#, fuzzy +#| msgid "dfs-host" +msgid "modify_hosts" +msgstr "dfs-host" -#: backend/flow/consts.py:633 -msgid "例行校验单据发起" -msgstr "例行校验单据发起" +#: backend/flow/consts.py:416 +msgid "NOT_RUNNING" +msgstr "NOT_RUNNING" -#: backend/flow/consts.py:639 -#, fuzzy -#| msgid "mms" -msgid "ms" -msgstr "mms" +#: backend/flow/consts.py:417 backend/flow/consts.py:475 +msgid "RUNNING" +msgstr "RUNNING" -#: backend/flow/consts.py:649 -msgid "redis slot分隔符" -msgstr "redis slot分隔符" +#: backend/flow/consts.py:418 backend/flow/consts.py:476 +msgid "SUCCESS" +msgstr "SUCCESS" -#: backend/flow/consts.py:650 -msgid "redis slot导入分隔符" -msgstr "redis slot导入分隔符" +#: backend/flow/consts.py:419 backend/flow/consts.py:477 +msgid "FAILED" +msgstr "FAILED" -#: backend/flow/consts.py:651 -msgid "redis slot迁移分隔符" -msgstr "redis slot迁移分隔符" +#: backend/flow/consts.py:420 +msgid "SKIPPED" +msgstr "SKIPPED" -#: backend/flow/consts.py:659 -#, fuzzy -#| msgid "redis_master" -msgid "redis min slot" -msgstr "redis_master" +#: backend/flow/consts.py:421 +msgid "IGNORED" +msgstr "IGNORED" -#: backend/flow/consts.py:660 -#, fuzzy -#| msgid "redis_master" -msgid "redis max slot" -msgstr "redis_master" +#: backend/flow/consts.py:422 +msgid "WAITING" +msgstr "WAITING" -#: backend/flow/consts.py:661 -#, fuzzy -#| msgid "redis_tools" -msgid "redis total slot" -msgstr "redis_tools" +#: backend/flow/consts.py:423 +msgid "NORMAL" +msgstr "NORMAL" -#: backend/flow/consts.py:669 -msgid "redis PFAIL state" -msgstr "redis PFAIL state" +#: backend/flow/consts.py:425 +msgid "步骤强制终止中" +msgstr "步骤强制终止中" -#: backend/flow/consts.py:670 -#, fuzzy -#| msgid "redis_master" -msgid "redis fail state" -msgstr "redis_master" +#: backend/flow/consts.py:426 +msgid "步骤强制终止成功" +msgstr "步骤强制终止成功" -#: backend/flow/consts.py:671 -msgid "redis handshake state" -msgstr "redis handshake state" +#: backend/flow/consts.py:430 +msgid "准备中" +msgstr "准备中" -#: backend/flow/consts.py:672 -#, fuzzy -#| msgid "redis_master" -msgid "redis noaddr state" -msgstr "redis_master" +#: backend/flow/consts.py:431 +msgid "运行中" +msgstr "运行中" -#: backend/flow/consts.py:673 -#, fuzzy -#| msgid "redis config file" -msgid "redis noflags state" -msgstr "redis config file" +#: backend/flow/consts.py:432 +msgid "完成" +msgstr "完成" -#: backend/flow/consts.py:681 -#, fuzzy -#| msgid "redis_master" -msgid "redis master role" -msgstr "redis_master" +#: backend/flow/consts.py:433 +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:94 +#: backend/ticket/constants.py:66 backend/ticket/constants.py:76 +msgid "失败" +msgstr "失败" -#: backend/flow/consts.py:682 -#, fuzzy -#| msgid "redis_slave" -msgid "redis slave role" -msgstr "redis_slave" +#: backend/flow/consts.py:438 +msgid "available" +msgstr "available" -#: backend/flow/consts.py:683 -#, fuzzy -#| msgid "redis config file" -msgid "redis unknown role" -msgstr "redis config file" +#: backend/flow/consts.py:440 +msgid "locked" +msgstr "locked" -#: backend/flow/consts.py:691 -msgid "redis master link status up" -msgstr "redis master link status up" +#: backend/flow/consts.py:444 +msgid "cluster no" +msgstr "cluster no" -#: backend/flow/consts.py:692 -msgid "redis master link status down" -msgstr "redis master link status down" +#: backend/flow/consts.py:445 +msgid "cluster yes" +msgstr "cluster yes" -#: backend/flow/consts.py:693 -msgid "redis ssd incrSync state" -msgstr "redis ssd incrSync state" +#: backend/flow/consts.py:449 backend/flow/consts.py:457 +msgid "create" +msgstr "create" -#: backend/flow/consts.py:694 -msgid "redis ssd REPL_FOLLOW state" -msgstr "redis ssd REPL_FOLLOW state" +#: backend/flow/consts.py:450 +msgid "cluster_delete" +msgstr "cluster_delete" -#: backend/flow/consts.py:695 -msgid "redis connected status" -msgstr "redis connected status" +#: backend/flow/consts.py:451 +msgid "recycle_record" +msgstr "recycle_record" -#: backend/flow/consts.py:696 -msgid "redis disconnected status" -msgstr "redis disconnected status" +#: backend/flow/consts.py:452 backend/flow/consts.py:458 +msgid "update" +msgstr "update" -#: backend/flow/consts.py:704 -msgid "" -"redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" -msgstr "redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" +#: backend/flow/consts.py:453 +msgid "select" +msgstr "select" -#: backend/flow/consts.py:705 -msgid "" -"redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" -msgstr "redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" +#: backend/flow/consts.py:459 +msgid "delete" +msgstr "delete" -#: backend/flow/engine/bamboo/engine.py:245 -msgid "获取流程失败" -msgstr "获取流程失败" +#: backend/flow/consts.py:463 +msgid "kibana" +msgstr "kibana" -#: backend/flow/engine/bamboo/engine.py:248 -msgid "获取流程节点失败" -msgstr "获取流程节点失败" +#: backend/flow/consts.py:464 +msgid "kafka_manager" +msgstr "kafka_manager" -#: backend/flow/engine/bamboo/engine.py:251 -msgid "获取节点运行版本失败" -msgstr "获取节点运行版本失败" +#: backend/flow/consts.py:465 +msgid "pulsar_manager" +msgstr "pulsar_manager" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:127 -msgid "下发{}可执行文件包" -msgstr "下发{}可执行文件包" +#: backend/flow/consts.py:466 +msgid "ha_proxy" +msgstr "ha_proxy" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:136 -msgid "部署{}服务进程" -msgstr "部署{}服务进程" +#: backend/flow/consts.py:470 +msgid "KIBANA_PORT" +msgstr "KIBANA_PORT" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:185 -msgid "下发{}配置文件" -msgstr "下发{}配置文件" +#: backend/flow/consts.py:471 +msgid "KAFKA_MANAGER_PORT" +msgstr "KAFKA_MANAGER_PORT" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:311 -msgid "存量集群的权限更新" -msgstr "存量集群的权限更新" +#: backend/flow/consts.py:481 +msgid "proxy默认实例个数" +msgstr "proxy默认实例个数" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:339 -#, fuzzy -#| msgid "更新服务" -msgid "更新服务元信息" -msgstr "更新服务" +#: backend/flow/consts.py:482 +msgid "redis角色数" +msgstr "redis角色数" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:364 -msgid "裁撤{}的服务" -msgstr "裁撤{}的服务" +#: backend/flow/consts.py:486 +msgid "DB安装目录" +msgstr "DB安装目录" -#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:387 -#, fuzzy -#| msgid "nginx服务" -msgid "重启nginx服务" -msgstr "nginx服务" +#: backend/flow/consts.py:490 +msgid "gcs 安装路径" +msgstr "gcs 安装路径" -#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:40 -msgid "主机{}部署gm服务" -msgstr "主机{}部署gm服务" +#: backend/flow/consts.py:491 +msgid "key生命周期路径" +msgstr "key生命周期路径" -#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:59 -msgid "主机{}部署agent服务" -msgstr "主机{}部署agent服务" +#: backend/flow/consts.py:495 +msgid "truncate_table" +msgstr "truncate_table" -#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:76 -msgid "部署dbha-gm服务" -msgstr "部署dbha-gm服务" +#: backend/flow/consts.py:496 +msgid "drop_database" +msgstr "drop_database" -#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:82 -msgid "部署dbha-agent服务" -msgstr "部署dbha-agent服务" +#: backend/flow/consts.py:497 +msgid "drop_table" +msgstr "drop_table" -#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:46 -#: backend/flow/engine/bamboo/scene/cloud/nginx_service_flow.py:75 -msgid "主机{}部署dns服务" -msgstr "主机{}部署dns服务" +#: backend/flow/consts.py:520 +msgid "TendataModuleDefault" +msgstr "TendataModuleDefault" -#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:50 -msgid "部署dns服务" -msgstr "部署dns服务" +#: backend/flow/consts.py:524 backend/ticket/builders/common/constants.py:38 +msgid "hot" +msgstr "hot" -#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:65 -msgid "对存量机器的nameserver刷新" -msgstr "对存量机器的nameserver刷新" +#: backend/flow/consts.py:525 backend/ticket/builders/common/constants.py:39 +msgid "cold" +msgstr "cold" -#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:154 -#, fuzzy -#| msgid "部署dns服务" -msgid "部署新dns服务流程" -msgstr "部署dns服务" +#: backend/flow/consts.py:526 backend/ticket/builders/common/constants.py:40 +msgid "client" +msgstr "client" -#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:173 -msgid "裁撤旧dns服务流程" -msgstr "裁撤旧dns服务流程" +#: backend/flow/consts.py:531 +msgid "redis key删除正则方式" +msgstr "redis key删除正则方式" + +#: backend/flow/consts.py:532 +msgid "redis key删除文件方式" +msgstr "redis key删除文件方式" + +#: backend/flow/consts.py:536 +msgid "get" +msgstr "get" + +#: backend/flow/consts.py:537 +msgid "release" +msgstr "release" + +#: backend/flow/consts.py:541 +msgid "覆盖写入上下文变量" +msgstr "覆盖写入上下文变量" + +#: backend/flow/consts.py:542 +msgid "追加写入上下文变量" +msgstr "追加写入上下文变量" + +#: backend/flow/consts.py:546 +msgid "install-supervisor" +msgstr "install-supervisor" + +#: backend/flow/consts.py:547 +msgid "render-config" +msgstr "render-config" + +#: backend/flow/consts.py:550 +msgid "install-zookeeper" +msgstr "install-zookeeper" + +#: backend/flow/consts.py:551 +msgid "install-journalnode" +msgstr "install-journalnode" + +#: backend/flow/consts.py:552 +msgid "install-nn1" +msgstr "install-nn1" + +#: backend/flow/consts.py:553 +msgid "install-nn2" +msgstr "install-nn2" + +#: backend/flow/consts.py:554 +msgid "install-dn" +msgstr "install-dn" + +#: backend/flow/consts.py:555 +msgid "install-zkfc" +msgstr "install-zkfc" + +#: backend/flow/consts.py:556 +msgid "install-telegraf" +msgstr "install-telegraf" + +#: backend/flow/consts.py:557 +msgid "install-haproxy" +msgstr "install-haproxy" + +#: backend/flow/consts.py:558 +msgid "update-hosts" +msgstr "update-hosts" + +#: backend/flow/consts.py:559 +msgid "stop-process" +msgstr "stop-process" + +#: backend/flow/consts.py:560 +msgid "start-component" +msgstr "start-component" + +#: backend/flow/consts.py:561 +msgid "clean-data" +msgstr "clean-data" + +#: backend/flow/consts.py:562 +msgid "dfs-host" +msgstr "dfs-host" + +#: backend/flow/consts.py:573 backend/ticket/builders/common/constants.py:45 +msgid "namenode" +msgstr "namenode" + +#: backend/flow/consts.py:574 backend/ticket/builders/common/constants.py:44 +msgid "datanode" +msgstr "datanode" + +#: backend/flow/consts.py:575 +msgid "journalnode" +msgstr "journalnode" + +#: backend/flow/consts.py:577 +msgid "zkfc" +msgstr "zkfc" + +#: backend/flow/consts.py:581 backend/ticket/builders/common/constants.py:54 +msgid "bookkeeper" +msgstr "bookkeeper" + +#: backend/flow/consts.py:588 +msgid "常规备份" +msgstr "常规备份" + +#: backend/flow/consts.py:589 +msgid "长期备份" +msgstr "长期备份" + +#: backend/flow/consts.py:593 +msgid "KAFKA_REPLACE" +msgstr "KAFKA_REPLACE" + +#: backend/flow/consts.py:594 +msgid "KAFKA_SCALE_UP" +msgstr "KAFKA_SCALE_UP" + +#: backend/flow/consts.py:598 +#, fuzzy +#| msgid "KAFKA_REPLACE" +msgid "INFLUXDB_REPLACE" +msgstr "KAFKA_REPLACE" + +#: backend/flow/consts.py:602 +msgid "逻辑备份" +msgstr "逻辑备份" + +#: backend/flow/consts.py:603 +msgid "物理备份" +msgstr "" + +#: backend/flow/consts.py:607 +msgid "全备-保留25天" +msgstr "全备-保留25天" + +#: backend/flow/consts.py:608 +msgid "长久存储-保留三年" +msgstr "长久存储-保留三年" + +#: backend/flow/consts.py:616 +msgid "Mysql的进程名称" +msgstr "Mysql的进程名称" + +#: backend/flow/consts.py:617 +msgid "Mysql-proxy进程名称" +msgstr "Mysql-proxy进程名称" + +#: backend/flow/consts.py:618 +msgid "ES的进程名称" +msgstr "ES的进程名称" + +#: backend/flow/consts.py:619 +msgid "HDFS-NameNode的进程名称" +msgstr "HDFS-NameNode的进程名称" + +#: backend/flow/consts.py:620 +msgid "HDFS-DataNode的进程名称" +msgstr "HDFS-DataNode的进程名称" + +#: backend/flow/consts.py:621 +msgid "Pulsar的进程名称" +msgstr "Pulsar的进程名称" + +#: backend/flow/consts.py:629 +msgid "远程备份+时间" +msgstr "远程备份+时间" + +#: backend/flow/consts.py:630 +msgid "远程备份+备份ID" +msgstr "远程备份+备份ID" + +#: backend/flow/consts.py:631 +msgid "本地备份+时间" +msgstr "本地备份+时间" + +#: backend/flow/consts.py:632 +msgid "本地备份+备份ID" +msgstr "本地备份+备份ID" + +#: backend/flow/consts.py:640 +msgid "手动单据发起" +msgstr "手动单据发起" + +#: backend/flow/consts.py:641 +msgid "例行校验单据发起" +msgstr "例行校验单据发起" + +#: backend/flow/consts.py:647 +#, fuzzy +#| msgid "mms" +msgid "ms" +msgstr "mms" + +#: backend/flow/consts.py:657 +msgid "redis slot分隔符" +msgstr "redis slot分隔符" + +#: backend/flow/consts.py:658 +msgid "redis slot导入分隔符" +msgstr "redis slot导入分隔符" + +#: backend/flow/consts.py:659 +msgid "redis slot迁移分隔符" +msgstr "redis slot迁移分隔符" + +#: backend/flow/consts.py:667 +#, fuzzy +#| msgid "redis_master" +msgid "redis min slot" +msgstr "redis_master" + +#: backend/flow/consts.py:668 +#, fuzzy +#| msgid "redis_master" +msgid "redis max slot" +msgstr "redis_master" + +#: backend/flow/consts.py:669 +#, fuzzy +#| msgid "redis_tools" +msgid "redis total slot" +msgstr "redis_tools" + +#: backend/flow/consts.py:677 +msgid "redis PFAIL state" +msgstr "redis PFAIL state" + +#: backend/flow/consts.py:678 +#, fuzzy +#| msgid "redis_master" +msgid "redis fail state" +msgstr "redis_master" + +#: backend/flow/consts.py:679 +msgid "redis handshake state" +msgstr "redis handshake state" + +#: backend/flow/consts.py:680 +#, fuzzy +#| msgid "redis_master" +msgid "redis noaddr state" +msgstr "redis_master" + +#: backend/flow/consts.py:681 +#, fuzzy +#| msgid "redis config file" +msgid "redis noflags state" +msgstr "redis config file" + +#: backend/flow/consts.py:689 +#, fuzzy +#| msgid "redis_master" +msgid "redis master role" +msgstr "redis_master" + +#: backend/flow/consts.py:690 +#, fuzzy +#| msgid "redis_slave" +msgid "redis slave role" +msgstr "redis_slave" + +#: backend/flow/consts.py:691 +#, fuzzy +#| msgid "redis config file" +msgid "redis unknown role" +msgstr "redis config file" + +#: backend/flow/consts.py:699 +msgid "redis master link status up" +msgstr "redis master link status up" + +#: backend/flow/consts.py:700 +msgid "redis master link status down" +msgstr "redis master link status down" + +#: backend/flow/consts.py:701 +msgid "redis ssd incrSync state" +msgstr "redis ssd incrSync state" + +#: backend/flow/consts.py:702 +msgid "redis ssd REPL_FOLLOW state" +msgstr "redis ssd REPL_FOLLOW state" + +#: backend/flow/consts.py:703 +msgid "redis connected status" +msgstr "redis connected status" + +#: backend/flow/consts.py:704 +msgid "redis disconnected status" +msgstr "redis disconnected status" + +#: backend/flow/consts.py:712 +msgid "" +"redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" +msgstr "" +"redis cluster state ok,all slots are covered. 通过 cluster info 命令获取" + +#: backend/flow/consts.py:713 +msgid "" +"redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" +msgstr "" +"redis cluster state fail,not all slots are covered.通过 cluster info 命令获取" + +#: backend/flow/consts.py:722 +msgid "tdbctl" +msgstr "" + +#: backend/flow/engine/bamboo/engine.py:245 +msgid "获取流程失败" +msgstr "获取流程失败" + +#: backend/flow/engine/bamboo/engine.py:248 +msgid "获取流程节点失败" +msgstr "获取流程节点失败" + +#: backend/flow/engine/bamboo/engine.py:251 +msgid "获取节点运行版本失败" +msgstr "获取节点运行版本失败" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:127 +msgid "下发{}可执行文件包" +msgstr "下发{}可执行文件包" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:136 +msgid "部署{}服务进程" +msgstr "部署{}服务进程" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:185 +msgid "下发{}配置文件" +msgstr "下发{}配置文件" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:311 +msgid "存量集群的权限更新" +msgstr "存量集群的权限更新" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:339 +#, fuzzy +#| msgid "更新服务" +msgid "更新服务元信息" +msgstr "更新服务" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:364 +msgid "裁撤{}的服务" +msgstr "裁撤{}的服务" + +#: backend/flow/engine/bamboo/scene/cloud/base_service_flow.py:387 +#, fuzzy +#| msgid "nginx服务" +msgid "重启nginx服务" +msgstr "nginx服务" + +#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:40 +msgid "主机{}部署gm服务" +msgstr "主机{}部署gm服务" + +#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:59 +msgid "主机{}部署agent服务" +msgstr "主机{}部署agent服务" + +#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:76 +msgid "部署dbha-gm服务" +msgstr "部署dbha-gm服务" + +#: backend/flow/engine/bamboo/scene/cloud/dbha_service_flow.py:82 +msgid "部署dbha-agent服务" +msgstr "部署dbha-agent服务" + +#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:46 +#: backend/flow/engine/bamboo/scene/cloud/nginx_service_flow.py:75 +msgid "主机{}部署dns服务" +msgstr "主机{}部署dns服务" + +#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:50 +msgid "部署dns服务" +msgstr "部署dns服务" + +#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:65 +msgid "对存量机器的nameserver刷新" +msgstr "对存量机器的nameserver刷新" + +#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:154 +#, fuzzy +#| msgid "部署dns服务" +msgid "部署新dns服务流程" +msgstr "部署dns服务" + +#: backend/flow/engine/bamboo/scene/cloud/dns_service_flow.py:173 +msgid "裁撤旧dns服务流程" +msgstr "裁撤旧dns服务流程" #: backend/flow/engine/bamboo/scene/cloud/drs_service_flow.py:34 #, fuzzy @@ -7990,7 +8417,7 @@ msgid "执行sa初始化" msgstr "执行sa初始化" #: backend/flow/engine/bamboo/scene/common/machine_os_init.py:64 -#: backend/ticket/constants.py:239 +#: backend/ticket/constants.py:240 msgid "资源池导入" msgstr "资源池导入" @@ -8018,8 +8445,6 @@ msgstr "资源池导入" #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:72 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:63 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_shrink_flow.py:55 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:76 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:74 msgid "获取集群部署配置" msgstr "获取集群部署配置" @@ -8035,8 +8460,6 @@ msgstr "获取集群部署配置" #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:76 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:68 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_shrink_flow.py:59 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:70 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:68 msgid "获取机器信息" msgstr "获取机器信息" @@ -8315,12 +8738,11 @@ msgstr "下发hdfs介质包" #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:145 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:343 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:120 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:108 #: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:140 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:105 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:89 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:227 #: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:99 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:208 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:165 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:223 msgid "初始化机器" msgstr "初始化机器" @@ -8599,8 +9021,10 @@ msgstr "安装telegraf-{}" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:290 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:181 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:120 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:331 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:264 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:125 +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:162 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:348 +#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:91 msgid "更新DBMeta元信息" msgstr "更新DBMeta元信息" @@ -8674,8 +9098,9 @@ msgstr "插入manager实例信息" #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:145 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_replace_flow.py:176 #: backend/flow/engine/bamboo/scene/pulsar/pulsar_scale_up_flow.py:114 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:318 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:250 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:164 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:332 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:335 msgid "添加集群域名" msgstr "添加集群域名" @@ -8758,126 +9183,115 @@ msgstr "停止进程" msgid "清理数据" msgstr "清理数据" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:62 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:61 msgid "执行ip信息为空" msgstr "执行ip信息为空" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:70 -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:345 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:69 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:366 msgid "下发MySQL周边程序介质" msgstr "下发MySQL周边程序介质" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:87 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:86 #, fuzzy #| msgid "Master安装备份程序" msgid "Master[{}]安装备份程序" msgstr "Master安装备份程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:100 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:99 #, fuzzy #| msgid "Master安装rotate_binlog程序" msgid "Master[{}]安装rotate_binlog程序" msgstr "Master安装rotate_binlog程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:113 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:112 #, fuzzy #| msgid "Master安装mysql-monitor" msgid "Master[{}]安装mysql-monitor" msgstr "Master安装mysql-monitor" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:132 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:131 #, fuzzy #| msgid "Master安装校验程序" msgid "Master[{}]安装校验程序" msgstr "Master安装校验程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:149 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:148 #, fuzzy #| msgid "Master安装DBATools工具箱" msgid "Master[{}]安装DBATools工具箱" msgstr "Master安装DBATools工具箱" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:168 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:167 #, fuzzy #| msgid "Slave安装备份程序" msgid "Slave[{}]安装备份程序" msgstr "Slave安装备份程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:181 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:180 #, fuzzy #| msgid "Slave安装rotate_binlog程序" msgid "Slave[{}]安装rotate_binlog程序" msgstr "Slave安装rotate_binlog程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:194 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:193 #, fuzzy #| msgid "Slave安装mysql-monitor" msgid "Slave[{}]安装mysql-monitor" msgstr "Slave安装mysql-monitor" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:213 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:212 #, fuzzy #| msgid "Slave安装校验程序" msgid "Slave[{}]安装校验程序" msgstr "Slave安装校验程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:230 -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:361 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:229 #, fuzzy #| msgid "Slave安装DBATools工具箱" msgid "Slave[{}]安装DBATools工具箱" msgstr "Slave安装DBATools工具箱" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:248 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:247 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_add.py:260 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:291 msgid "Proxy安装mysql-monitor" msgstr "Proxy安装mysql-monitor" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:263 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:262 msgid "安装MySql周边程序" msgstr "安装MySql周边程序" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:298 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:297 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:219 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:384 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:450 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:400 msgid "新增repl帐户" msgstr "新增repl帐户" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:313 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:312 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:228 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:135 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:399 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:149 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:465 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:415 msgid "建立主从关系" msgstr "建立主从关系" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:325 +#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:324 msgid "建立主从同步[{}]" msgstr "建立主从同步[{}]" -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:377 -#, fuzzy -#| msgid "Master安装mysql-monitor" -msgid "spider[{}]安装mysql-monitor" -msgstr "Master安装mysql-monitor" - -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:397 -#, fuzzy -#| msgid "Master安装备份程序" -msgid "spider[{}]安装备份程序" -msgstr "Master安装备份程序" - -#: backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py:411 +#: backend/flow/engine/bamboo/scene/mysql/common/exceptions.py:17 #, fuzzy -#| msgid "安装MySql周边程序" -msgid "安装Spider周边程序" -msgstr "安装MySql周边程序" +#| msgid "Flow模块HDFS异常" +msgid "Flow模块TenDB 异常" +msgstr "Flow模块HDFS异常" #: backend/flow/engine/bamboo/scene/mysql/import_sqlfile_flow.py:77 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:110 #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_disable_flow.py:97 #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:73 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:172 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:180 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_add.py:178 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:191 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:334 @@ -8949,7 +9363,7 @@ msgstr "检查元数据信息是否存在主备关系" #: backend/flow/engine/bamboo/scene/mysql/mysql_checksum.py:124 #: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:113 #: backend/flow/plugins/components/collections/common/sleep_timer_service.py:140 -#: backend/ticket/constants.py:320 +#: backend/ticket/constants.py:321 msgid "定时" msgstr "定时" @@ -8958,14 +9372,18 @@ msgid "创建临时用户" msgstr "创建临时用户" #: backend/flow/engine/bamboo/scene/mysql/mysql_checksum.py:149 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:117 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:137 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:129 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:102 #: backend/flow/engine/bamboo/scene/mysql/mysql_partition.py:119 #: backend/flow/engine/bamboo/scene/mysql/mysql_rename_database_flow.py:173 #: backend/flow/engine/bamboo/scene/mysql/mysql_truncate_flow.py:171 #: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:119 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:126 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:215 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:172 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:262 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:317 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:155 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:226 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:273 #: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:258 #: backend/flow/engine/bamboo/scene/spider/spider_partition.py:90 #: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:270 @@ -9061,7 +9479,7 @@ msgid "空闲检查" msgstr "空闲检查" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:129 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:174 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:189 msgid "下发MySQL介质包" msgstr "下发MySQL介质包" @@ -9076,21 +9494,21 @@ msgstr "下发Proxy介质包" #: backend/flow/engine/bamboo/scene/mysql/mysql_restore_slave_flow.py:597 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:350 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:127 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:98 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:236 #: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:110 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:219 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:174 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:234 msgid "部署mysql-crond" msgstr "部署mysql-crond" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:184 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:211 msgid "安装proxy实例" msgstr "安装proxy实例" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:194 #: backend/flow/engine/bamboo/scene/mysql/mysql_rollback_data_flow.py:357 #: backend/flow/engine/bamboo/scene/mysql/mysql_single_apply_flow.py:134 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:233 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:248 msgid "安装MySQL实例" msgstr "安装MySQL实例" @@ -9111,7 +9529,7 @@ msgid "添加从集群域名" msgstr "添加从集群域名" #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_apply_flow.py:276 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:367 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:383 msgid "{}集群部署" msgstr "{}集群部署" @@ -9119,33 +9537,40 @@ msgstr "{}集群部署" msgid "部署MySQL高可用集群" msgstr "部署MySQL高可用集群" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:94 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:97 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:83 #, fuzzy #| msgid "%s slave 节点不存在" msgid "{} standby slave 不存在" msgstr "%s slave 节点不存在" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:111 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:117 msgid "构造mydumper正则" msgstr "构造mydumper正则" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:129 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:149 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:123 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:166 +msgid "检查正则匹配" +msgstr "" + +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:141 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:114 msgid "执行库表备份" msgstr "执行库表备份" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:143 -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:163 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:244 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:155 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:128 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:124 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:123 msgid "关联备份id" msgstr "关联备份id" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:148 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:250 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:160 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:130 msgid "{} 库表备份" msgstr "{} 库表备份" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:151 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_db_table_backup.py:163 msgid "构建库表备份流程成功" msgstr "构建库表备份流程成功" @@ -9155,11 +9580,6 @@ msgstr "构建库表备份流程成功" msgid "删除注册CC系统的服务实例" msgstr "删除注册CC系统的服务实例" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:128 -#: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:528 -msgid "清理实例周边配置" -msgstr "清理实例周边配置" - #: backend/flow/engine/bamboo/scene/mysql/mysql_ha_destroy_flow.py:142 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:356 msgid "卸载proxy实例" @@ -9216,11 +9636,11 @@ msgstr "集群变更ONLINE状态" msgid "启动MySQL高可用集群[{}]" msgstr "启动MySQL高可用集群[{}]" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:168 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:133 msgid "{} 全库备份" msgstr "{} 全库备份" -#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:171 +#: backend/flow/engine/bamboo/scene/mysql/mysql_ha_full_backup_flow.py:136 msgid "构建全库备份流程成功" msgstr "构建全库备份流程成功" @@ -9229,7 +9649,7 @@ msgid "执行集群主故障转移" msgstr "执行集群主故障转移" #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:134 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:266 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:274 msgid "salve节点同步新master数据" msgstr "salve节点同步新master数据" @@ -9238,7 +9658,7 @@ msgid "{}集群执行主故障切换" msgstr "{}集群执行主故障切换" #: backend/flow/engine/bamboo/scene/mysql/mysql_master_fail_over.py:160 -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:292 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:300 #: backend/flow/engine/bamboo/scene/mysql/mysql_proxy_cluster_switch.py:278 msgid "变更db_meta元信息" msgstr "变更db_meta元信息" @@ -9247,33 +9667,37 @@ msgstr "变更db_meta元信息" msgid "主故障切换流程[整机切换]" msgstr "主故障切换流程[整机切换]" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:121 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:87 +msgid "the is_stand_by of new-master-instance [{}] is False " +msgstr "" + +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:129 msgid "回收新master的域名映射" msgstr "回收新master的域名映射" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:136 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:144 msgid "对旧master添加域名映射" msgstr "对旧master添加域名映射" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:216 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:224 msgid "旧master添加切换临时账号" msgstr "旧master添加切换临时账号" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:231 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:239 #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:453 msgid "新master克隆旧master权限" msgstr "新master克隆旧master权限" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:252 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:260 #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:461 msgid "执行集群切换" msgstr "执行集群切换" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:285 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:293 msgid "{}集群执行主从切换" msgstr "{}集群执行主从切换" -#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:315 +#: backend/flow/engine/bamboo/scene/mysql/mysql_master_slave_switch.py:323 msgid "主从切换流程[整机切换]" msgstr "主从切换流程[整机切换]" @@ -9401,6 +9825,10 @@ msgstr "对新slave添加域名映射" msgid "{}集群执行成对切换" msgstr "{}集群执行成对切换" +#: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:528 +msgid "清理实例周边配置" +msgstr "清理实例周边配置" + #: backend/flow/engine/bamboo/scene/mysql/mysql_migrate_cluster_flow.py:546 msgid "卸载MySQL实例:{}:{}" msgstr "卸载MySQL实例:{}:{}" @@ -10065,6 +10493,42 @@ msgstr "滚动重启broker节点-{ip}" msgid "等待数据过期" msgstr "等待数据过期" +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:68 +#, fuzzy +#| msgid "[redis]下发介质包" +msgid "Proxy-001-{}-下发介质包" +msgstr "[redis]下发介质包" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:75 +#, fuzzy +#| msgid "初始化机器" +msgid "Proxy-002-{}-初始化机器" +msgstr "初始化机器" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:100 +#, fuzzy +#| msgid "Redis-003-{}-安装实例" +msgid "Proxy-003-{}-安装实例" +msgstr "Redis-003-{}-安装实例" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:109 +#, fuzzy +#| msgid "Redis-004-{}-写入元数据" +msgid "Proxy-004-{}-写入元数据" +msgstr "Redis-004-{}-写入元数据" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:130 +#, fuzzy +#| msgid "Redis-005-{}-安装监控" +msgid "Proxy-005-{}-安装监控" +msgstr "Redis-005-{}-安装监控" + +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/proxy_install.py:135 +#, fuzzy +#| msgid "Redis-{}-安装原子任务" +msgid "Proxy-{}-安装原子任务" +msgstr "Redis-{}-安装原子任务" + #: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dbmon.py:57 #, fuzzy #| msgid "[redis]下发介质包" @@ -10076,31 +10540,31 @@ msgid "Redis-202-{}-安装监控" msgstr "Redis-202-{}-安装监控" #: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dbmon.py:83 -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:120 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:129 msgid "Redis-{}-安装原子任务" msgstr "Redis-{}-安装原子任务" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:61 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:63 #, fuzzy #| msgid "[redis]下发介质包" msgid "Redis-001-{}-下发介质包" msgstr "[redis]下发介质包" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:69 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:71 #, fuzzy #| msgid "初始化机器" msgid "Redis-002-{}-初始化机器" msgstr "初始化机器" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:81 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:90 msgid "Redis-003-{}-安装实例" msgstr "Redis-003-{}-安装实例" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:95 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:104 msgid "Redis-004-{}-写入元数据" msgstr "Redis-004-{}-写入元数据" -#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:115 +#: backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_install.py:124 msgid "Redis-005-{}-安装监控" msgstr "Redis-005-{}-安装监控" @@ -10216,80 +10680,46 @@ msgstr "Redis-505-元数据切换" msgid "Redis-{}-实例切换" msgstr "实例切换" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:87 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:84 -msgid "[proxy]下发介质包" -msgstr "[proxy]下发介质包" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:97 -msgid "[redis]下发介质包" -msgstr "[redis]下发介质包" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:119 -msgid "安装Redis实例" -msgstr "安装Redis实例" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:128 -msgid "redis实例安装 元数据" -msgstr "redis实例安装 元数据" +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:98 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:98 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:114 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:104 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_master.py:137 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_slave.py:135 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_shutdown.py:118 +#: backend/flow/engine/bamboo/scene/redis/redis_dbmon.py:78 +#: backend/flow/engine/bamboo/scene/redis/redis_flush_data.py:102 +#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:100 +#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:88 +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:128 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:88 +msgid "初始化配置" +msgstr "初始化配置" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:139 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:160 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:157 msgid "redis建立主从 元数据" msgstr "redis建立主从 元数据" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:168 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:165 -msgid "[redis master]部署bkdbmon" -msgstr "[redis master]部署bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:193 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:190 -msgid "[redis slave]部署bkdbmon" -msgstr "[redis slave]部署bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:235 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:232 -msgid "[proxy]部署bkdbmon" -msgstr "[proxy]部署bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:248 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:245 -msgid "proxy安装 元数据" -msgstr "proxy安装 元数据" - -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:254 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:250 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:186 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:184 msgid "建立集群 元数据" msgstr "建立集群 元数据" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:278 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:263 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:210 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:197 msgid "回写集群配置[Redis]" msgstr "回写集群配置[Redis]" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:294 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:226 msgid "回写集群配置[Twemproxy]" msgstr "回写集群配置[Twemproxy]" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:309 -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:294 +#: backend/flow/engine/bamboo/scene/redis/redis_cluster_apply_flow.py:241 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:228 msgid "注册域名" msgstr "注册域名" -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:98 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:114 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:104 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_master.py:137 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_slave.py:135 -#: backend/flow/engine/bamboo/scene/redis/redis_cluster_shutdown.py:118 -#: backend/flow/engine/bamboo/scene/redis/redis_dbmon.py:78 -#: backend/flow/engine/bamboo/scene/redis/redis_flush_data.py:102 -#: backend/flow/engine/bamboo/scene/redis/redis_keys_delete.py:100 -#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:88 -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:128 -msgid "初始化配置" -msgstr "初始化配置" - #: backend/flow/engine/bamboo/scene/redis/redis_cluster_backup.py:103 #: backend/flow/engine/bamboo/scene/redis/redis_cluster_dts.py:119 #: backend/flow/engine/bamboo/scene/redis/redis_cluster_open_close.py:109 @@ -10449,1873 +10879,1657 @@ msgstr "集群[{}]按文件删除keys" msgid "提取key: {}" msgstr "提取key: {}" -#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:110 -msgid "集群[{}提取keys" -msgstr "集群[{}提取keys" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:136 -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:211 -msgid "proxy下发介质包" -msgstr "proxy下发介质包" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:151 -msgid "{}安装proxy实例" -msgstr "{}安装proxy实例" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:158 -msgid "{}部署bkdbmon" -msgstr "{}部署bkdbmon" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:171 -msgid "{}proxy扩容 元数据" -msgstr "{}proxy扩容 元数据" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:184 -msgid "{}添加域名" -msgstr "{}添加域名" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:200 -msgid "主机转移" -msgstr "主机转移" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:203 -msgid "新增proxy实例" -msgstr "新增proxy实例" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:226 -msgid "{}删除域名" -msgstr "{}删除域名" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:244 -#: backend/flow/engine/bamboo/scene/redis/singele_redis_shutdown.py:136 -msgid "主机转移到空闲机" -msgstr "主机转移到空闲机" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:249 -msgid "下架proxy实例" -msgstr "下架proxy实例" - -#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:259 -msgid "proxy下架元数据" -msgstr "proxy下架元数据" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:94 -msgid "[tendisplus]下发介质包" -msgstr "[tendisplus]下发介质包" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:116 -msgid "安装tendisplus实例" -msgstr "安装tendisplus实例" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:125 -msgid "tendisplus实例安装 元数据" -msgstr "tendisplus实例安装 元数据" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:132 -msgid "建立meet关系" -msgstr "建立meet关系" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:136 -msgid "redis建立主从元数据" -msgstr "redis建立主从元数据" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:208 -msgid "安装predixy实例" -msgstr "安装predixy实例" - -#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:279 -msgid "回写集群配置[predixy]" -msgstr "回写集群配置[predixy]" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:209 -msgid "查询remotedb version 失败" -msgstr "查询remotedb version 失败" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:215 -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:231 -#, python-brace-format -msgid "存在多个版本{version}" -msgstr "存在多个版本{version}" - -#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:225 -msgid "查询spider version 失败" -msgstr "查询spider version 失败" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:79 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:187 -msgid "下发Spider/tdbCtl介质包" -msgstr "下发Spider/tdbCtl介质包" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:129 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:253 -msgid "安装Spider实例" -msgstr "安装Spider实例" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:140 -msgid "spider上对中控主节点进行授权" -msgstr "spider上对中控主节点进行授权" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:150 -msgid "中控主节点注册临时spider节点路由信息" -msgstr "中控主节点注册临时spider节点路由信息" - -#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:155 -msgid "{}添加临时spider节点" -msgstr "{}添加临时spider节点" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:147 -#, fuzzy -#| msgid "创建临时用户" -msgid "分片{}:创建临时用户" -msgstr "创建临时用户" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:201 -#, fuzzy -#| msgid "master[{}{}{}],slave[{}{}{}]的校验结果" -msgid "分片{}:master[{}{}{}],slave[{}{}{}]的校验结果" -msgstr "master[{}{}{}],slave[{}{}{}]的校验结果" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:216 -#, fuzzy -#| msgid "master[{}{}{}]的校验任务" -msgid "分片{}:master[{}{}{}]的校验任务" -msgstr "master[{}{}{}]的校验任务" - -#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:224 -#, fuzzy -#| msgid "master[{}{}{}]的校验任务" -msgid "集群[{}]的校验任务" -msgstr "master[{}{}{}]的校验任务" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:120 -#, fuzzy -#| msgid "构造mydumper正则" -msgid "构造 spider/ctl mydumper正则" -msgstr "构造mydumper正则" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:138 -#, fuzzy -#| msgid "执行库表备份" -msgid "spider 执行库表备份" -msgstr "执行库表备份" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:151 -#, fuzzy -#| msgid "执行库表备份" -msgid "ctl 执行库表备份" -msgstr "执行库表备份" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:164 -#, fuzzy -#| msgid "备份测试库表结构" -msgid "spider/ctl 备份库表结构" -msgstr "备份测试库表结构" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:209 -#, fuzzy -#| msgid "构造mydumper正则" -msgid "构造remote mydumper正则" -msgstr "构造mydumper正则" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:227 -#, fuzzy -#| msgid "执行库表备份" -msgid "remote 执行库表备份" -msgstr "执行库表备份" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:239 -msgid "remote 备份库表" -msgstr "remote 备份库表" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:254 -#, fuzzy -#| msgid "构建库表备份流程成功" -msgid "构造库表备份流程成功" -msgstr "构建库表备份流程成功" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:72 -msgid "存入的存储节点数量不是偶数,请检查!" -msgstr "存入的存储节点数量不是偶数,请检查!" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:269 -msgid "安装Spider集群中控实例" -msgstr "安装Spider集群中控实例" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:301 -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:199 -msgid "集群内部节点间授权" -msgstr "集群内部节点间授权" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:311 -msgid "初始化集群节点间关系" -msgstr "初始化集群节点间关系" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:413 -msgid "部署spider-ctl集群" -msgstr "部署spider-ctl集群" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:136 -msgid "卸载spider实例" -msgstr "卸载spider实例" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:150 -msgid "卸载中控实例" -msgstr "卸载中控实例" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:193 -msgid "下架TenDB-Cluster集群[{}]" -msgstr "下架TenDB-Cluster集群[{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_disable_deploy.py:103 -#, fuzzy -#| msgid "卸载spider实例" -msgid "重启spider实例" -msgstr "卸载spider实例" +#: backend/flow/engine/bamboo/scene/redis/redis_keys_extract.py:110 +msgid "集群[{}提取keys" +msgstr "集群[{}提取keys" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_enable_deploy.py:137 -#, fuzzy -#| msgid "启动MySQL高可用集群[{}]" -msgid "启用spider集群[{}]" -msgstr "启动MySQL高可用集群[{}]" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:136 +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:211 +msgid "proxy下发介质包" +msgstr "proxy下发介质包" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:182 -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:186 -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:190 -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:194 -msgid "预清理备份库" -msgstr "预清理备份库" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:151 +msgid "{}安装proxy实例" +msgstr "{}安装proxy实例" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:240 -msgid "适配备份库映射" -msgstr "适配备份库映射" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:158 +msgid "{}部署bkdbmon" +msgstr "{}部署bkdbmon" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:246 -msgid "重建备份库" -msgstr "重建备份库" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:171 +msgid "{}proxy扩容 元数据" +msgstr "{}proxy扩容 元数据" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:283 -msgid "{} on remote {} 清档" -msgstr "{} on remote {} 清档" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:184 +msgid "{}添加域名" +msgstr "{}添加域名" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:294 -msgid "处理集群表" -msgstr "处理集群表" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:200 +msgid "主机转移" +msgstr "主机转移" -#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:311 -#, fuzzy -#| msgid "构建清档流程成功" -msgid "构造清档流程成功" -msgstr "构建清档流程成功" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:203 +msgid "新增proxy实例" +msgstr "新增proxy实例" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:110 -msgid "partition_sql_file_{}_{}_{}_{}.txt" -msgstr "partition_sql_file_{}_{}_{}_{}.txt" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:226 +msgid "{}删除域名" +msgstr "{}删除域名" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:113 -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:124 -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:145 -msgid "{}: {}" -msgstr "{}: {}" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:244 +#: backend/flow/engine/bamboo/scene/redis/singele_redis_shutdown.py:136 +msgid "主机转移到空闲机" +msgstr "主机转移到空闲机" -#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:167 -#, fuzzy -#| msgid "构建partition流程成功" -msgid "构建spider partition流程成功" -msgstr "构建partition流程成功" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:249 +msgid "下架proxy实例" +msgstr "下架proxy实例" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:307 -#, fuzzy -#| msgid "{} 重命名数据库" -msgid "{} on remote {} 重命名数据库" -msgstr "{} 重命名数据库" +#: backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py:259 +msgid "proxy下架元数据" +msgstr "proxy下架元数据" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:315 +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:140 #, fuzzy -#| msgid "删除集群域名" -msgid "删除集群源库" -msgstr "删除集群域名" +#| msgid "建立meet关系" +msgid "建立集群meet关系" +msgstr "建立meet关系" -#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:323 -#, fuzzy -#| msgid "构建重命名数据库流程成功" -msgid "构造数据库重命名流程成功" -msgstr "构建重命名数据库流程成功" +#: backend/flow/engine/bamboo/scene/redis/tendis_plus_apply_flow.py:213 +msgid "回写集群配置[predixy]" +msgstr "回写集群配置[predixy]" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:148 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:72 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:210 #, fuzzy #| msgid "下发proxy安装介质" msgid "下发spider安装介质" msgstr "下发proxy安装介质" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:190 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:114 #, fuzzy #| msgid "安装Spider实例" msgid "安装Spider_slave实例" msgstr "安装Spider实例" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:205 -#, fuzzy -#| msgid "下发actuator" -msgid "中控Master下发DB-actuator" -msgstr "下发actuator" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:130 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:284 +msgid "克隆权限到spider节点[{}]" +msgstr "克隆权限到spider节点[{}]" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:221 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:149 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:307 msgid "添加对应路由关系" msgstr "添加对应路由关系" -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:231 -msgid "克隆权限到spider节点[{}]" -msgstr "克隆权限到spider节点[{}]" - -#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:280 +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:176 #, fuzzy -#| msgid "开始添加slave" -msgid "添加slave集群" -msgstr "开始添加slave" - -#: backend/flow/engine/exceptions.py:28 -msgid "组件服务未部署" -msgstr "组件服务未部署" - -#: backend/flow/models.py:22 backend/flow/models.py:38 -msgid "流程ID" -msgstr "流程ID" +#| msgid "{}添加临时spider节点" +msgid "集群[{}]添加spider slave节点" +msgstr "{}添加临时spider节点" -#: backend/flow/models.py:23 -msgid "流程树" -msgstr "流程树" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:252 +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:129 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:268 +msgid "安装Spider实例" +msgstr "安装Spider实例" -#: backend/flow/models.py:25 backend/ticket/serializers.py:108 -msgid "流程状态" -msgstr "流程状态" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:267 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:284 +msgid "安装Spider集群中控实例" +msgstr "安装Spider集群中控实例" -#: backend/flow/models.py:27 -msgid "流程创建人" -msgstr "流程创建人" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:344 +#, fuzzy +#| msgid "{}添加临时spider节点" +msgid "集群[{}]添加spider master节点" +msgstr "{}添加临时spider节点" -#: backend/flow/models.py:28 -msgid "启动时间" -msgstr "启动时间" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:382 +#, fuzzy +#| msgid "Master安装DBATools工具箱" +msgid "spider[{}]安装DBATools工具箱" +msgstr "Master安装DBATools工具箱" -#: backend/flow/models.py:29 -msgid "流程结束时间" -msgstr "流程结束时间" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:398 +#, fuzzy +#| msgid "Master安装mysql-monitor" +msgid "spider[{}]安装mysql-monitor" +msgstr "Master安装mysql-monitor" -#: backend/flow/models.py:40 -msgid "当前版本ID" -msgstr "当前版本ID" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:415 +#, fuzzy +#| msgid "Master安装备份程序" +msgid "spider[{}]安装备份程序" +msgstr "Master安装备份程序" -#: backend/flow/models.py:42 -msgid "节点状态" -msgstr "节点状态" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:429 +#, fuzzy +#| msgid "安装MySql周边程序" +msgid "安装Spider周边程序" +msgstr "安装MySql周边程序" -#: backend/flow/models.py:44 -msgid "节点运行时IP" -msgstr "节点运行时IP" +#: backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py:479 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:429 +msgid "部署spider-ctl集群" +msgstr "部署spider-ctl集群" -#: backend/flow/models.py:46 -msgid "开始执行时间" -msgstr "开始执行时间" +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:17 +#, fuzzy +#| msgid "Flow模块HDFS异常" +msgid "Flow模块TenDB Cluster异常" +msgstr "Flow模块HDFS异常" -#: backend/flow/plugins/components/collections/cloud/exec_service_script.py:58 -msgid "该节点{}获取到执行ip信息为空,请联系系统管理员" -msgstr "该节点{}获取到执行ip信息为空,请联系系统管理员" +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:28 +msgid "添加spider-master节点是分配incr初始值失败" +msgstr "" -#: backend/flow/plugins/components/collections/cloud/push_config_file.py:56 -#: backend/flow/plugins/components/collections/cloud/trans_files.py:59 -#: backend/flow/plugins/components/collections/es/trans_files.py:63 -#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:70 -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:99 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:85 -#: backend/flow/plugins/components/collections/redis/trans_flies.py:79 -msgid "[{}] 下发介质包参数:{}" -msgstr "[{}] 下发介质包参数:{}" +#: backend/flow/engine/bamboo/scene/spider/common/exceptions.py:34 +#, fuzzy +#| msgid "spider中控节点名称" +msgid "添加spider节点路由失败" +msgstr "spider中控节点名称" -#: backend/flow/plugins/components/collections/cloud/trans_files.py:44 -msgid "该节点{}获取到执行ip信息为空,请联系系统管理员{}" -msgstr "该节点{}获取到执行ip信息为空,请联系系统管理员{}" +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:209 +msgid "查询remotedb version 失败" +msgstr "查询remotedb version 失败" -#: backend/flow/plugins/components/collections/common/base_service.py:83 -msgid "[{}] 运行成功" -msgstr "[{}] 运行成功" +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:215 +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:231 +#, python-brace-format +msgid "存在多个版本{version}" +msgstr "存在多个版本{version}" -#: backend/flow/plugins/components/collections/common/base_service.py:87 -msgid "[{}] 失败: {}" -msgstr "[{}] 失败: {}" +#: backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py:225 +msgid "查询spider version 失败" +msgstr "查询spider version 失败" -#: backend/flow/plugins/components/collections/common/base_service.py:216 -msgid "[写入上下文结果失败] failed: {}" -msgstr "[写入上下文结果失败] failed: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:87 +msgid "[{}]The cluster has not added a slave cluster, skip" +msgstr "" -#: backend/flow/plugins/components/collections/common/base_service.py:253 -msgid "[{}] 任务正在执行🤔" -msgstr "[{}] 任务正在执行🤔" +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:96 +msgid "[{}]This type of role addition is not supported" +msgstr "" -#: backend/flow/plugins/components/collections/common/base_service.py:262 -msgid "[{}] 任务调度失败😱" -msgstr "[{}] 任务调度失败😱" +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:140 +#, fuzzy +#| msgid "{}添加临时spider节点" +msgid "[{}]添加spider-master节点流程" +msgstr "{}添加临时spider节点" -#: backend/flow/plugins/components/collections/common/base_service.py:273 -msgid "[{}]任务调度成功🥳︎" -msgstr "[{}]任务调度成功🥳︎" +#: backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py:177 +#, fuzzy +#| msgid "{}添加临时spider节点" +msgid "[{}]添加spider-slave节点流程" +msgstr "{}添加临时spider节点" -#: backend/flow/plugins/components/collections/common/base_service.py:279 -msgid "[{}]该节点需要获取执行后日志,赋值到trans_data" -msgstr "[{}]该节点需要获取执行后日志,赋值到trans_data" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:79 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:202 +msgid "下发Spider/tdbCtl介质包" +msgstr "下发Spider/tdbCtl介质包" -#: backend/flow/plugins/components/collections/common/base_service.py:290 -msgid "[{}] 获取执行后日志失败,获取ip[{}]" -msgstr "[{}] 获取执行后日志失败,获取ip[{}]" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:140 +msgid "spider上对中控主节点进行授权" +msgstr "spider上对中控主节点进行授权" -#: backend/flow/plugins/components/collections/common/bigdata_manager_service.py:123 -msgid "无法找到Manager处理类型,请联系系统管理员:{}" -msgstr "无法找到Manager处理类型,请联系系统管理员:{}" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:150 +msgid "中控主节点注册临时spider节点路由信息" +msgstr "中控主节点注册临时spider节点路由信息" -#: backend/flow/plugins/components/collections/common/create_ticket.py:36 -msgid "未知单据类型, {}不存在于已知单据类型中" -msgstr "未知单据类型, {}不存在于已知单据类型中" +#: backend/flow/engine/bamboo/scene/spider/spider_add_tmp_node.py:155 +msgid "{}添加临时spider节点" +msgstr "{}添加临时spider节点" -#: backend/flow/plugins/components/collections/common/create_ticket.py:41 -msgid "不允许自动创建单据,单据创建流程结束" -msgstr "不允许自动创建单据,单据创建流程结束" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:147 +#, fuzzy +#| msgid "创建临时用户" +msgid "分片{}:创建临时用户" +msgstr "创建临时用户" -#: backend/flow/plugins/components/collections/common/external_service.py:36 -msgid "第三方接口: {} 请求成功! 返回参数为: {}" -msgstr "第三方接口: {} 请求成功! 返回参数为: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:201 +#, fuzzy +#| msgid "master[{}{}{}],slave[{}{}{}]的校验结果" +msgid "分片{}:master[{}{}{}],slave[{}{}{}]的校验结果" +msgstr "master[{}{}{}],slave[{}{}{}]的校验结果" -#: backend/flow/plugins/components/collections/common/external_service.py:38 +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:216 #, fuzzy -#| msgid "下发文件job启动失败,错误信息: {}" -msgid "第三方接口:{} 调用失败!错误信息为: {}" -msgstr "下发文件job启动失败,错误信息: {}" +#| msgid "master[{}{}{}]的校验任务" +msgid "分片{}:master[{}{}{}]的校验任务" +msgstr "master[{}{}{}]的校验任务" -#: backend/flow/plugins/components/collections/common/external_service.py:40 +#: backend/flow/engine/bamboo/scene/spider/spider_checksum.py:224 #, fuzzy -#| msgid "JWT鉴权错误,错误信息: {}" -msgid "请求遇到未知错误!错误信息为: {}" -msgstr "JWT鉴权错误,错误信息: {}" +#| msgid "master[{}{}{}]的校验任务" +msgid "集群[{}]的校验任务" +msgstr "master[{}{}{}]的校验任务" -#: backend/flow/plugins/components/collections/common/pause.py:44 -msgid "【{}】自动化流程待确认,是否继续?" -msgstr "【{}】自动化流程待确认,是否继续?" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:121 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:120 +msgid "不支持的备份位置 {}" +msgstr "" -#: backend/flow/plugins/components/collections/common/pause.py:78 -msgid "回调数据" -msgstr "回调数据" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:134 +#, fuzzy +#| msgid "构建库表备份流程成功" +msgid "构造库表备份流程成功" +msgstr "构建库表备份流程成功" -#: backend/flow/plugins/components/collections/common/pause.py:87 -#: backend/ticket/constants.py:314 -msgid "暂停" -msgstr "暂停" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:160 +#, fuzzy +#| msgid "构造mydumper正则" +msgid "构造 spider/ctl mydumper正则" +msgstr "构造mydumper正则" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:38 -msgid "{}-空闲检查" -msgstr "{}-空闲检查" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:184 +#, fuzzy +#| msgid "执行库表备份" +msgid "spider 执行库表备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:70 -#: backend/flow/plugins/components/collections/common/sa_init.py:66 -msgid "空闲检查失败" -msgstr "空闲检查失败" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:197 +#, fuzzy +#| msgid "执行库表备份" +msgid "ctl 执行库表备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:72 -#: backend/flow/plugins/components/collections/common/sa_init.py:68 -msgid "任务状态异常{}" -msgstr "任务状态异常{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:208 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:191 +#, fuzzy +#| msgid "备份测试库表结构" +msgid "spider/ctl备份库表结构" +msgstr "备份测试库表结构" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:85 -msgid "错误详情{}" -msgstr "错误详情{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:256 +#, fuzzy +#| msgid "构造mydumper正则" +msgid "构造remote mydumper正则" +msgstr "构造mydumper正则" -#: backend/flow/plugins/components/collections/common/sa_idle_check.py:90 -msgid "sa空闲检查" -msgstr "sa空闲检查" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:274 +#, fuzzy +#| msgid "执行库表备份" +msgid "remote 执行库表备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/common/sa_init.py:35 -msgid "SA初始化" -msgstr "SA初始化" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:286 +msgid "remote 备份库表" +msgstr "remote 备份库表" -#: backend/flow/plugins/components/collections/common/sa_init.py:82 -msgid "sa初始化" -msgstr "sa初始化" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:311 +#, fuzzy +#| msgid "运维节点" +msgid "构造运维节点正则" +msgstr "运维节点" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:50 -msgid "定时时间" -msgstr "定时时间" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:329 +#, fuzzy +#| msgid "执行库表备份" +msgid "运维节点执行库表备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:53 -#, python-format -msgid "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" -msgstr "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py:340 +#, fuzzy +#| msgid "库表备份" +msgid "spider_mnt库表备份" +msgstr "库表备份" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:56 -msgid "是否强制晚于当前时间" -msgstr "是否强制晚于当前时间" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:84 +msgid "存入的存储节点数量不是偶数,请检查!" +msgstr "存入的存储节点数量不是偶数,请检查!" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:59 -msgid "" -"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" -msgstr "" -"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:316 +msgid "集群内部节点间授权" +msgstr "集群内部节点间授权" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:83 -#, python-format -msgid "输入参数%s不符合【时区(+08:00、-08:00)】格式" -msgstr "输入参数%s不符合【时区(+08:00、-08:00)】格式" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py:328 +msgid "初始化集群节点间关系" +msgstr "初始化集群节点间关系" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:98 -msgid "定时时间需晚于当前时间" -msgstr "定时时间需晚于当前时间" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:136 +msgid "卸载spider实例" +msgstr "卸载spider实例" -#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:106 -#, python-format -msgid "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" -msgstr "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:150 +msgid "卸载中控实例" +msgstr "卸载中控实例" -#: backend/flow/plugins/components/collections/es/es_dns_manage.py:61 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:37 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:48 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:75 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:57 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:69 -#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:29 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:43 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:78 -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:44 -msgid "该节点获取到执行ip信息为空,请联系系统管理员" -msgstr "该节点获取到执行ip信息为空,请联系系统管理员" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py:193 +msgid "下架TenDB-Cluster集群[{}]" +msgstr "下架TenDB-Cluster集群[{}]" -#: backend/flow/plugins/components/collections/es/es_dns_manage.py:146 -#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:71 -#: backend/flow/plugins/components/collections/kafka/dns_manage.py:93 -#: backend/flow/plugins/components/collections/mysql/dns_manage.py:84 -#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:61 -#: backend/flow/plugins/components/collections/pulsar/pulsar_zk_dns_manage.py:51 -#: backend/flow/plugins/components/collections/redis/dns_manage.py:84 -msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" -msgstr "无法适配到传入的域名处理类型,请联系系统管理员:{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_disable_deploy.py:103 +#, fuzzy +#| msgid "卸载spider实例" +msgid "重启spider实例" +msgstr "卸载spider实例" -#: backend/flow/plugins/components/collections/es/exec_es_actuator_script.py:65 -#: backend/flow/plugins/components/collections/es/trans_files.py:47 -#: backend/flow/plugins/components/collections/hdfs/exec_actuator_script.py:69 -#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:53 -#: backend/flow/plugins/components/collections/influxdb/exec_actuator_script.py:62 -#: backend/flow/plugins/components/collections/kafka/exec_actuator_script.py:62 -#: backend/flow/plugins/components/collections/mysql/exec_actuator_script.py:103 -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:60 -#: backend/flow/plugins/components/collections/pulsar/exec_actuator_script.py:66 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:46 -#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:82 -#: backend/flow/plugins/components/collections/redis/trans_flies.py:61 -msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" -msgstr "该节点获取到执行ip信息为空,请联系系统管理员{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_enable_deploy.py:137 +#, fuzzy +#| msgid "启动MySQL高可用集群[{}]" +msgid "启用spider集群[{}]" +msgstr "启动MySQL高可用集群[{}]" -#: backend/flow/plugins/components/collections/es/get_es_resource.py:57 -#: backend/flow/plugins/components/collections/kafka/get_kafka_resource.py:50 -#: backend/flow/plugins/components/collections/redis/get_redis_resource.py:81 -msgid "获取机器资源成功成功。 {}" -msgstr "获取机器资源成功成功。 {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:128 +#, fuzzy +#| msgid "{} 全库备份" +msgid "{} 全备" +msgstr "{} 全库备份" -#: backend/flow/plugins/components/collections/hdfs/get_hdfs_resource.py:61 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:131 #, fuzzy -#| msgid "获取机器资源成功成功。 {}" -msgid "获取机器资源成功。 {}" -msgstr "获取机器资源成功成功。 {}" +#| msgid "构建全库备份流程成功" +msgid "构造全库备份流程成功" +msgstr "构建全库备份流程成功" -#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:48 -msgid "获取DNS操作IP为空" -msgstr "获取DNS操作IP为空" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:167 +#, fuzzy +#| msgid "执行库表备份" +msgid "spider 执行全库备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/hdfs/update_hdfs_resource.py:67 -msgid "更新机器资源成功成功。 {}" -msgstr "更新机器资源成功成功。 {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:180 +#, fuzzy +#| msgid "执行库表备份" +msgid "ctl 执行全库备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/influxdb/trans_flies.py:52 -#: backend/flow/plugins/components/collections/kafka/trans_flies.py:52 -msgid " 下发介质包参数:{}" -msgstr " 下发介质包参数:{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:238 +#, fuzzy +#| msgid "执行库表备份" +msgid "remote 执行全库备份" +msgstr "执行库表备份" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:64 -msgid "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" -msgstr "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:250 +#, fuzzy +#| msgid "{} 全库备份" +msgid "remote 全库备份" +msgstr "{} 全库备份" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:70 -msgid "" -"授权规则明细:\n" -"{}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:285 +msgid "运维节点执行全库备份" msgstr "" -"授权规则明细:\n" -"{}\n" - -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:83 -msgid "「授权接口返回结果异常」{}" -msgstr "「授权接口返回结果异常」{}" - -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:85 -msgid "「授权接口调用异常」{}" -msgstr "「授权接口调用异常」{}" - -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:88 -msgid "授权异常,相关信息: {}\n" -msgstr "授权异常,相关信息: {}\n" - -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:95 -msgid "授权整体结果{}" -msgstr "授权整体结果{}" - -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:99 -msgid "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" -msgstr "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" -#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:108 -msgid "" -"授权结果详情请下载excel: excel 下载" -msgstr "" -"授权结果详情请下载excel: excel 下载" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py:296 +#, fuzzy +#| msgid "库表备份" +msgid "spider_mnt全库备份" +msgstr "库表备份" -#: backend/flow/plugins/components/collections/mysql/build_database_table_filter_regex.py:47 -msgid "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" -msgstr "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:182 +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:186 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:190 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:194 +msgid "预清理备份库" +msgstr "预清理备份库" -#: backend/flow/plugins/components/collections/mysql/clear_machine.py:45 -msgid "机器还在系统中注册,暂不用清理[{}]" -msgstr "机器还在系统中注册,暂不用清理[{}]" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:240 +msgid "适配备份库映射" +msgstr "适配备份库映射" -#: backend/flow/plugins/components/collections/mysql/clear_machine.py:50 -msgid "本次操作没有机器可以清理,提前结束活动节点" -msgstr "本次操作没有机器可以清理,提前结束活动节点" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:246 +msgid "重建备份库" +msgstr "重建备份库" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:92 -#: backend/flow/plugins/components/collections/mysql/clone_user.py:61 -msgid "「权限克隆返回结果异常」{}" -msgstr "「权限克隆返回结果异常」{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:283 +msgid "{} on remote {} 清档" +msgstr "{} on remote {} 清档" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:94 -#: backend/flow/plugins/components/collections/mysql/clone_user.py:63 -msgid "「权限克隆调用异常」{}" -msgstr "「权限克隆调用异常」{}" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:294 +msgid "处理集群表" +msgstr "处理集群表" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:98 -msgid "权限克隆失败,错误信息: {}\n" -msgstr "权限克隆失败,错误信息: {}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py:311 +#, fuzzy +#| msgid "构建清档流程成功" +msgid "构造清档流程成功" +msgstr "构建清档流程成功" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:105 -msgid "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" -msgstr "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:110 +msgid "partition_sql_file_{}_{}_{}_{}.txt" +msgstr "partition_sql_file_{}_{}_{}_{}.txt" -#: backend/flow/plugins/components/collections/mysql/clone_rules.py:111 -msgid "" -"详情请下载excel: excel 下载" -msgstr "" -"详情请下载excel: excel 下载" +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:113 +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:124 +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:145 +msgid "{}: {}" +msgstr "{}: {}" -#: backend/flow/plugins/components/collections/mysql/clone_user.py:64 -msgid "执行克隆失败!" -msgstr "执行克隆失败!" +#: backend/flow/engine/bamboo/scene/spider/spider_partition.py:167 +#, fuzzy +#| msgid "构建partition流程成功" +msgid "构建spider partition流程成功" +msgstr "构建partition流程成功" -#: backend/flow/plugins/components/collections/mysql/create_user.py:52 -msgid "在「{}」创建临时用户「{}@{}」成功" -msgstr "在「{}」创建临时用户「{}@{}」成功" +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:307 +#, fuzzy +#| msgid "{} 重命名数据库" +msgid "{} on remote {} 重命名数据库" +msgstr "{} 重命名数据库" -#: backend/flow/plugins/components/collections/mysql/create_user.py:54 -msgid "创建用户接口异常,相关信息: {}" -msgstr "创建用户接口异常,相关信息: {}" +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:315 +#, fuzzy +#| msgid "删除集群域名" +msgid "删除集群源库" +msgstr "删除集群域名" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:38 +#: backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py:323 #, fuzzy -#| msgid "在{}执行sql失败,相关信息: {}" -msgid "在「{}」执行sql失败,相关信息: {}" -msgstr "在{}执行sql失败,相关信息: {}" +#| msgid "构建重命名数据库流程成功" +msgid "构造数据库重命名流程成功" +msgstr "构建重命名数据库流程成功" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:42 +#: backend/flow/engine/bamboo/scene/spider/spider_slave_cluster_deploy.py:106 #, fuzzy -#| msgid "在{}执行sql{}失败,相关信息: {}" -msgid "在「{}」执行sql{}失败,相关信息: {}" -msgstr "在{}执行sql{}失败,相关信息: {}" +#| msgid "开始添加slave" +msgid "[{}]添加slave集群" +msgstr "开始添加slave" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:49 -msgid "删除用户接口异常,相关信息: {}" -msgstr "删除用户接口异常,相关信息: {}" +#: backend/flow/engine/exceptions.py:28 +msgid "组件服务未部署" +msgstr "组件服务未部署" -#: backend/flow/plugins/components/collections/mysql/drop_user.py:52 -msgid "在「{}」删除临时用户「{}@{}」成功" -msgstr "在「{}」删除临时用户「{}@{}」成功" +#: backend/flow/engine/exceptions.py:32 +msgid "MySQL备份位置异常" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:58 -msgid "这是一个fake的模拟执行" -msgstr "这是一个fake的模拟执行" +#: backend/flow/engine/exceptions.py:37 +msgid "MySQL备份方式和位置不兼容" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:65 -msgid "语义检查执行成功" -msgstr "语义检查执行成功" +#: backend/flow/engine/exceptions.py:38 +#, python-brace-format +msgid "MySQL备份方式{backup_type}和位置{backup_local}不兼容" +msgstr "" -#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:91 -msgid "[{}] 过滤所得库表: {}" -msgstr "[{}] 过滤所得库表: {}" +#: backend/flow/models.py:22 backend/flow/models.py:38 +msgid "流程ID" +msgstr "流程ID" -#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:94 -msgid "[{}] 未匹配到任何库" -msgstr "[{}] 未匹配到任何库" +#: backend/flow/models.py:23 +msgid "流程树" +msgstr "流程树" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:56 -msgid "在{}执行sql失败,相关信息: {}" -msgstr "在{}执行sql失败,相关信息: {}" +#: backend/flow/models.py:25 backend/ticket/serializers.py:108 +msgid "流程状态" +msgstr "流程状态" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:61 -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:68 -msgid "在{}执行sql{}失败,相关信息: {}" -msgstr "在{}执行sql{}失败,相关信息: {}" +#: backend/flow/models.py:27 +msgid "流程创建人" +msgstr "流程创建人" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:87 -msgid "查询数据库接口异常,相关信息: {}" -msgstr "查询数据库接口异常,相关信息: {}" +#: backend/flow/models.py:28 +msgid "启动时间" +msgstr "启动时间" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:90 -msgid "uid:{}" -msgstr "uid:{}" +#: backend/flow/models.py:29 +msgid "流程结束时间" +msgstr "流程结束时间" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:119 -msgid "ERROR 数据不一致的表的数量: {}" -msgstr "ERROR 数据不一致的表的数量: {}" +#: backend/flow/models.py:40 +msgid "当前版本ID" +msgstr "当前版本ID" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:120 -msgid "WARNING 被跳过校验的表的数量: {}" -msgstr "WARNING 被跳过校验的表的数量: {}" +#: backend/flow/models.py:42 +msgid "节点状态" +msgstr "节点状态" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:121 -msgid "SUCCESS 数据一致的表的数量: {}" -msgstr "SUCCESS 数据一致的表的数量: {}" +#: backend/flow/models.py:44 +msgid "节点运行时IP" +msgstr "节点运行时IP" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:126 -msgid "ERROR 校验失败,数据不一致的表:" -msgstr "ERROR 校验失败,数据不一致的表:" +#: backend/flow/models.py:46 +msgid "开始执行时间" +msgstr "开始执行时间" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:132 -msgid "WARNING 校验程序没有校验的表:" -msgstr "WARNING 校验程序没有校验的表:" +#: backend/flow/plugins/components/collections/cloud/exec_service_script.py:58 +msgid "该节点{}获取到执行ip信息为空,请联系系统管理员" +msgstr "该节点{}获取到执行ip信息为空,请联系系统管理员" -#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:138 -msgid "SUCCESS 校验成功,数据一致的表:" -msgstr "SUCCESS 校验成功,数据一致的表:" +#: backend/flow/plugins/components/collections/cloud/push_config_file.py:56 +#: backend/flow/plugins/components/collections/cloud/trans_files.py:59 +#: backend/flow/plugins/components/collections/es/trans_files.py:63 +#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:70 +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:99 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:85 +#: backend/flow/plugins/components/collections/redis/trans_flies.py:79 +msgid "[{}] 下发介质包参数:{}" +msgstr "[{}] 下发介质包参数:{}" -#: backend/flow/plugins/components/collections/mysql/mysql_db_meta.py:41 -#: backend/flow/plugins/components/collections/redis/get_redis_payload.py:45 -#: backend/flow/plugins/components/collections/redis/redis_db_meta.py:46 -#: backend/flow/plugins/components/collections/spider/spider_db_meta.py:40 -msgid "集群元信息:{}" -msgstr "集群元信息:{}" +#: backend/flow/plugins/components/collections/cloud/trans_files.py:44 +msgid "该节点{}获取到执行ip信息为空,请联系系统管理员{}" +msgstr "该节点{}获取到执行ip信息为空,请联系系统管理员{}" -#: backend/flow/plugins/components/collections/mysql/mysql_ha_db_table_backup_response.py:28 -msgid "[{}] 备份 id: {}" -msgstr "[{}] 备份 id: {}" +#: backend/flow/plugins/components/collections/common/base_service.py:83 +msgid "[{}] 运行成功" +msgstr "[{}] 运行成功" -#: backend/flow/plugins/components/collections/mysql/mysql_master_slave_relationship_check.py:72 -msgid "主备关系校验成功" -msgstr "主备关系校验成功" +#: backend/flow/plugins/components/collections/common/base_service.py:87 +msgid "[{}] 失败: {}" +msgstr "[{}] 失败: {}" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:40 -msgid "分区管理服务api异常,相关信息: {}" -msgstr "分区管理服务api异常,相关信息: {}" +#: backend/flow/plugins/components/collections/common/base_service.py:216 +msgid "[写入上下文结果失败] failed: {}" +msgstr "[写入上下文结果失败] failed: {}" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:45 -#: backend/flow/plugins/components/collections/mysql/upload_file.py:43 -msgid "单据id{}" -msgstr "单据id{}" +#: backend/flow/plugins/components/collections/common/base_service.py:253 +msgid "[{}] 任务正在执行🤔" +msgstr "[{}] 任务正在执行🤔" -#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:46 -msgid "获取分区语句成功" -msgstr "获取分区语句成功" +#: backend/flow/plugins/components/collections/common/base_service.py:262 +msgid "[{}] 任务调度失败😱" +msgstr "[{}] 任务调度失败😱" -#: backend/flow/plugins/components/collections/mysql/rename_database_confirm_empty_from.py:69 -msgid "确认源数据库已空完成" -msgstr "确认源数据库已空完成" +#: backend/flow/plugins/components/collections/common/base_service.py:273 +msgid "[{}]任务调度成功🥳︎" +msgstr "[{}]任务调度成功🥳︎" -#: backend/flow/plugins/components/collections/mysql/rename_database_drop_from.py:51 -msgid "删除源数据库完成" -msgstr "删除源数据库完成" +#: backend/flow/plugins/components/collections/common/base_service.py:279 +msgid "[{}]该节点需要获取执行后日志,赋值到trans_data" +msgstr "[{}]该节点需要获取执行后日志,赋值到trans_data" -#: backend/flow/plugins/components/collections/mysql/rename_database_prepare_param.py:28 -msgid "[{}] 构造 old_new_map 完成: {}" -msgstr "[{}] 构造 old_new_map 完成: {}" +#: backend/flow/plugins/components/collections/common/base_service.py:290 +msgid "[{}] 获取执行后日志失败,获取ip[{}]" +msgstr "[{}] 获取执行后日志失败,获取ip[{}]" -#: backend/flow/plugins/components/collections/mysql/rollback_trans_flies.py:53 -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:63 -msgid "没有符合的备份文件提供定点恢复" -msgstr "没有符合的备份文件提供定点恢复" +#: backend/flow/plugins/components/collections/common/bigdata_manager_service.py:123 +msgid "无法找到Manager处理类型,请联系系统管理员:{}" +msgstr "无法找到Manager处理类型,请联系系统管理员:{}" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:56 -msgid "创建模拟执行任务resp{}" -msgstr "创建模拟执行任务resp{}" +#: backend/flow/plugins/components/collections/common/create_ticket.py:36 +msgid "未知单据类型, {}不存在于已知单据类型中" +msgstr "未知单据类型, {}不存在于已知单据类型中" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:60 -msgid "创建模拟任务失败:{}" -msgstr "创建模拟任务失败:{}" +#: backend/flow/plugins/components/collections/common/create_ticket.py:41 +msgid "不允许自动创建单据,单据创建流程结束" +msgstr "不允许自动创建单据,单据创建流程结束" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:62 -msgid "创建模拟任务成功" -msgstr "创建模拟任务成功" +#: backend/flow/plugins/components/collections/common/external_service.py:36 +msgid "第三方接口: {} 请求成功! 返回参数为: {}" +msgstr "第三方接口: {} 请求成功! 返回参数为: {}" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:66 -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:68 -msgid "「执行语义分析任务异常」{}" -msgstr "「执行语义分析任务异常」{}" +#: backend/flow/plugins/components/collections/common/external_service.py:38 +#, fuzzy +#| msgid "下发文件job启动失败,错误信息: {}" +msgid "第三方接口:{} 调用失败!错误信息为: {}" +msgstr "下发文件job启动失败,错误信息: {}" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:69 -msgid "创建模拟任务失败!" -msgstr "创建模拟任务失败!" +#: backend/flow/plugins/components/collections/common/external_service.py:40 +#, fuzzy +#| msgid "JWT鉴权错误,错误信息: {}" +msgid "请求遇到未知错误!错误信息为: {}" +msgstr "JWT鉴权错误,错误信息: {}" -#: backend/flow/plugins/components/collections/mysql/semantic_check.py:119 -msgid "语义检查出发的自动创建单据" -msgstr "语义检查出发的自动创建单据" +#: backend/flow/plugins/components/collections/common/pause.py:44 +msgid "【{}】自动化流程待确认,是否继续?" +msgstr "【{}】自动化流程待确认,是否继续?" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:42 -msgid "仅在主库查找备份源" -msgstr "仅在主库查找备份源" +#: backend/flow/plugins/components/collections/common/pause.py:78 +msgid "回调数据" +msgstr "回调数据" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:46 -msgid "在主、从库查找备份源" -msgstr "在主、从库查找备份源" +#: backend/flow/plugins/components/collections/common/pause.py:87 +#: backend/ticket/constants.py:315 +msgid "暂停" +msgstr "暂停" -#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:50 -msgid "从备份源中筛选符合的备份" -msgstr "从备份源中筛选符合的备份" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:38 +msgid "{}-空闲检查" +msgstr "{}-空闲检查" -#: backend/flow/plugins/components/collections/mysql/trans_flies.py:66 -#: backend/flow/plugins/components/collections/pulsar/trans_files.py:52 -msgid "" -"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" -"{}" -msgstr "" -"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" -"{}" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:70 +#: backend/flow/plugins/components/collections/common/sa_init.py:66 +msgid "空闲检查失败" +msgstr "空闲检查失败" -#: backend/flow/plugins/components/collections/mysql/truncate_data_create_stage_database.py:55 -msgid "建立备份库完成" -msgstr "建立备份库完成" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:72 +#: backend/flow/plugins/components/collections/common/sa_init.py:68 +msgid "任务状态异常{}" +msgstr "任务状态异常{}" -#: backend/flow/plugins/components/collections/mysql/truncate_data_drop_stage_database.py:49 -msgid "删除备份库完成" -msgstr "删除备份库完成" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:85 +msgid "错误详情{}" +msgstr "错误详情{}" -#: backend/flow/plugins/components/collections/mysql/truncate_data_generate_stage_database_name.py:31 -msgid "生成备份库名完成" -msgstr "生成备份库名完成" +#: backend/flow/plugins/components/collections/common/sa_idle_check.py:90 +msgid "sa空闲检查" +msgstr "sa空闲检查" -#: backend/flow/plugins/components/collections/mysql/truncate_data_recreate_table.py:60 -msgid "重建表成功" -msgstr "重建表成功" +#: backend/flow/plugins/components/collections/common/sa_init.py:35 +msgid "SA初始化" +msgstr "SA初始化" -#: backend/flow/plugins/components/collections/mysql/truncate_data_rename_table.py:88 -msgid "[{}] 备份清档表完成" -msgstr "[{}] 备份清档表完成" +#: backend/flow/plugins/components/collections/common/sa_init.py:82 +msgid "sa初始化" +msgstr "sa初始化" -#: backend/flow/plugins/components/collections/mysql/upload_file.py:38 -msgid "分区sql为空无需上传" -msgstr "分区sql为空无需上传" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:50 +msgid "定时时间" +msgstr "定时时间" -#: backend/flow/plugins/components/collections/mysql/upload_file.py:44 -#, fuzzy -#| msgid "文件上传" -msgid "分区sql文件上传成功" -msgstr "文件上传" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:53 +#, python-format +msgid "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" +msgstr "定时时间,格式为秒(s) 或 (%%Y-%%m-%%d %%H:%%M:%%S)" -#: backend/flow/plugins/components/collections/pulsar/blank_schedule_service.py:66 -msgid "successfully enter blank schedule, interval times: {}" -msgstr "successfully enter blank schedule, interval times: {}" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:56 +msgid "是否强制晚于当前时间" +msgstr "是否强制晚于当前时间" -#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:100 -msgid "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" -msgstr "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:59 +msgid "" +"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" +msgstr "" +"用户输入日期格式时是否强制要求时间晚于当前时间,只对日期格式定时输入有效" -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:113 -msgid "无符合要求机器" -msgstr "无符合要求机器" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:83 +#, python-format +msgid "输入参数%s不符合【时区(+08:00、-08:00)】格式" +msgstr "输入参数%s不符合【时区(+08:00、-08:00)】格式" -#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:117 -msgid "获取最大磁盘空闲机器失败:{}" -msgstr "获取最大磁盘空闲机器失败:{}" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:98 +msgid "定时时间需晚于当前时间" +msgstr "定时时间需晚于当前时间" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:393 -msgid "源redis集群{}存在{}个非running状态的slave" -msgstr "源redis集群{}存在{}个非running状态的slave" +#: backend/flow/plugins/components/collections/common/sleep_timer_service.py:106 +#, python-format +msgid "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" +msgstr "输入参数%s不符合【秒(s) 或 时间(%%Y-%%m-%%d %%H:%%M:%%S)】格式" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:450 -msgid "所有源redis slave机器:{} 磁盘空间检查通过" -msgstr "所有源redis slave机器:{} 磁盘空间检查通过" +#: backend/flow/plugins/components/collections/es/es_dns_manage.py:61 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:37 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:48 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:75 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:57 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:69 +#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:29 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:43 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:78 +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:44 +msgid "该节点获取到执行ip信息为空,请联系系统管理员" +msgstr "该节点获取到执行ip信息为空,请联系系统管理员" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:461 -msgid "src_cluster:{} type:{} 无需检查cluster nodes是否ok" -msgstr "src_cluster:{} type:{} 无需检查cluster nodes是否ok" +#: backend/flow/plugins/components/collections/es/es_dns_manage.py:146 +#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:71 +#: backend/flow/plugins/components/collections/kafka/dns_manage.py:93 +#: backend/flow/plugins/components/collections/mysql/dns_manage.py:84 +#: backend/flow/plugins/components/collections/pulsar/pulsar_dns_manage.py:61 +#: backend/flow/plugins/components/collections/pulsar/pulsar_zk_dns_manage.py:51 +#: backend/flow/plugins/components/collections/redis/dns_manage.py:84 +msgid "无法适配到传入的域名处理类型,请联系系统管理员:{}" +msgstr "无法适配到传入的域名处理类型,请联系系统管理员:{}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:523 -msgid "src_cluster:{} 类型是:{} 无需检查cluster state" -msgstr "src_cluster:{} 类型是:{} 无需检查cluster state" +#: backend/flow/plugins/components/collections/es/exec_es_actuator_script.py:65 +#: backend/flow/plugins/components/collections/es/trans_files.py:47 +#: backend/flow/plugins/components/collections/hdfs/exec_actuator_script.py:69 +#: backend/flow/plugins/components/collections/hdfs/trans_flies.py:53 +#: backend/flow/plugins/components/collections/influxdb/exec_actuator_script.py:62 +#: backend/flow/plugins/components/collections/kafka/exec_actuator_script.py:62 +#: backend/flow/plugins/components/collections/mysql/exec_actuator_script.py:103 +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:60 +#: backend/flow/plugins/components/collections/pulsar/exec_actuator_script.py:66 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:46 +#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:82 +#: backend/flow/plugins/components/collections/redis/trans_flies.py:61 +msgid "该节点获取到执行ip信息为空,请联系系统管理员{}" +msgstr "该节点获取到执行ip信息为空,请联系系统管理员{}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:696 -msgid "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" +#: backend/flow/plugins/components/collections/es/get_es_resource.py:57 +#: backend/flow/plugins/components/collections/kafka/get_kafka_resource.py:50 +msgid "获取机器资源成功成功。 {}" +msgstr "获取机器资源成功成功。 {}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:705 -msgid "" -"bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" +#: backend/flow/plugins/components/collections/hdfs/get_hdfs_resource.py:61 +#, fuzzy +#| msgid "获取机器资源成功成功。 {}" +msgid "获取机器资源成功。 {}" +msgstr "获取机器资源成功成功。 {}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:715 -msgid "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" -msgstr "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" +#: backend/flow/plugins/components/collections/hdfs/hdfs_dns_manage.py:48 +msgid "获取DNS操作IP为空" +msgstr "获取DNS操作IP为空" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:798 -msgid "task:{} {}:{} 迁移失败" -msgstr "task:{} {}:{} 迁移失败" +#: backend/flow/plugins/components/collections/hdfs/update_hdfs_resource.py:67 +msgid "更新机器资源成功成功。 {}" +msgstr "更新机器资源成功成功。 {}" -#: backend/flow/plugins/components/collections/redis/redis_dts.py:863 -msgid "{}中有{}个proxy不是running状态" -msgstr "{}中有{}个proxy不是running状态" +#: backend/flow/plugins/components/collections/influxdb/trans_flies.py:52 +#: backend/flow/plugins/components/collections/kafka/trans_flies.py:52 +msgid " 下发介质包参数:{}" +msgstr " 下发介质包参数:{}" -#: backend/flow/plugins/components/collections/redis/trans_flies.py:87 -#, fuzzy -#| msgid "下发介质包失败:resp: {}" -msgid "下发介质包失败: [{}/{}] resp:{}" -msgstr "下发介质包失败:resp: {}" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:64 +msgid "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" +msgstr "{}. 账号规则: {}-{}, 来源ip: {}, 目标集群: {}" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:70 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:80 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:91 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:112 -msgid "在[{}]创建添加内置账号成功" -msgstr "在[{}]创建添加内置账号成功" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:70 +msgid "" +"授权规则明细:\n" +"{}\n" +msgstr "" +"授权规则明细:\n" +"{}\n" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:72 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:82 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:93 -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:114 -msgid "[{}]添加用户接口异常,相关信息: {}" -msgstr "[{}]添加用户接口异常,相关信息: {}" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:83 +msgid "「授权接口返回结果异常」{}" +msgstr "「授权接口返回结果异常」{}" -#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:118 -msgid "[{}]根据单据类型活动节点找不到对应的授权方式。" -msgstr "[{}]根据单据类型活动节点找不到对应的授权方式。" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:85 +msgid "「授权接口调用异常」{}" +msgstr "「授权接口调用异常」{}" -#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:45 -#, fuzzy -#| msgid "检查源数据库是否在用" -msgid "{} {} 检查库表是否在用" -msgstr "检查源数据库是否在用" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:88 +msgid "授权异常,相关信息: {}\n" +msgstr "授权异常,相关信息: {}\n" -#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:50 -#, fuzzy -#| msgid "检查源数据库是否在用" -msgid "{} 检查库表是否在用" -msgstr "检查源数据库是否在用" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:95 +msgid "授权整体结果{}" +msgstr "授权整体结果{}" -#: backend/flow/plugins/components/collections/spider/clear_database_on_remote_service.py:56 -msgid "remote drop 新库完成" -msgstr "remote drop 新库完成" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:99 +msgid "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" +msgstr "Excel导入授权行数:{},成功授权数目:{},失败授权数目:{}" -#: backend/flow/plugins/components/collections/spider/create_database_like_via_ctl.py:110 -msgid "建立集群备份库表完成" -msgstr "建立集群备份库表完成" +#: backend/flow/plugins/components/collections/mysql/authorize_rules.py:108 +msgid "" +"授权结果详情请下载excel: excel 下载" +msgstr "" +"授权结果详情请下载excel: excel 下载" -#: backend/flow/plugins/components/collections/spider/drop_spider_table_via_ctl.py:49 -#, fuzzy -#| msgid "删除源数据库完成" -msgid "删除老数据库完成" -msgstr "删除源数据库完成" +#: backend/flow/plugins/components/collections/mysql/build_database_table_filter_regex.py:47 +msgid "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" +msgstr "[{}] 成功: db_table_filter_regex: {}, db_filter_regex: {}" -#: backend/flow/plugins/components/collections/spider/truncate_database_drop_stage_db_via_ctl.py:47 -#, fuzzy -#| msgid "建立备份库完成" -msgid "清理备份库完成" -msgstr "建立备份库完成" +#: backend/flow/plugins/components/collections/mysql/clear_machine.py:45 +msgid "机器还在系统中注册,暂不用清理[{}]" +msgstr "机器还在系统中注册,暂不用清理[{}]" -#: backend/flow/plugins/components/collections/spider/truncate_database_on_spider_via_ctl.py:145 -msgid "处理集群表完成" -msgstr "处理集群表完成" +#: backend/flow/plugins/components/collections/mysql/clear_machine.py:50 +msgid "本次操作没有机器可以清理,提前结束活动节点" +msgstr "本次操作没有机器可以清理,提前结束活动节点" -#: backend/flow/signal/handlers.py:35 -msgid "【状态信号捕获】{} root_id={}, node_id={}, status:{}" -msgstr "【状态信号捕获】{} root_id={}, node_id={}, status:{}" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:92 +#: backend/flow/plugins/components/collections/mysql/clone_user.py:61 +msgid "「权限克隆返回结果异常」{}" +msgstr "「权限克隆返回结果异常」{}" -#: backend/flow/signal/handlers.py:68 -msgid "【状态信号捕获】未查找到FlowTree root_id={}" -msgstr "【状态信号捕获】未查找到FlowTree root_id={}" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:94 +#: backend/flow/plugins/components/collections/mysql/clone_user.py:63 +msgid "「权限克隆调用异常」{}" +msgstr "「权限克隆调用异常」{}" -#: backend/flow/utils/cc_manage.py:55 -msgid "查询主机bk_host_id失败[数量不匹配]" -msgstr "查询主机bk_host_id失败[数量不匹配]" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:98 +msgid "权限克隆失败,错误信息: {}\n" +msgstr "权限克隆失败,错误信息: {}\n" -#: backend/flow/utils/cc_manage.py:67 -msgid "查询空闲机模块ID bk_module_id 失败" -msgstr "查询空闲机模块ID bk_module_id 失败" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:105 +msgid "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" +msgstr "权限克隆整体执行结果——总数:{},成功数:{},失败数:{}\n" -#: backend/flow/utils/cloud/cloud_act_payload.py:42 -msgid "单据中不包含DRS的部署信息" -msgstr "单据中不包含DRS的部署信息" +#: backend/flow/plugins/components/collections/mysql/clone_rules.py:111 +msgid "" +"详情请下载excel: excel 下载" +msgstr "" +"详情请下载excel: excel 下载" -#: backend/flow/utils/cloud/cloud_act_payload.py:50 -msgid "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" -msgstr "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" +#: backend/flow/plugins/components/collections/mysql/clone_user.py:64 +msgid "执行克隆失败!" +msgstr "执行克隆失败!" -#: backend/flow/utils/cloud/cloud_act_payload.py:58 -msgid "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" -msgstr "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" +#: backend/flow/plugins/components/collections/mysql/create_user.py:52 +msgid "在「{}」创建临时用户「{}@{}」成功" +msgstr "在「{}」创建临时用户「{}@{}」成功" -#: backend/flow/utils/cloud/cloud_db_proxy.py:52 -msgid "找不到单据类型需要变更的proxy函数,服务信息入库失败" -msgstr "找不到单据类型需要变更的proxy函数,服务信息入库失败" +#: backend/flow/plugins/components/collections/mysql/create_user.py:54 +msgid "创建用户接口异常,相关信息: {}" +msgstr "创建用户接口异常,相关信息: {}" -#: backend/flow/utils/cloud/cloud_module_operate.py:135 +#: backend/flow/plugins/components/collections/mysql/drop_user.py:38 #, fuzzy -#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" -msgid "主机{}转移{}失败,转移参数:{}, 错误信息:{}" -msgstr "主机{}转移失败,转移参数:{}, 错误信息:{}" +#| msgid "在{}执行sql失败,相关信息: {}" +msgid "在「{}」执行sql失败,相关信息: {}" +msgstr "在{}执行sql失败,相关信息: {}" -#: backend/flow/utils/cloud/cloud_module_operate.py:196 +#: backend/flow/plugins/components/collections/mysql/drop_user.py:42 #, fuzzy -#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" -msgid "主机{}转移待回收失败,错误信息:{}" -msgstr "主机{}转移失败,转移参数:{}, 错误信息:{}" +#| msgid "在{}执行sql{}失败,相关信息: {}" +msgid "在「{}」执行sql{}失败,相关信息: {}" +msgstr "在{}执行sql{}失败,相关信息: {}" -#: backend/flow/utils/es/es_db_meta.py:94 -msgid "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" -msgstr "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" +#: backend/flow/plugins/components/collections/mysql/drop_user.py:49 +msgid "删除用户接口异常,相关信息: {}" +msgstr "删除用户接口异常,相关信息: {}" -#: backend/flow/utils/hdfs/hdfs_db_meta.py:52 -#: backend/flow/utils/influxdb/influxdb_db_meta.py:114 -#: backend/flow/utils/kafka/kafka_db_meta.py:160 -#: backend/flow/utils/redis/redis_db_meta.py:49 -msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" -msgstr "找不到单据类型需要变更的cmdb函数,请联系系统管理员" +#: backend/flow/plugins/components/collections/mysql/drop_user.py:52 +msgid "在「{}」删除临时用户「{}@{}」成功" +msgstr "在「{}」删除临时用户「{}@{}」成功" -#: backend/flow/utils/mysql/db_resource.py:106 -#: backend/flow/utils/redis/db_resource.py:106 -msgid " 获取资源失败: {}" -msgstr " 获取资源失败: {}" +#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:58 +msgid "这是一个fake的模拟执行" +msgstr "这是一个fake的模拟执行" -#: backend/flow/utils/mysql/db_table_filter/exception.py:18 -msgid "库表过滤异常" -msgstr "库表过滤异常" +#: backend/flow/plugins/components/collections/mysql/fake_semantic_check.py:65 +msgid "语义检查执行成功" +msgstr "语义检查执行成功" -#: backend/flow/utils/mysql/db_table_filter/exception.py:23 -msgid "输入校验异常" -msgstr "输入校验异常" +#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:91 +msgid "[{}] 过滤所得库表: {}" +msgstr "[{}] 过滤所得库表: {}" -#: backend/flow/utils/mysql/db_table_filter/filter.py:42 -msgid "include patterns 不能为空" -msgstr "include patterns 不能为空" +#: backend/flow/plugins/components/collections/mysql/filter_database_table_from_regex.py:94 +msgid "[{}] 未匹配到任何库" +msgstr "[{}] 未匹配到任何库" -#: backend/flow/utils/mysql/db_table_filter/filter.py:48 -msgid "exclude patterns 要么同时为空, 要么都不为空" -msgstr "exclude patterns 要么同时为空, 要么都不为空" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:56 +msgid "在{}执行sql失败,相关信息: {}" +msgstr "在{}执行sql失败,相关信息: {}" -#: backend/flow/utils/mysql/db_table_filter/tools.py:30 -msgid "使用通配符时, 只能有一个模式: {}" -msgstr "使用通配符时, 只能有一个模式: {}" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:61 +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:68 +msgid "在{}执行sql{}失败,相关信息: {}" +msgstr "在{}执行sql{}失败,相关信息: {}" -#: backend/flow/utils/mysql/db_table_filter/tools.py:33 -msgid "% ? 不能独立使用" -msgstr "% ? 不能独立使用" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:87 +msgid "查询数据库接口异常,相关信息: {}" +msgstr "查询数据库接口异常,相关信息: {}" -#: backend/flow/utils/mysql/db_table_filter/tools.py:36 -msgid "* 只能独立使用" -msgstr "* 只能独立使用" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:90 +msgid "uid:{}" +msgstr "uid:{}" -#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:27 -msgid "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" -msgstr "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:119 +msgid "ERROR 数据不一致的表的数量: {}" +msgstr "ERROR 数据不一致的表的数量: {}" -#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:29 -msgid "exec_ip变量和get_trans_data_ip_var变量不能同时为None" -msgstr "exec_ip变量和get_trans_data_ip_var变量不能同时为None" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:120 +msgid "WARNING 被跳过校验的表的数量: {}" +msgstr "WARNING 被跳过校验的表的数量: {}" -#: backend/flow/utils/mysql/mysql_act_playload.py:337 -msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" -msgstr "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:121 +msgid "SUCCESS 数据一致的表的数量: {}" +msgstr "SUCCESS 数据一致的表的数量: {}" -#: backend/flow/utils/mysql/mysql_act_playload.py:381 -msgid "传入的安装spider端口列表为空或者非法值,请联系系统管理员" -msgstr "传入的安装spider端口列表为空或者非法值,请联系系统管理员" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:126 +msgid "ERROR 校验失败,数据不一致的表:" +msgstr "ERROR 校验失败,数据不一致的表:" -#: backend/flow/utils/pulsar/consts.py:20 -msgid "broker默认分区数" -msgstr "broker默认分区数" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:132 +msgid "WARNING 校验程序没有校验的表:" +msgstr "WARNING 校验程序没有校验的表:" -#: backend/flow/utils/pulsar/consts.py:21 -msgid "broker认证配置" -msgstr "broker认证配置" +#: backend/flow/plugins/components/collections/mysql/mysql_checksum_report.py:138 +msgid "SUCCESS 校验成功,数据一致的表:" +msgstr "SUCCESS 校验成功,数据一致的表:" -#: backend/flow/utils/pulsar/consts.py:22 -msgid "默认bookie池大小" -msgstr "默认bookie池大小" +#: backend/flow/plugins/components/collections/mysql/mysql_db_meta.py:41 +#: backend/flow/plugins/components/collections/redis/get_redis_payload.py:45 +#: backend/flow/plugins/components/collections/redis/redis_db_meta.py:45 +#: backend/flow/plugins/components/collections/spider/spider_db_meta.py:40 +msgid "集群元信息:{}" +msgstr "集群元信息:{}" -#: backend/flow/utils/pulsar/consts.py:23 -msgid "写入副本数" -msgstr "写入副本数" +#: backend/flow/plugins/components/collections/mysql/mysql_link_backup_id_bill_id.py:28 +msgid "[{}] 备份 id: {}" +msgstr "[{}] 备份 id: {}" -#: backend/flow/utils/pulsar/consts.py:24 -msgid "确认写入副本数" -msgstr "确认写入副本数" +#: backend/flow/plugins/components/collections/mysql/mysql_master_slave_relationship_check.py:72 +msgid "主备关系校验成功" +msgstr "主备关系校验成功" -#: backend/flow/utils/pulsar/consts.py:25 -msgid "数据保留时间,单位为分钟" -msgstr "数据保留时间,单位为分钟" +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:40 +msgid "分区管理服务api异常,相关信息: {}" +msgstr "分区管理服务api异常,相关信息: {}" -#: backend/flow/utils/pulsar/consts.py:26 -msgid "broker服务端口" -msgstr "broker服务端口" +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:45 +#: backend/flow/plugins/components/collections/mysql/upload_file.py:43 +msgid "单据id{}" +msgstr "单据id{}" + +#: backend/flow/plugins/components/collections/mysql/mysql_partition_check.py:46 +msgid "获取分区语句成功" +msgstr "获取分区语句成功" + +#: backend/flow/plugins/components/collections/mysql/rename_database_confirm_empty_from.py:69 +msgid "确认源数据库已空完成" +msgstr "确认源数据库已空完成" + +#: backend/flow/plugins/components/collections/mysql/rename_database_drop_from.py:51 +msgid "删除源数据库完成" +msgstr "删除源数据库完成" -#: backend/flow/utils/pulsar/consts.py:27 -msgid "访问Pulsar Manager账户名" -msgstr "访问Pulsar Manager账户名" +#: backend/flow/plugins/components/collections/mysql/rename_database_prepare_param.py:28 +msgid "[{}] 构造 old_new_map 完成: {}" +msgstr "[{}] 构造 old_new_map 完成: {}" -#: backend/flow/utils/pulsar/consts.py:28 -msgid "访问Pulsar Manager密码" -msgstr "访问Pulsar Manager密码" +#: backend/flow/plugins/components/collections/mysql/rollback_trans_flies.py:53 +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:63 +msgid "没有符合的备份文件提供定点恢复" +msgstr "没有符合的备份文件提供定点恢复" -#: backend/flow/utils/redis/redis_db_meta.py:57 -msgid "找不到单据类型需要查询的cmdb函数,请联系系统管理员" -msgstr "找不到单据类型需要查询的cmdb函数,请联系系统管理员" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:56 +msgid "创建模拟执行任务resp{}" +msgstr "创建模拟执行任务resp{}" -#: backend/flow/views/cloud_dbha_apply.py:39 -#: backend/flow/views/cloud_dns_bind_apply.py:39 -msgid "开始部署dns-bind服务场景" -msgstr "开始部署dns-bind服务场景" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:60 +msgid "创建模拟任务失败:{}" +msgstr "创建模拟任务失败:{}" -#: backend/flow/views/cloud_drs_apply.py:44 -msgid "开始部署drs服务场景" -msgstr "开始部署drs服务场景" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:62 +msgid "创建模拟任务成功" +msgstr "创建模拟任务成功" -#: backend/flow/views/cloud_nginx_apply.py:44 -msgid "开始部署nginx服务场景" -msgstr "开始部署nginx服务场景" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:66 +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:68 +msgid "「执行语义分析任务异常」{}" +msgstr "「执行语义分析任务异常」{}" -#: backend/flow/views/cloud_nginx_apply.py:54 -#, fuzzy -#| msgid "开始部署nginx服务场景" -msgid "开始替换nginx服务场景" -msgstr "开始部署nginx服务场景" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:69 +msgid "创建模拟任务失败!" +msgstr "创建模拟任务失败!" -#: backend/flow/views/es_apply.py:63 -msgid "开始部署ES场景" -msgstr "开始部署ES场景" +#: backend/flow/plugins/components/collections/mysql/semantic_check.py:119 +msgid "语义检查出发的自动创建单据" +msgstr "语义检查出发的自动创建单据" -#: backend/flow/views/es_destroy.py:39 -msgid "开始下架ES场景" -msgstr "开始下架ES场景" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:42 +msgid "仅在主库查找备份源" +msgstr "仅在主库查找备份源" -#: backend/flow/views/es_disable.py:39 -msgid "开始禁用ES场景" -msgstr "开始禁用ES场景" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:46 +msgid "在主、从库查找备份源" +msgstr "在主、从库查找备份源" -#: backend/flow/views/es_enable.py:39 -msgid "开始启用ES场景" -msgstr "开始启用ES场景" +#: backend/flow/plugins/components/collections/mysql/slave_trans_flies.py:50 +msgid "从备份源中筛选符合的备份" +msgstr "从备份源中筛选符合的备份" -#: backend/flow/views/es_reboot.py:47 -msgid "开始重启ES节点场景" -msgstr "开始重启ES节点场景" +#: backend/flow/plugins/components/collections/mysql/trans_flies.py:66 +#: backend/flow/plugins/components/collections/pulsar/trans_files.py:52 +msgid "" +"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" +"{}" +msgstr "" +"选择服务器之间文件传输模式,应当源文件的机器ip列表不能为空,请联系系统管理员" +"{}" -#: backend/flow/views/es_replace.py:63 backend/flow/views/es_scale_up.py:52 -msgid "开始扩容ES场景" -msgstr "开始扩容ES场景" +#: backend/flow/plugins/components/collections/mysql/truncate_data_create_stage_database.py:55 +msgid "建立备份库完成" +msgstr "建立备份库完成" -#: backend/flow/views/es_shrink.py:52 -msgid "开始缩容ES场景" -msgstr "开始缩容ES场景" +#: backend/flow/plugins/components/collections/mysql/truncate_data_drop_stage_database.py:49 +msgid "删除备份库完成" +msgstr "删除备份库完成" -#: backend/flow/views/hdfs_apply.py:61 -msgid "开始部署HDFS场景" -msgstr "开始部署HDFS场景" +#: backend/flow/plugins/components/collections/mysql/truncate_data_generate_stage_database_name.py:31 +msgid "生成备份库名完成" +msgstr "生成备份库名完成" -#: backend/flow/views/hdfs_destroy.py:39 -msgid "开始HDFS集群销毁场景" -msgstr "开始HDFS集群销毁场景" +#: backend/flow/plugins/components/collections/mysql/truncate_data_recreate_table.py:60 +msgid "重建表成功" +msgstr "重建表成功" -#: backend/flow/views/hdfs_disable.py:39 -msgid "开始HDFS集群禁用场景" -msgstr "开始HDFS集群禁用场景" +#: backend/flow/plugins/components/collections/mysql/truncate_data_rename_table.py:88 +msgid "[{}] 备份清档表完成" +msgstr "[{}] 备份清档表完成" -#: backend/flow/views/hdfs_enable.py:39 -msgid "开始HDFS集群启用场景" -msgstr "开始HDFS集群启用场景" +#: backend/flow/plugins/components/collections/mysql/upload_file.py:38 +msgid "分区sql为空无需上传" +msgstr "分区sql为空无需上传" -#: backend/flow/views/hdfs_reboot.py:55 -msgid "开始重启HDFS场景" -msgstr "开始重启HDFS场景" +#: backend/flow/plugins/components/collections/mysql/upload_file.py:44 +#, fuzzy +#| msgid "文件上传" +msgid "分区sql文件上传成功" +msgstr "文件上传" -#: backend/flow/views/hdfs_replace.py:65 -msgid "开始替换HDFS场景" -msgstr "开始替换HDFS场景" +#: backend/flow/plugins/components/collections/pulsar/blank_schedule_service.py:66 +msgid "successfully enter blank schedule, interval times: {}" +msgstr "successfully enter blank schedule, interval times: {}" -#: backend/flow/views/hdfs_scale_up.py:42 -msgid "开始扩容HDFS场景" -msgstr "开始扩容HDFS场景" +#: backend/flow/plugins/components/collections/redis/exec_actuator_script.py:100 +msgid "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" +msgstr "[{}] kwargs['payload'] 是不完整,需要将{}内容加到payload中" -#: backend/flow/views/hdfs_shrink.py:42 -msgid "开始HDFS集群缩容场景" -msgstr "开始HDFS集群缩容场景" +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:113 +msgid "无符合要求机器" +msgstr "无符合要求机器" -#: backend/flow/views/influxdb_apply.py:57 -msgid "开始部署influxdb场景" -msgstr "开始部署influxdb场景" +#: backend/flow/plugins/components/collections/redis/exec_shell_script.py:117 +msgid "获取最大磁盘空闲机器失败:{}" +msgstr "获取最大磁盘空闲机器失败:{}" -#: backend/flow/views/influxdb_destroy.py:39 -msgid "开始下架Influxdb场景" -msgstr "开始下架Influxdb场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:393 +msgid "源redis集群{}存在{}个非running状态的slave" +msgstr "源redis集群{}存在{}个非running状态的slave" -#: backend/flow/views/influxdb_disable.py:39 -msgid "开始禁用Influxdb场景" -msgstr "开始禁用Influxdb场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:450 +msgid "所有源redis slave机器:{} 磁盘空间检查通过" +msgstr "所有源redis slave机器:{} 磁盘空间检查通过" -#: backend/flow/views/influxdb_enable.py:39 -msgid "开始启用Influxdb场景" -msgstr "开始启用Influxdb场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:461 +msgid "src_cluster:{} type:{} 无需检查cluster nodes是否ok" +msgstr "src_cluster:{} type:{} 无需检查cluster nodes是否ok" -#: backend/flow/views/influxdb_reboot.py:47 -msgid "开始重启Influxdb节点场景" -msgstr "开始重启Influxdb节点场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:523 +msgid "src_cluster:{} 类型是:{} 无需检查cluster state" +msgstr "src_cluster:{} 类型是:{} 无需检查cluster state" -#: backend/flow/views/influxdb_replace.py:49 -#, fuzzy -#| msgid "开始替换kafka场景" -msgid "开始替换influxdb场景" -msgstr "开始替换kafka场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:696 +msgid "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" +msgstr "bill_id:{} src_cluster:{} dst_cluster:{} 某些tasks迁移失败" -#: backend/flow/views/kafka_apply.py:70 -msgid "开始部署kafka场景" -msgstr "开始部署kafka场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:705 +msgid "" +"bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" +msgstr "" +"bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都成功且终止了迁移进程" -#: backend/flow/views/kafka_destroy.py:39 -msgid "开始下架Kafka场景" -msgstr "开始下架Kafka场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:715 +msgid "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" +msgstr "bill_id:{} src_cluster:{} dst_cluster:{} 所有tasks都是增量同步" -#: backend/flow/views/kafka_disable.py:39 -msgid "开始禁用Kafka场景" -msgstr "开始禁用Kafka场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:797 +msgid "task:{} {}:{} 迁移失败" +msgstr "task:{} {}:{} 迁移失败" -#: backend/flow/views/kafka_enable.py:39 -msgid "开始启用Kafka场景" -msgstr "开始启用Kafka场景" +#: backend/flow/plugins/components/collections/redis/redis_dts.py:862 +msgid "{}中有{}个proxy不是running状态" +msgstr "{}中有{}个proxy不是running状态" -#: backend/flow/views/kafka_reboot.py:47 -msgid "开始重启Kafka节点场景" -msgstr "开始重启Kafka节点场景" +#: backend/flow/plugins/components/collections/redis/trans_flies.py:87 +#, fuzzy +#| msgid "下发介质包失败:resp: {}" +msgid "下发介质包失败: [{}/{}] resp:{}" +msgstr "下发介质包失败:resp: {}" -#: backend/flow/views/kafka_replace.py:51 -msgid "开始替换kafka场景" -msgstr "开始替换kafka场景" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:60 +msgid "select mysql.servers failed: {}" +msgstr "" -#: backend/flow/views/kafka_scale_up.py:49 -msgid "开始扩容kafka场景" -msgstr "开始扩容kafka场景" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:94 +msgid "TdbCtl-create-node failed: {}" +msgstr "" -#: backend/flow/views/kafka_shrink.py:44 -msgid "开始缩容kafka场景" -msgstr "开始缩容kafka场景" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:142 +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:148 +#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:23 +msgid "在[{}]创建添加内置账号成功" +msgstr "在[{}]创建添加内置账号成功" -#: backend/flow/views/mysql_add_slave.py:44 -msgid "开始添加slave" -msgstr "开始添加slave" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:151 +#: backend/flow/plugins/components/collections/spider/add_system_user_in_cluster.py:25 +msgid "[{}]添加用户接口异常,相关信息: {}" +msgstr "[{}]添加用户接口异常,相关信息: {}" -#: backend/flow/views/mysql_edit_config.py:60 -msgid "开始下发修改的参数" -msgstr "开始下发修改的参数" +#: backend/flow/plugins/components/collections/spider/add_spider_routing.py:186 +msgid "This spider-role is not supported,check" +msgstr "" -#: backend/flow/views/mysql_flashback.py:49 -msgid "开始flashback" -msgstr "开始flashback" +#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:45 +#, fuzzy +#| msgid "检查源数据库是否在用" +msgid "{} {} 检查库表是否在用" +msgstr "检查源数据库是否在用" -#: backend/flow/views/mysql_ha_db_table_backup.py:32 -msgid "开始库表备份场景" -msgstr "开始库表备份场景" +#: backend/flow/plugins/components/collections/spider/check_cluster_table_using_sub.py:50 +#, fuzzy +#| msgid "检查源数据库是否在用" +msgid "{} 检查库表是否在用" +msgstr "检查源数据库是否在用" + +#: backend/flow/plugins/components/collections/spider/clear_database_on_remote_service.py:56 +msgid "remote drop 新库完成" +msgstr "remote drop 新库完成" -#: backend/flow/views/mysql_ha_destroy.py:31 -msgid "开始回收mysql主从版场景" -msgstr "开始回收mysql主从版场景" +#: backend/flow/plugins/components/collections/spider/create_database_like_via_ctl.py:110 +msgid "建立集群备份库表完成" +msgstr "建立集群备份库表完成" -#: backend/flow/views/mysql_ha_destroy.py:49 -msgid "开始禁用mysql主从版场景" -msgstr "开始禁用mysql主从版场景" +#: backend/flow/plugins/components/collections/spider/drop_spider_table_via_ctl.py:49 +#, fuzzy +#| msgid "删除源数据库完成" +msgid "删除老数据库完成" +msgstr "删除源数据库完成" -#: backend/flow/views/mysql_ha_destroy.py:65 -msgid "开始启动mysql主从版场景" -msgstr "开始启动mysql主从版场景" +#: backend/flow/plugins/components/collections/spider/truncate_database_drop_stage_db_via_ctl.py:47 +#, fuzzy +#| msgid "建立备份库完成" +msgid "清理备份库完成" +msgstr "建立备份库完成" -#: backend/flow/views/mysql_ha_full_backup.py:32 -msgid "开始全库备份场景" -msgstr "开始全库备份场景" +#: backend/flow/plugins/components/collections/spider/truncate_database_on_spider_via_ctl.py:145 +msgid "处理集群表完成" +msgstr "处理集群表完成" -#: backend/flow/views/mysql_ha_master_fail_over.py:30 -msgid "开始执行主故障切换[整机切换]的任务" -msgstr "开始执行主故障切换[整机切换]的任务" +#: backend/flow/signal/handlers.py:35 +msgid "【状态信号捕获】{} root_id={}, node_id={}, status:{}" +msgstr "【状态信号捕获】{} root_id={}, node_id={}, status:{}" -#: backend/flow/views/mysql_ha_rename_database.py:30 -#: backend/flow/views/mysql_ha_truncate_data.py:30 -msgid "开始TenDBHA清档场景" -msgstr "开始TenDBHA清档场景" +#: backend/flow/signal/handlers.py:68 +msgid "【状态信号捕获】未查找到FlowTree root_id={}" +msgstr "【状态信号捕获】未查找到FlowTree root_id={}" -#: backend/flow/views/mysql_ha_switch.py:30 -msgid "开始执行主从切换[整机切换]的任务" -msgstr "开始执行主从切换[整机切换]的任务" +#: backend/flow/utils/cc_manage.py:55 +msgid "查询主机bk_host_id失败[数量不匹配]" +msgstr "查询主机bk_host_id失败[数量不匹配]" -#: backend/flow/views/mysql_migrate_cluster.py:46 -#: backend/flow/views/mysql_restore_slave.py:49 -msgid "开始重建slave" -msgstr "开始重建slave" +#: backend/flow/utils/cc_manage.py:67 +msgid "查询空闲机模块ID bk_module_id 失败" +msgstr "查询空闲机模块ID bk_module_id 失败" -#: backend/flow/views/mysql_proxy_add.py:30 -msgid "开始添加mysql_proxy实例场景" -msgstr "开始添加mysql_proxy实例场景" +#: backend/flow/utils/cloud/cloud_act_payload.py:42 +msgid "单据中不包含DRS的部署信息" +msgstr "单据中不包含DRS的部署信息" -#: backend/flow/views/mysql_proxy_reduce.py:30 -msgid "开始回收mysql_proxy实例场景" -msgstr "开始回收mysql_proxy实例场景" +#: backend/flow/utils/cloud/cloud_act_payload.py:50 +msgid "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" +msgstr "DNS服务未部署,请在DNS服务部署后再进行该服务的部署" -#: backend/flow/views/mysql_proxy_switch.py:30 -msgid "开始替换mysql_proxy实例场景" -msgstr "开始替换mysql_proxy实例场景" +#: backend/flow/utils/cloud/cloud_act_payload.py:58 +msgid "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" +msgstr "Nginx服务未部署,请在Nginx服务部署后再进行该服务的部署" -#: backend/flow/views/mysql_pt_table_sync.py:30 -msgid "开始执行数据修复" -msgstr "开始执行数据修复" +#: backend/flow/utils/cloud/cloud_db_proxy.py:52 +msgid "找不到单据类型需要变更的proxy函数,服务信息入库失败" +msgstr "找不到单据类型需要变更的proxy函数,服务信息入库失败" -#: backend/flow/views/mysql_restore_local_slave.py:44 -msgid "开始原地重建slave" -msgstr "开始原地重建slave" +#: backend/flow/utils/cloud/cloud_module_operate.py:135 +#, fuzzy +#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" +msgid "主机{}转移{}失败,转移参数:{}, 错误信息:{}" +msgstr "主机{}转移失败,转移参数:{}, 错误信息:{}" -#: backend/flow/views/mysql_rollback_data.py:48 -msgid "开始重建定点回档数据" -msgstr "开始重建定点回档数据" +#: backend/flow/utils/cloud/cloud_module_operate.py:196 +#, fuzzy +#| msgid "主机{}转移失败,转移参数:{}, 错误信息:{}" +msgid "主机{}转移待回收失败,错误信息:{}" +msgstr "主机{}转移失败,转移参数:{}, 错误信息:{}" -#: backend/flow/views/mysql_single_apply.py:57 -msgid "开始部署mysql单实例场景" -msgstr "开始部署mysql单实例场景" +#: backend/flow/utils/es/es_db_meta.py:94 +msgid "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" +msgstr "找不到单据类型需要变更的cmdb函数{},请联系系统管理员" -#: backend/flow/views/mysql_single_destroy.py:30 -msgid "开始回收mysql单节点版场景" -msgstr "开始回收mysql单节点版场景" +#: backend/flow/utils/hdfs/hdfs_db_meta.py:52 +#: backend/flow/utils/influxdb/influxdb_db_meta.py:114 +#: backend/flow/utils/kafka/kafka_db_meta.py:160 +#: backend/flow/utils/redis/redis_db_meta.py:48 +msgid "找不到单据类型需要变更的cmdb函数,请联系系统管理员" +msgstr "找不到单据类型需要变更的cmdb函数,请联系系统管理员" -#: backend/flow/views/mysql_single_destroy.py:46 -msgid "开始禁用mysql单节点版场景" -msgstr "开始禁用mysql单节点版场景" +#: backend/flow/utils/mysql/db_resource.py:106 +msgid " 获取资源失败: {}" +msgstr " 获取资源失败: {}" -#: backend/flow/views/mysql_single_destroy.py:62 -msgid "开始启动mysql单节点版场景" -msgstr "开始启动mysql单节点版场景" +#: backend/flow/utils/mysql/db_table_filter/exception.py:18 +msgid "库表过滤异常" +msgstr "库表过滤异常" -#: backend/flow/views/mysql_single_rename_database.py:30 -#: backend/flow/views/mysql_single_truncate_data.py:30 -#, fuzzy -#| msgid "开始TenDBHA清档场景" -msgid "开始TenDBSingle清档场景" -msgstr "开始TenDBHA清档场景" +#: backend/flow/utils/mysql/db_table_filter/exception.py:23 +msgid "输入校验异常" +msgstr "输入校验异常" -#: backend/flow/views/pulsar_destroy.py:39 -msgid "开始pulsar集群销毁场景" -msgstr "开始pulsar集群销毁场景" +#: backend/flow/utils/mysql/db_table_filter/filter.py:42 +msgid "include patterns 不能为空" +msgstr "include patterns 不能为空" -#: backend/flow/views/pulsar_disable.py:39 -msgid "开始PULSAR集群禁用场景" -msgstr "开始PULSAR集群禁用场景" +#: backend/flow/utils/mysql/db_table_filter/filter.py:48 +msgid "exclude patterns 要么同时为空, 要么都不为空" +msgstr "exclude patterns 要么同时为空, 要么都不为空" -#: backend/flow/views/pulsar_enable.py:39 -msgid "开始PULSAR集群启用场景" -msgstr "开始PULSAR集群启用场景" +#: backend/flow/utils/mysql/db_table_filter/tools.py:30 +msgid "使用通配符时, 只能有一个模式: {}" +msgstr "使用通配符时, 只能有一个模式: {}" -#: backend/flow/views/pulsar_reboot.py:55 -msgid "开始重启PULSAR场景" -msgstr "开始重启PULSAR场景" +#: backend/flow/utils/mysql/db_table_filter/tools.py:33 +msgid "% ? 不能独立使用" +msgstr "% ? 不能独立使用" -#: backend/flow/views/pulsar_replace.py:28 -#, fuzzy -#| msgid "开始PULSAR集群禁用场景" -msgid "开始PULSAR集群替换场景" -msgstr "开始PULSAR集群禁用场景" +#: backend/flow/utils/mysql/db_table_filter/tools.py:36 +msgid "* 只能独立使用" +msgstr "* 只能独立使用" -#: backend/flow/views/pulsar_shrink.py:28 -#, fuzzy -#| msgid "开始HDFS集群缩容场景" -msgid "开始PULSAR集群缩容场景" -msgstr "开始HDFS集群缩容场景" +#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:27 +msgid "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" +msgstr "exec_ip变量和get_trans_data_ip_var变量不能同时赋值" -#: backend/flow/views/rollback_pipeline.py:151 -msgid "导入资源池失败" -msgstr "导入资源池失败" +#: backend/flow/utils/mysql/mysql_act_dataclass_validator.py:29 +msgid "exec_ip变量和get_trans_data_ip_var变量不能同时为None" +msgstr "exec_ip变量和get_trans_data_ip_var变量不能同时为None" -#: backend/flow/views/rollback_pipeline.py:171 -msgid "高可用架构" -msgstr "高可用架构" +#: backend/flow/utils/mysql/mysql_act_playload.py:304 +msgid "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" +msgstr "传入的安装mysql端口列表为空或者非法值,请联系系统管理员" -#: backend/flow/views/rollback_pipeline.py:172 -msgid "单实例架构" -msgstr "单实例架构" +#: backend/flow/utils/mysql/mysql_act_playload.py:348 +msgid "传入的安装spider端口列表为空或者非法值,请联系系统管理员" +msgstr "传入的安装spider端口列表为空或者非法值,请联系系统管理员" -#: backend/flow/views/spider_cluster_database_table_backup.py:30 -#, fuzzy -#| msgid "开始库表备份场景" -msgid "开始TenDBCluster库表备份场景" -msgstr "开始库表备份场景" +#: backend/flow/utils/pulsar/consts.py:20 +msgid "broker默认分区数" +msgstr "broker默认分区数" -#: backend/flow/views/spider_cluster_destroy.py:34 -#, fuzzy -#| msgid "开始禁用ES场景" -msgid "开始禁用spider集群场景" -msgstr "开始禁用ES场景" +#: backend/flow/utils/pulsar/consts.py:21 +msgid "broker认证配置" +msgstr "broker认证配置" -#: backend/flow/views/spider_cluster_destroy.py:53 -#, fuzzy -#| msgid "开始启用ES场景" -msgid "开始启用spider集群场景" -msgstr "开始启用ES场景" +#: backend/flow/utils/pulsar/consts.py:22 +msgid "默认bookie池大小" +msgstr "默认bookie池大小" -#: backend/flow/views/spider_cluster_rename_database.py:30 -msgid "开始TenDBCluster数据库重命名场景" -msgstr "开始TenDBCluster数据库重命名场景" +#: backend/flow/utils/pulsar/consts.py:23 +msgid "写入副本数" +msgstr "写入副本数" -#: backend/flow/views/spider_cluster_truncate_database.py:30 -#, fuzzy -#| msgid "开始TenDBHA清档场景" -msgid "开始TenDBCluster清档场景" -msgstr "开始TenDBHA清档场景" +#: backend/flow/utils/pulsar/consts.py:24 +msgid "确认写入副本数" +msgstr "确认写入副本数" -#: backend/iam_app/dataclass/actions.py:47 -msgid "业务访问" -msgstr "业务访问" +#: backend/flow/utils/pulsar/consts.py:25 +msgid "数据保留时间,单位为分钟" +msgstr "数据保留时间,单位为分钟" -#: backend/iam_app/dataclass/actions.py:56 -msgid "数据库管理" -msgstr "数据库管理" +#: backend/flow/utils/pulsar/consts.py:26 +msgid "broker服务端口" +msgstr "broker服务端口" -#: backend/iam_app/dataclass/actions.py:65 -msgid "平台管理" -msgstr "平台管理" +#: backend/flow/utils/pulsar/consts.py:27 +msgid "访问Pulsar Manager账户名" +msgstr "访问Pulsar Manager账户名" -#: backend/iam_app/dataclass/actions.py:78 -msgid "动作ID不存在: {}" -msgstr "动作ID不存在: {}" +#: backend/flow/utils/pulsar/consts.py:28 +msgid "访问Pulsar Manager密码" +msgstr "访问Pulsar Manager密码" -#: backend/iam_app/dataclass/resources.py:94 -msgid "资源类型ID不存在: {}" -msgstr "资源类型ID不存在: {}" +#: backend/flow/utils/redis/redis_db_meta.py:56 +msgid "找不到单据类型需要查询的cmdb函数,请联系系统管理员" +msgstr "找不到单据类型需要查询的cmdb函数,请联系系统管理员" -#: backend/iam_app/exceptions.py:51 -#, python-brace-format -msgid "当前用户无 [{action_name}] 权限" -msgstr "当前用户无 [{action_name}] 权限" +#: backend/flow/utils/spider/get_spider_incr.py:45 +msgid "select spider_auto_increment failed: {}" +msgstr "" -#: backend/iam_app/handlers/drf_perm.py:162 -msgid "JWT鉴权错误,错误信息: {}" -msgstr "JWT鉴权错误,错误信息: {}" +#: backend/flow/utils/spider/get_spider_incr.py:49 +msgid "select spider_auto_increment is null, check " +msgstr "" -#: backend/iam_app/handlers/permission.py:74 -#, python-brace-format -msgid "获取系统信息错误:{message}" -msgstr "获取系统信息错误:{message}" +#: backend/flow/utils/spider/get_spider_incr.py:65 +msgid "The obtained incr is greater than MAX_SPIDER_MASTER_COUNT, check" +msgstr "" -#: backend/iam_app/serializers.py:18 -msgid "资源类型" -msgstr "资源类型" +#: backend/flow/views/cloud_dbha_apply.py:39 +#: backend/flow/views/cloud_dns_bind_apply.py:39 +msgid "开始部署dns-bind服务场景" +msgstr "开始部署dns-bind服务场景" -#: backend/iam_app/serializers.py:19 -msgid "资源ID" -msgstr "资源ID" +#: backend/flow/views/cloud_drs_apply.py:44 +msgid "开始部署drs服务场景" +msgstr "开始部署drs服务场景" -#: backend/iam_app/serializers.py:21 -msgid "动作ID列表" -msgstr "动作ID列表" +#: backend/flow/views/cloud_nginx_apply.py:44 +msgid "开始部署nginx服务场景" +msgstr "开始部署nginx服务场景" -#: backend/iam_app/serializers.py:22 -msgid "资源列表" -msgstr "资源列表" +#: backend/flow/views/cloud_nginx_apply.py:54 +#, fuzzy +#| msgid "开始部署nginx服务场景" +msgid "开始替换nginx服务场景" +msgstr "开始部署nginx服务场景" -#: backend/iam_app/views/views.py:27 -msgid "获取系统权限中心信息" -msgstr "获取系统权限中心信息" +#: backend/flow/views/es_apply.py:63 +msgid "开始部署ES场景" +msgstr "开始部署ES场景" -#: backend/iam_app/views/views.py:34 -msgid "检查当前用户对该动作是否有权限" -msgstr "检查当前用户对该动作是否有权限" +#: backend/flow/views/es_destroy.py:39 +msgid "开始下架ES场景" +msgstr "开始下架ES场景" -#: backend/iam_app/views/views.py:51 -msgid "获取权限申请数据" -msgstr "获取权限申请数据" +#: backend/flow/views/es_disable.py:39 +msgid "开始禁用ES场景" +msgstr "开始禁用ES场景" -#: backend/redis_dts/constants.py:19 -msgid "tendis ssd备份任务" -msgstr "tendis ssd备份任务" +#: backend/flow/views/es_enable.py:39 +msgid "开始启用ES场景" +msgstr "开始启用ES场景" -#: backend/redis_dts/constants.py:20 -msgid "tendis ssd备份拉取任务" -msgstr "tendis ssd备份拉取任务" +#: backend/flow/views/es_reboot.py:47 +msgid "开始重启ES节点场景" +msgstr "开始重启ES节点场景" -#: backend/redis_dts/constants.py:21 -msgid "tendis ssd备份解析任务" -msgstr "tendis ssd备份解析任务" +#: backend/flow/views/es_replace.py:63 backend/flow/views/es_scale_up.py:52 +msgid "开始扩容ES场景" +msgstr "开始扩容ES场景" -#: backend/redis_dts/constants.py:22 -msgid "tendis ssd数据导入任务" -msgstr "tendis ssd数据导入任务" +#: backend/flow/views/es_shrink.py:52 +msgid "开始缩容ES场景" +msgstr "开始缩容ES场景" -#: backend/redis_dts/constants.py:23 -msgid "tendis ssd拉起sync任务" -msgstr "tendis ssd拉起sync任务" +#: backend/flow/views/hdfs_apply.py:61 +msgid "开始部署HDFS场景" +msgstr "开始部署HDFS场景" -#: backend/redis_dts/constants.py:24 backend/redis_dts/constants.py:28 -msgid "tendis ssd监视sync任务" -msgstr "tendis ssd监视sync任务" +#: backend/flow/views/hdfs_destroy.py:39 +msgid "开始HDFS集群销毁场景" +msgstr "开始HDFS集群销毁场景" -#: backend/redis_dts/constants.py:27 -msgid "redis cache拉起redis-shake任务" -msgstr "redis cache拉起redis-shake任务" +#: backend/flow/views/hdfs_disable.py:39 +msgid "开始HDFS集群禁用场景" +msgstr "开始HDFS集群禁用场景" -#: backend/redis_dts/constants.py:31 -msgid "tendisplus拉起reids-sync任务" -msgstr "tendisplus拉起reids-sync任务" +#: backend/flow/views/hdfs_enable.py:39 +msgid "开始HDFS集群启用场景" +msgstr "开始HDFS集群启用场景" -#: backend/redis_dts/constants.py:33 -#, fuzzy -#| msgid "tendisplus实例安装 元数据" -msgid "tendisplus全量数据同步" -msgstr "tendisplus实例安装 元数据" +#: backend/flow/views/hdfs_reboot.py:55 +msgid "开始重启HDFS场景" +msgstr "开始重启HDFS场景" -#: backend/redis_dts/constants.py:34 -#, fuzzy -#| msgid "tendisplus实例安装 元数据" -msgid "tendisplus增量数据同步" -msgstr "tendisplus实例安装 元数据" +#: backend/flow/views/hdfs_replace.py:65 +msgid "开始替换HDFS场景" +msgstr "开始替换HDFS场景" -#: backend/redis_dts/constants.py:40 -msgid "停止数据同步todo" -msgstr "停止数据同步todo" +#: backend/flow/views/hdfs_scale_up.py:42 +msgid "开始扩容HDFS场景" +msgstr "开始扩容HDFS场景" -#: backend/redis_dts/constants.py:41 -msgid "停止数据同步失败" -msgstr "停止数据同步失败" +#: backend/flow/views/hdfs_shrink.py:42 +msgid "开始HDFS集群缩容场景" +msgstr "开始HDFS集群缩容场景" -#: backend/redis_dts/constants.py:42 -msgid "停止数据同步成功" -msgstr "停止数据同步成功" +#: backend/flow/views/influxdb_apply.py:57 +msgid "开始部署influxdb场景" +msgstr "开始部署influxdb场景" -#: backend/redis_dts/constants.py:44 -msgid "强制暂停任务todo" -msgstr "强制暂停任务todo" +#: backend/flow/views/influxdb_destroy.py:39 +msgid "开始下架Influxdb场景" +msgstr "开始下架Influxdb场景" -#: backend/redis_dts/constants.py:45 -#, fuzzy -#| msgid "创建模拟任务失败!" -msgid "强制暂停任务失败" -msgstr "创建模拟任务失败!" +#: backend/flow/views/influxdb_disable.py:39 +msgid "开始禁用Influxdb场景" +msgstr "开始禁用Influxdb场景" -#: backend/redis_dts/constants.py:46 -#, fuzzy -#| msgid "创建模拟任务成功" -msgid "强制暂停任务成功" -msgstr "创建模拟任务成功" +#: backend/flow/views/influxdb_enable.py:39 +msgid "开始启用Influxdb场景" +msgstr "开始启用Influxdb场景" -#: backend/redis_dts/constants.py:52 -#, fuzzy -#| msgid "获取集群节点" -msgid "集群节点数变更" -msgstr "获取集群节点" +#: backend/flow/views/influxdb_reboot.py:47 +msgid "开始重启Influxdb节点场景" +msgstr "开始重启Influxdb节点场景" -#: backend/redis_dts/constants.py:53 +#: backend/flow/views/influxdb_replace.py:49 #, fuzzy -#| msgid "集群类型" -msgid "集群类型变更" -msgstr "集群类型" - -#: backend/redis_dts/constants.py:54 -msgid "数据复制" -msgstr "数据复制" +#| msgid "开始替换kafka场景" +msgid "开始替换influxdb场景" +msgstr "开始替换kafka场景" -#: backend/redis_dts/constants.py:60 -msgid "同一业务不同集群" -msgstr "同一业务不同集群" +#: backend/flow/views/kafka_apply.py:70 +msgid "开始部署kafka场景" +msgstr "开始部署kafka场景" -#: backend/redis_dts/constants.py:61 -msgid "不同业务不同集群" -msgstr "不同业务不同集群" +#: backend/flow/views/kafka_destroy.py:39 +msgid "开始下架Kafka场景" +msgstr "开始下架Kafka场景" -#: backend/redis_dts/constants.py:62 -msgid "复制到其他系统" -msgstr "复制到其他系统" +#: backend/flow/views/kafka_disable.py:39 +msgid "开始禁用Kafka场景" +msgstr "开始禁用Kafka场景" -#: backend/redis_dts/constants.py:63 -msgid "从回档临时环境复制数据" -msgstr "从回档临时环境复制数据" +#: backend/flow/views/kafka_enable.py:39 +msgid "开始启用Kafka场景" +msgstr "开始启用Kafka场景" -#: backend/redis_dts/constants.py:64 -msgid "用户自建redis迁移到DBM" -msgstr "用户自建redis迁移到DBM" +#: backend/flow/views/kafka_reboot.py:47 +msgid "开始重启Kafka节点场景" +msgstr "开始重启Kafka节点场景" -#: backend/redis_dts/constants.py:70 -msgid "自动切换" -msgstr "自动切换" +#: backend/flow/views/kafka_replace.py:51 +msgid "开始替换kafka场景" +msgstr "开始替换kafka场景" -#: backend/redis_dts/constants.py:71 -msgid "用户确认切换" -msgstr "用户确认切换" +#: backend/flow/views/kafka_scale_up.py:49 +msgid "开始扩容kafka场景" +msgstr "开始扩容kafka场景" -#: backend/redis_dts/constants.py:77 -#: backend/ticket/builders/common/constants.py:79 -msgid "自动修复" -msgstr "自动修复" +#: backend/flow/views/kafka_shrink.py:44 +msgid "开始缩容kafka场景" +msgstr "开始缩容kafka场景" -#: backend/redis_dts/constants.py:78 -msgid "用户确认修复" -msgstr "用户确认修复" +#: backend/flow/views/mysql_add_slave.py:44 +msgid "开始添加slave" +msgstr "开始添加slave" -#: backend/redis_dts/exceptions.py:18 -#, fuzzy -#| msgid "DBMeta模块异常" -msgid "DBDts模块异常" -msgstr "DBMeta模块异常" +#: backend/flow/views/mysql_edit_config.py:60 +msgid "开始下发修改的参数" +msgstr "开始下发修改的参数" -#: backend/redis_dts/exceptions.py:23 -#, fuzzy -#| msgid "任务列表" -msgid "获取DTS任务列表异常" -msgstr "任务列表" +#: backend/flow/views/mysql_flashback.py:49 +msgid "开始flashback" +msgstr "开始flashback" -#: backend/redis_dts/exceptions.py:29 -msgid "DTS task操作异常" -msgstr "DTS task操作异常" +#: backend/flow/views/mysql_ha_db_table_backup.py:32 +msgid "开始库表备份场景" +msgstr "开始库表备份场景" -#: backend/redis_dts/models/tb_dts_distribute_lock.py:17 -#, fuzzy -#| msgid "关键字唯一标识" -msgid "锁的唯一标识" -msgstr "关键字唯一标识" +#: backend/flow/views/mysql_ha_destroy.py:31 +msgid "开始回收mysql主从版场景" +msgstr "开始回收mysql主从版场景" -#: backend/redis_dts/models/tb_dts_distribute_lock.py:18 -msgid "锁的持有者" -msgstr "锁的持有者" +#: backend/flow/views/mysql_ha_destroy.py:49 +msgid "开始禁用mysql主从版场景" +msgstr "开始禁用mysql主从版场景" -#: backend/redis_dts/models/tb_dts_distribute_lock.py:20 -msgid "锁的过期时间" -msgstr "锁的过期时间" +#: backend/flow/views/mysql_ha_destroy.py:65 +msgid "开始启动mysql主从版场景" +msgstr "开始启动mysql主从版场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:17 -#: backend/redis_dts/models/tb_tendis_dts_task.py:19 -#, fuzzy -#| msgid "单据" -msgid "单据号" -msgstr "单据" +#: backend/flow/views/mysql_ha_full_backup.py:32 +msgid "开始全库备份场景" +msgstr "开始全库备份场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:18 -#: backend/redis_dts/models/tb_tendis_dts_task.py:21 -msgid "业务bk_biz_id" -msgstr "业务bk_biz_id" +#: backend/flow/views/mysql_ha_master_fail_over.py:30 +msgid "开始执行主故障切换[整机切换]的任务" +msgstr "开始执行主故障切换[整机切换]的任务" -#: backend/redis_dts/models/tb_tendis_dts_job.py:19 -#: backend/redis_dts/models/tb_tendis_dts_task.py:22 -msgid "云区域id" -msgstr "云区域id" +#: backend/flow/views/mysql_ha_rename_database.py:30 +#: backend/flow/views/mysql_ha_truncate_data.py:30 +msgid "开始TenDBHA清档场景" +msgstr "开始TenDBHA清档场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:20 -#: backend/redis_dts/models/tb_tendis_dts_task.py:20 -msgid "申请人" -msgstr "申请人" +#: backend/flow/views/mysql_ha_switch.py:30 +msgid "开始执行主从切换[整机切换]的任务" +msgstr "开始执行主从切换[整机切换]的任务" -#: backend/redis_dts/models/tb_tendis_dts_job.py:25 -#, fuzzy -#| msgid "单据类型" -msgid "DTS单据类型" -msgstr "单据类型" +#: backend/flow/views/mysql_migrate_cluster.py:46 +#: backend/flow/views/mysql_restore_slave.py:49 +msgid "开始重建slave" +msgstr "开始重建slave" -#: backend/redis_dts/models/tb_tendis_dts_job.py:32 -msgid "DTS数据复制类型" -msgstr "DTS数据复制类型" +#: backend/flow/views/mysql_proxy_add.py:30 +msgid "开始添加mysql_proxy实例场景" +msgstr "开始添加mysql_proxy实例场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:36 -msgid "在线切换类型" -msgstr "在线切换类型" +#: backend/flow/views/mysql_proxy_reduce.py:30 +msgid "开始回收mysql_proxy实例场景" +msgstr "开始回收mysql_proxy实例场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:37 -#, fuzzy -#| msgid "数据校验执行" -msgid "是否数据校验" -msgstr "数据校验执行" +#: backend/flow/views/mysql_proxy_switch.py:30 +msgid "开始替换mysql_proxy实例场景" +msgstr "开始替换mysql_proxy实例场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:38 -#, fuzzy -#| msgid "{}数据修复" -msgid "是否数据修复" -msgstr "{}数据修复" +#: backend/flow/views/mysql_pt_table_sync.py:30 +msgid "开始执行数据修复" +msgstr "开始执行数据修复" -#: backend/redis_dts/models/tb_tendis_dts_job.py:42 -msgid "数据修复模式" -msgstr "数据修复模式" +#: backend/flow/views/mysql_restore_local_slave.py:44 +msgid "开始原地重建slave" +msgstr "开始原地重建slave" -#: backend/redis_dts/models/tb_tendis_dts_job.py:45 -#, fuzzy -#| msgid "集群类型" -msgid "源集群类型" -msgstr "集群类型" +#: backend/flow/views/mysql_rollback_data.py:48 +msgid "开始重建定点回档数据" +msgstr "开始重建定点回档数据" -#: backend/redis_dts/models/tb_tendis_dts_job.py:46 -msgid "回滚单据号" -msgstr "回滚单据号" +#: backend/flow/views/mysql_single_apply.py:57 +msgid "开始部署mysql单实例场景" +msgstr "开始部署mysql单实例场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:47 -msgid "回滚临时环境实例" -msgstr "回滚临时环境实例" +#: backend/flow/views/mysql_single_destroy.py:30 +msgid "开始回收mysql单节点版场景" +msgstr "开始回收mysql单节点版场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:48 -msgid "目标业务id" -msgstr "目标业务id" +#: backend/flow/views/mysql_single_destroy.py:46 +msgid "开始禁用mysql单节点版场景" +msgstr "开始禁用mysql单节点版场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:49 -#: backend/redis_dts/models/tb_tendis_dts_task.py:49 -msgid "目的集群" -msgstr "目的集群" +#: backend/flow/views/mysql_single_destroy.py:62 +msgid "开始启动mysql单节点版场景" +msgstr "开始启动mysql单节点版场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:51 +#: backend/flow/views/mysql_single_rename_database.py:30 +#: backend/flow/views/mysql_single_truncate_data.py:30 #, fuzzy -#| msgid "集群类型" -msgid "目标集群类型" -msgstr "集群类型" - -#: backend/redis_dts/models/tb_tendis_dts_job.py:52 -msgid "key正则(包含key)" -msgstr "key正则(包含key)" +#| msgid "开始TenDBHA清档场景" +msgid "开始TenDBSingle清档场景" +msgstr "开始TenDBSingle清档场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:53 -msgid "key正则(排除key)" -msgstr "key正则(排除key)" +#: backend/flow/views/pulsar_destroy.py:39 +msgid "开始pulsar集群销毁场景" +msgstr "开始pulsar集群销毁场景" -#: backend/redis_dts/models/tb_tendis_dts_job.py:56 -msgid "bill备注" -msgstr "bill备注" +#: backend/flow/views/pulsar_disable.py:39 +msgid "开始PULSAR集群禁用场景" +msgstr "开始PULSAR集群禁用场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:23 -msgid "执行迁移任务的dts_server" -msgstr "执行迁移任务的dts_server" +#: backend/flow/views/pulsar_enable.py:39 +msgid "开始PULSAR集群启用场景" +msgstr "开始PULSAR集群启用场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:25 -msgid "源集群优先级,值越大,优先级越高" -msgstr "源集群优先级,值越大,优先级越高" +#: backend/flow/views/pulsar_reboot.py:55 +msgid "开始重启PULSAR场景" +msgstr "开始重启PULSAR场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:26 +#: backend/flow/views/pulsar_replace.py:28 #, fuzzy -#| msgid "slave" -msgid "源slave_ip" -msgstr "slave" - -#: backend/redis_dts/models/tb_tendis_dts_task.py:27 -msgid "源slave_port" -msgstr "源slave_port" - -#: backend/redis_dts/models/tb_tendis_dts_task.py:28 -msgid "源实例密码base64值" -msgstr "源实例密码base64值" +#| msgid "开始PULSAR集群禁用场景" +msgid "开始PULSAR集群替换场景" +msgstr "开始PULSAR集群禁用场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:30 -msgid "源slave db类型" -msgstr "源slave db类型" +#: backend/flow/views/pulsar_shrink.py:28 +#, fuzzy +#| msgid "开始HDFS集群缩容场景" +msgid "开始PULSAR集群缩容场景" +msgstr "开始HDFS集群缩容场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:32 -msgid "源实例数据量大小,单位Byte" -msgstr "源实例数据量大小,单位Byte" +#: backend/flow/views/rollback_pipeline.py:151 +msgid "导入资源池失败" +msgstr "导入资源池失败" -#: backend/redis_dts/models/tb_tendis_dts_task.py:34 -msgid "源实例所属segment_start" -msgstr "源实例所属segment_start" +#: backend/flow/views/rollback_pipeline.py:171 +msgid "高可用架构" +msgstr "高可用架构" -#: backend/redis_dts/models/tb_tendis_dts_task.py:35 -msgid "源实例所属segment_end" -msgstr "源实例所属segment_end" +#: backend/flow/views/rollback_pipeline.py:172 +msgid "单实例架构" +msgstr "单实例架构" -#: backend/redis_dts/models/tb_tendis_dts_task.py:37 -msgid "源实例权重" -msgstr "源实例权重" +#: backend/flow/views/spider_cluster_database_table_backup.py:30 +#, fuzzy +#| msgid "开始库表备份场景" +msgid "开始TenDBCluster库表备份场景" +msgstr "开始库表备份场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:39 -msgid "源slave_ip上task并发数控制" -msgstr "源slave_ip上task并发数控制" +#: backend/flow/views/spider_cluster_destroy.py:34 +#, fuzzy +#| msgid "开始禁用ES场景" +msgid "开始禁用spider集群场景" +msgstr "开始禁用ES场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:40 +#: backend/flow/views/spider_cluster_destroy.py:53 #, fuzzy -#| msgid "实例所在的时区" -msgid "源实例所在城市" -msgstr "实例所在的时区" +#| msgid "开始启用ES场景" +msgid "开始启用spider集群场景" +msgstr "开始启用ES场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:42 -msgid "源实例slave-keep-log-count的旧值" -msgstr "源实例slave-keep-log-count的旧值" +#: backend/flow/views/spider_cluster_full_backup.py:30 +#, fuzzy +#| msgid "开始库表备份场景" +msgid "开始TenDBCluster全库备份场景" +msgstr "开始库表备份场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:43 -msgid "源实例slave-keep-log-count的新值" -msgstr "源实例slave-keep-log-count的新值" +#: backend/flow/views/spider_cluster_rename_database.py:30 +msgid "开始TenDBCluster数据库重命名场景" +msgstr "开始TenDBCluster数据库重命名场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:44 -msgid "源实例slave-keep-log-count是否恢复" -msgstr "源实例slave-keep-log-count是否恢复" +#: backend/flow/views/spider_cluster_truncate_database.py:30 +#, fuzzy +#| msgid "开始TenDBHA清档场景" +msgid "开始TenDBCluster清档场景" +msgstr "开始TenDBHA清档场景" -#: backend/redis_dts/models/tb_tendis_dts_task.py:45 -msgid "srcRedis是否包含list类型key" -msgstr "srcRedis是否包含list类型key" +#: backend/iam_app/dataclass/actions.py:47 +msgid "业务访问" +msgstr "业务访问" -#: backend/redis_dts/models/tb_tendis_dts_task.py:46 -msgid "包含key(正则)" -msgstr "包含key(正则)" +#: backend/iam_app/dataclass/actions.py:56 +msgid "数据库管理" +msgstr "数据库管理" -#: backend/redis_dts/models/tb_tendis_dts_task.py:47 -msgid "排除key(正则)" -msgstr "排除key(正则)" +#: backend/iam_app/dataclass/actions.py:65 +msgid "平台管理" +msgstr "平台管理" -#: backend/redis_dts/models/tb_tendis_dts_task.py:50 -msgid "目的密码base64值" -msgstr "目的密码base64值" +#: backend/iam_app/dataclass/actions.py:78 +msgid "动作ID不存在: {}" +msgstr "动作ID不存在: {}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:53 -msgid "tendisssd slave上bakup文件位置" -msgstr "tendisssd slave上bakup文件位置" +#: backend/iam_app/dataclass/resources.py:94 +msgid "资源类型ID不存在: {}" +msgstr "资源类型ID不存在: {}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:54 -msgid "backup文件拉取到dts_server本地位置" -msgstr "backup文件拉取到dts_server本地位置" +#: backend/iam_app/exceptions.py:51 +#, python-brace-format +msgid "当前用户无 [{action_name}] 权限" +msgstr "当前用户无 [{action_name}] 权限" -#: backend/redis_dts/models/tb_tendis_dts_task.py:55 -msgid "tendisdumper得到的sql文件夹" -msgstr "tendisdumper得到的sql文件夹" +#: backend/iam_app/handlers/drf_perm.py:162 +msgid "JWT鉴权错误,错误信息: {}" +msgstr "JWT鉴权错误,错误信息: {}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:56 -msgid "redis-sync端口" -msgstr "redis-sync端口" +#: backend/iam_app/handlers/permission.py:74 +#, python-brace-format +msgid "获取系统信息错误:{message}" +msgstr "获取系统信息错误:{message}" -#: backend/redis_dts/models/tb_tendis_dts_task.py:57 -msgid "sync的进程id" -msgstr "sync的进程id" +#: backend/iam_app/serializers.py:18 +msgid "资源类型" +msgstr "资源类型" -#: backend/redis_dts/models/tb_tendis_dts_task.py:59 -msgid "task重试次数" -msgstr "task重试次数" +#: backend/iam_app/serializers.py:19 +msgid "资源ID" +msgstr "资源ID" -#: backend/redis_dts/models/tb_tendis_dts_task.py:61 -msgid "sync操作" -msgstr "sync操作" +#: backend/iam_app/serializers.py:21 +msgid "动作ID列表" +msgstr "动作ID列表" -#: backend/redis_dts/models/tb_tendis_dts_task.py:63 -msgid "杀死syncer" -msgstr "杀死syncer" +#: backend/iam_app/serializers.py:22 +msgid "资源列表" +msgstr "资源列表" -#: backend/redis_dts/models/tb_tendis_dts_task.py:66 -#, fuzzy -#| msgid "domain信息" -msgid "信息" -msgstr "domain信息" +#: backend/iam_app/views/views.py:27 +msgid "获取系统权限中心信息" +msgstr "获取系统权限中心信息" -#: backend/redis_dts/models/tb_tendis_dts_task.py:68 -msgid "被忽略的错误" -msgstr "被忽略的错误" +#: backend/iam_app/views/views.py:34 +msgid "检查当前用户对该动作是否有权限" +msgstr "检查当前用户对该动作是否有权限" -#: backend/redis_dts/models/tb_tendis_dts_task.py:69 -msgid "sync从该时间点重新同步" -msgstr "sync从该时间点重新同步" +#: backend/iam_app/views/views.py:51 +msgid "获取权限申请数据" +msgstr "获取权限申请数据" #: backend/ticket/builders/__init__.py:149 #, python-brace-format @@ -12332,7 +12546,7 @@ msgstr "需求信息" #: backend/ticket/builders/__init__.py:305 #: backend/ticket/builders/mysql/mysql_import_sqlfile.py:176 -#: backend/ticket/constants.py:306 +#: backend/ticket/constants.py:307 msgid "单据审批" msgstr "单据审批" @@ -12641,29 +12855,29 @@ msgstr "忽略DB选择框和忽略table选择框要么同时为空,要么同 msgid "数据库{}不在所属集群{}中,请重新查验" msgstr "数据库{}不在所属集群{}中,请重新查验" -#: backend/ticket/builders/common/bigdata.py:34 +#: backend/ticket/builders/common/bigdata.py:38 msgid "节点列表信息" msgstr "节点列表信息" -#: backend/ticket/builders/common/bigdata.py:48 +#: backend/ticket/builders/common/bigdata.py:52 #: backend/ticket/builders/redis/redis_cluster_apply.py:96 msgid "主机{}不在空闲机池,请保证所选的主机均来自空闲机" msgstr "主机{}不在空闲机池,请保证所选的主机均来自空闲机" -#: backend/ticket/builders/common/bigdata.py:57 +#: backend/ticket/builders/common/bigdata.py:61 msgid "主机{}已经被使用,请重新选择主机" msgstr "主机{}已经被使用,请重新选择主机" -#: backend/ticket/builders/common/bigdata.py:78 +#: backend/ticket/builders/common/bigdata.py:82 #: backend/ticket/builders/mysql/base.py:175 msgid "集群{}状态转移不合法:{}--->{} is invalid" msgstr "集群{}状态转移不合法:{}--->{} is invalid" -#: backend/ticket/builders/common/bigdata.py:86 +#: backend/ticket/builders/common/bigdata.py:90 msgid "资源池规格" msgstr "资源池规格" -#: backend/ticket/builders/common/bigdata.py:106 +#: backend/ticket/builders/common/bigdata.py:110 #: backend/ticket/builders/influxdb/influxdb_apply.py:29 #: backend/ticket/builders/mysql/mysql_single_apply.py:48 #: backend/ticket/builders/redis/redis_cluster_apply.py:33 @@ -12671,74 +12885,74 @@ msgstr "资源池规格" msgid "城市代码" msgstr "城市代码" -#: backend/ticket/builders/common/bigdata.py:108 +#: backend/ticket/builders/common/bigdata.py:112 #: backend/ticket/builders/redis/redis_cluster_apply.py:31 #: backend/ticket/serializers.py:77 msgid "业务英文缩写" msgstr "业务英文缩写" -#: backend/ticket/builders/common/bigdata.py:109 +#: backend/ticket/builders/common/bigdata.py:113 msgid "集群名称(英文数字及下划线)" msgstr "集群名称(英文数字及下划线)" -#: backend/ticket/builders/common/bigdata.py:110 +#: backend/ticket/builders/common/bigdata.py:114 #: backend/ticket/builders/redis/redis_cluster_apply.py:42 msgid "集群别名(一般为中文别名)" msgstr "集群别名(一般为中文别名)" -#: backend/ticket/builders/common/bigdata.py:114 +#: backend/ticket/builders/common/bigdata.py:118 msgid "资源申请规格" msgstr "资源申请规格" -#: backend/ticket/builders/common/bigdata.py:152 +#: backend/ticket/builders/common/bigdata.py:156 msgid "主机{}出现角色互斥,{}与{}冲突" msgstr "主机{}出现角色互斥,{}与{}冲突" -#: backend/ticket/builders/common/bigdata.py:166 -#: backend/ticket/builders/common/bigdata.py:287 +#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:291 msgid "旧节点信息集合" msgstr "旧节点信息集合" -#: backend/ticket/builders/common/bigdata.py:166 -#: backend/ticket/builders/common/bigdata.py:168 -#: backend/ticket/builders/common/bigdata.py:287 -#: backend/ticket/builders/common/bigdata.py:289 +#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:172 +#: backend/ticket/builders/common/bigdata.py:291 +#: backend/ticket/builders/common/bigdata.py:293 msgid "节点信息" msgstr "节点信息" -#: backend/ticket/builders/common/bigdata.py:168 -#: backend/ticket/builders/common/bigdata.py:289 +#: backend/ticket/builders/common/bigdata.py:172 +#: backend/ticket/builders/common/bigdata.py:293 msgid "新节点信息集合" msgstr "新节点信息集合" -#: backend/ticket/builders/common/bigdata.py:170 +#: backend/ticket/builders/common/bigdata.py:174 msgid "规格类型" msgstr "规格类型" -#: backend/ticket/builders/common/bigdata.py:177 -#: backend/ticket/builders/common/bigdata.py:298 +#: backend/ticket/builders/common/bigdata.py:181 +#: backend/ticket/builders/common/bigdata.py:302 msgid "替换前后角色类型不一致,请保证替换前后角色类型和数量一致!" msgstr "替换前后角色类型不一致,请保证替换前后角色类型和数量一致!" -#: backend/ticket/builders/common/bigdata.py:185 -#: backend/ticket/builders/common/bigdata.py:306 +#: backend/ticket/builders/common/bigdata.py:189 +#: backend/ticket/builders/common/bigdata.py:310 msgid "角色{}替换前后数量不一致,请保证替换前后角色类型和数量一致!" msgstr "角色{}替换前后数量不一致,请保证替换前后角色类型和数量一致!" -#: backend/ticket/builders/common/bigdata.py:204 +#: backend/ticket/builders/common/bigdata.py:208 msgid "实例名" msgstr "实例名" -#: backend/ticket/builders/common/bigdata.py:215 -#: backend/ticket/builders/common/bigdata.py:281 +#: backend/ticket/builders/common/bigdata.py:219 +#: backend/ticket/builders/common/bigdata.py:285 msgid "实例{}不存在, 请重新确认实例的合法性" msgstr "实例{}不存在, 请重新确认实例的合法性" -#: backend/ticket/builders/common/bigdata.py:220 +#: backend/ticket/builders/common/bigdata.py:224 msgid "无法进行重启操作,原因:{}" msgstr "无法进行重启操作,原因:{}" -#: backend/ticket/builders/common/bigdata.py:291 +#: backend/ticket/builders/common/bigdata.py:295 #, fuzzy #| msgid "机器规格" msgid "规格" @@ -12937,33 +13151,34 @@ msgid "资源规格" msgstr "资源规格" #: backend/ticket/builders/influxdb/influxdb_apply.py:75 -#: backend/ticket/constants.py:210 +#: backend/ticket/constants.py:211 msgid "InfluxDB 实例部署" msgstr "InfluxDB 实例部署" #: backend/ticket/builders/influxdb/influxdb_destroy.py:37 -#: backend/ticket/constants.py:214 +#: backend/ticket/constants.py:215 msgid "InfluxDB 实例删除" msgstr "InfluxDB 实例删除" #: backend/ticket/builders/influxdb/influxdb_disable.py:37 +#: backend/ticket/constants.py:214 #, fuzzy #| msgid "InfluxDB 实例停用" msgid "InfluxDB 实例禁用" msgstr "InfluxDB 实例停用" #: backend/ticket/builders/influxdb/influxdb_enable.py:37 -#: backend/ticket/constants.py:212 +#: backend/ticket/constants.py:213 msgid "InfluxDB 实例启用" msgstr "InfluxDB 实例启用" #: backend/ticket/builders/influxdb/influxdb_reboot.py:39 -#: backend/ticket/constants.py:211 +#: backend/ticket/constants.py:212 msgid "InfluxDB 实例重启" msgstr "InfluxDB 实例重启" #: backend/ticket/builders/influxdb/influxdb_replace.py:46 -#: backend/ticket/constants.py:215 +#: backend/ticket/constants.py:216 #, fuzzy #| msgid "InfluxDB 实例重启" msgid "InfluxDB 实例替换" @@ -12995,7 +13210,7 @@ msgstr "" "Broker节点与副本节点数量有误,请确保Broker节点至少为1且副本数量<=Broker数量" #: backend/ticket/builders/kafka/kafka_apply.py:133 -#: backend/ticket/constants.py:174 +#: backend/ticket/constants.py:175 msgid "Kafka 集群部署" msgstr "Kafka 集群部署" @@ -13006,27 +13221,26 @@ msgid "Kafka 集群销毁" msgstr "Kafka集群" #: backend/ticket/builders/kafka/kafka_disable.py:37 -#: backend/ticket/constants.py:180 msgid "Kafka 集群停用" msgstr "Kafka 集群停用" #: backend/ticket/builders/kafka/kafka_enable.py:37 -#: backend/ticket/constants.py:179 +#: backend/ticket/constants.py:180 msgid "Kafka 集群启用" msgstr "Kafka 集群启用" #: backend/ticket/builders/kafka/kafka_reboot.py:39 -#: backend/ticket/constants.py:177 +#: backend/ticket/constants.py:178 msgid "Kafka 实例重启" msgstr "Kafka 实例重启" #: backend/ticket/builders/kafka/kafka_replace.py:48 -#: backend/ticket/constants.py:178 +#: backend/ticket/constants.py:179 msgid "Kafka 集群替换" msgstr "Kafka 集群替换" #: backend/ticket/builders/kafka/kafka_scale_up.py:65 -#: backend/ticket/constants.py:175 +#: backend/ticket/constants.py:176 msgid "Kafka 集群扩容" msgstr "Kafka 集群扩容" @@ -13035,7 +13249,7 @@ msgid "缩容仅支持Broker" msgstr "缩容仅支持Broker" #: backend/ticket/builders/kafka/kafka_shrink.py:77 -#: backend/ticket/constants.py:176 +#: backend/ticket/constants.py:177 msgid "Kafka 集群缩容" msgstr "Kafka 集群缩容" @@ -13693,58 +13907,50 @@ msgid "最小成功写入副本数量不得大于副本数量" msgstr "最小成功写入副本数量不得大于副本数量" #: backend/ticket/builders/pulsar/pulsar_apply.py:98 -#, fuzzy -#| msgid "Pulsar集群部署" +#: backend/ticket/constants.py:202 msgid "Pulsar 集群部署" -msgstr "Pulsar集群部署" +msgstr "Pulsar 集群部署" #: backend/ticket/builders/pulsar/pulsar_destroy.py:37 -#, fuzzy -#| msgid "Pulsar集群" +#: backend/ticket/constants.py:209 msgid "Pulsar 集群删除" -msgstr "Pulsar集群" +msgstr "Pulsar 集群删除" #: backend/ticket/builders/pulsar/pulsar_disable.py:37 +#: backend/ticket/constants.py:208 #, fuzzy -#| msgid "Pulsar集群" +#| msgid "Pulsar 集群停用" msgid "Pulsar 集群禁用" -msgstr "Pulsar集群" +msgstr "Pulsar 集群停用" #: backend/ticket/builders/pulsar/pulsar_enable.py:37 -#, fuzzy -#| msgid "Pulsar集群" +#: backend/ticket/constants.py:207 msgid "Pulsar 集群启用" -msgstr "Pulsar集群" +msgstr "Pulsar 集群启用" #: backend/ticket/builders/pulsar/pulsar_reboot.py:39 #, fuzzy -#| msgid "Pulsar集群" +#| msgid "Pulsar 集群启用" msgid "Pulsar 集群重启" -msgstr "Pulsar集群" +msgstr "Pulsar 集群启用" #: backend/ticket/builders/pulsar/pulsar_replace.py:47 -#, fuzzy -#| msgid "Pulsar集群" +#: backend/ticket/constants.py:206 msgid "Pulsar 集群替换" -msgstr "Pulsar集群" +msgstr "Pulsar 集群替换" #: backend/ticket/builders/pulsar/pulsar_scale_up.py:47 -#, fuzzy -#| msgid "Pulsar集群扩容" +#: backend/ticket/constants.py:203 msgid "Pulsar 集群扩容" -msgstr "Pulsar集群扩容" +msgstr "Pulsar 集群扩容" #: backend/ticket/builders/pulsar/pulsar_shrink.py:35 -#, fuzzy -#| msgid "broker信息列表" msgid "bookkeeper信息列表" -msgstr "broker信息列表" +msgstr "bookkeeper信息列表" #: backend/ticket/builders/pulsar/pulsar_shrink.py:61 -#, fuzzy -#| msgid "{}: 至少保留1台!" msgid "{}: 至少保留{}台!" -msgstr "{}: 至少保留1台!" +msgstr "{}: 至少保留{}台!" #: backend/ticket/builders/pulsar/pulsar_shrink.py:64 msgid "请选择Broker和BookKeeper实例进行缩容" @@ -13755,10 +13961,9 @@ msgid "缩容不支持ZooKeeper" msgstr "缩容不支持ZooKeeper" #: backend/ticket/builders/pulsar/pulsar_shrink.py:85 -#, fuzzy -#| msgid "Pulsar集群扩容" +#: backend/ticket/constants.py:204 msgid "Pulsar 集群缩容" -msgstr "Pulsar集群扩容" +msgstr "Pulsar 集群缩容" #: backend/ticket/builders/redis/base.py:50 msgid "集群【{}({})】锁定中,请等待" @@ -14176,331 +14381,315 @@ msgstr "Redis 集群禁用" msgid "TenDB Cluster 集群销毁" msgstr "下架TenDB-Cluster集群[{}]" -#: backend/ticket/constants.py:157 +#: backend/ticket/constants.py:155 +#, fuzzy +#| msgid "库表备份" +msgid "Spider 全备" +msgstr "库表备份" + +#: backend/ticket/constants.py:158 msgid "Redis 单节点部署" msgstr "Redis 单节点部署" -#: backend/ticket/constants.py:158 +#: backend/ticket/constants.py:159 msgid "Redis 集群部署" msgstr "Redis 集群部署" -#: backend/ticket/constants.py:159 +#: backend/ticket/constants.py:160 msgid "Redis 提取 Key" msgstr "Redis 提取 Key" -#: backend/ticket/constants.py:160 +#: backend/ticket/constants.py:161 msgid "Redis 删除 key" msgstr "Redis 删除 key" -#: backend/ticket/constants.py:161 +#: backend/ticket/constants.py:162 msgid "Redis 集群备份" msgstr "Redis 集群备份" -#: backend/ticket/constants.py:162 +#: backend/ticket/constants.py:163 msgid "Redis 集群启用" msgstr "Redis 集群启用" -#: backend/ticket/constants.py:163 +#: backend/ticket/constants.py:164 msgid "Redis 集群禁用" msgstr "Redis 集群禁用" -#: backend/ticket/constants.py:164 +#: backend/ticket/constants.py:165 msgid "Redis 集群删除" msgstr "Redis 集群删除" -#: backend/ticket/constants.py:165 +#: backend/ticket/constants.py:166 msgid "Redis 集群清档" msgstr "Redis 集群清档" -#: backend/ticket/constants.py:166 +#: backend/ticket/constants.py:167 msgid "Redis 扩缩容" msgstr "Redis 扩缩容" -#: backend/ticket/constants.py:167 +#: backend/ticket/constants.py:168 msgid "Proxy 扩缩容" msgstr "Proxy 扩缩容" -#: backend/ticket/constants.py:168 +#: backend/ticket/constants.py:169 msgid "redis集群 slave 裁撤替换" msgstr "redis集群 slave 裁撤替换" -#: backend/ticket/constants.py:169 +#: backend/ticket/constants.py:170 msgid "redis集群 master 裁撤替换" msgstr "redis集群 master 裁撤替换" -#: backend/ticket/constants.py:170 +#: backend/ticket/constants.py:171 msgid "redis集群 proxy 裁撤替换" msgstr "redis集群 proxy 裁撤替换" -#: backend/ticket/constants.py:171 +#: backend/ticket/constants.py:172 msgid "Redis 新建DTS任务" msgstr "Redis 新建DTS任务" #: backend/ticket/constants.py:181 +#, fuzzy +#| msgid "Kafka 集群停用" +msgid "Kafka 集群禁用" +msgstr "Kafka 集群停用" + +#: backend/ticket/constants.py:182 msgid "Kafka 集群删除" msgstr "Kafka 集群删除" -#: backend/ticket/constants.py:183 +#: backend/ticket/constants.py:184 msgid "HDFS 集群部署" msgstr "HDFS 集群部署" -#: backend/ticket/constants.py:184 +#: backend/ticket/constants.py:185 msgid "HDFS 集群扩容" msgstr "HDFS 集群扩容" -#: backend/ticket/constants.py:185 +#: backend/ticket/constants.py:186 msgid "HDFS 集群缩容" msgstr "HDFS 集群缩容" -#: backend/ticket/constants.py:186 +#: backend/ticket/constants.py:187 msgid "HDFS 实例重启" msgstr "HDFS 实例重启" -#: backend/ticket/constants.py:187 +#: backend/ticket/constants.py:188 msgid "HDFS 集群替换" msgstr "HDFS 集群替换" -#: backend/ticket/constants.py:188 +#: backend/ticket/constants.py:189 msgid "HDFS 集群启用" msgstr "HDFS 集群启用" -#: backend/ticket/constants.py:189 -msgid "HDFS 集群停用" -msgstr "HDFS 集群停用" - #: backend/ticket/constants.py:190 +#, fuzzy +#| msgid "HDFS集群禁用" +msgid "HDFS 集群禁用" +msgstr "HDFS集群禁用" + +#: backend/ticket/constants.py:191 msgid "HDFS 集群删除" msgstr "HDFS 集群删除" -#: backend/ticket/constants.py:192 +#: backend/ticket/constants.py:193 msgid "ES 集群部署" msgstr "ES 集群部署" -#: backend/ticket/constants.py:193 +#: backend/ticket/constants.py:194 msgid "ES 集群扩容" msgstr "ES 集群扩容" -#: backend/ticket/constants.py:194 +#: backend/ticket/constants.py:195 msgid "ES 集群缩容" msgstr "ES 集群缩容" -#: backend/ticket/constants.py:195 +#: backend/ticket/constants.py:196 msgid "ES 实例重启" msgstr "ES 实例重启" -#: backend/ticket/constants.py:196 +#: backend/ticket/constants.py:197 msgid "ES 集群替换" msgstr "ES 集群替换" -#: backend/ticket/constants.py:197 +#: backend/ticket/constants.py:198 msgid "ES 集群启用" msgstr "ES 集群启用" -#: backend/ticket/constants.py:198 -msgid "ES 集群停用" +#: backend/ticket/constants.py:199 +#, fuzzy +#| msgid "ES 集群停用" +msgid "ES 集群禁用" msgstr "ES 集群停用" -#: backend/ticket/constants.py:199 +#: backend/ticket/constants.py:200 msgid "ES 集群删除" msgstr "ES 集群删除" -#: backend/ticket/constants.py:201 -msgid "PULSAR 集群部署" -msgstr "PULSAR 集群部署" - -#: backend/ticket/constants.py:202 -msgid "PULSAR 集群扩容" -msgstr "PULSAR 集群扩容" - -#: backend/ticket/constants.py:203 -msgid "PULSAR 集群缩容" -msgstr "PULSAR 集群缩容" - -#: backend/ticket/constants.py:204 -msgid "PULSAR 实例重启" -msgstr "PULSAR 实例重启" - #: backend/ticket/constants.py:205 -msgid "PULSAR 集群替换" -msgstr "PULSAR 集群替换" - -#: backend/ticket/constants.py:206 -msgid "PULSAR 集群启用" -msgstr "PULSAR 集群启用" +msgid "Pulsar 实例重启" +msgstr "Pulsar 实例重启" -#: backend/ticket/constants.py:207 -msgid "PULSAR 集群停用" -msgstr "PULSAR 集群停用" - -#: backend/ticket/constants.py:208 -msgid "PULSAR 集群删除" -msgstr "PULSAR 集群删除" - -#: backend/ticket/constants.py:213 -msgid "InfluxDB 实例停用" -msgstr "InfluxDB 实例停用" - -#: backend/ticket/constants.py:218 +#: backend/ticket/constants.py:219 msgid "云区域服务部署" msgstr "云区域服务部署" -#: backend/ticket/constants.py:219 +#: backend/ticket/constants.py:220 msgid "云区域Nginx 服务部署" msgstr "云区域Nginx 服务部署" -#: backend/ticket/constants.py:220 +#: backend/ticket/constants.py:221 #, fuzzy #| msgid "云区域Nginx 服务部署" msgid "云区域nginx 服务重装" msgstr "云区域Nginx 服务部署" -#: backend/ticket/constants.py:221 +#: backend/ticket/constants.py:222 #, fuzzy #| msgid "云区域Nginx 服务部署" msgid "云区域nginx 服务替换" msgstr "云区域Nginx 服务部署" -#: backend/ticket/constants.py:222 +#: backend/ticket/constants.py:223 msgid "云区域dns 服务部署" msgstr "云区域dns 服务部署" -#: backend/ticket/constants.py:223 +#: backend/ticket/constants.py:224 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务添加" msgstr "云区域dns 服务部署" -#: backend/ticket/constants.py:224 +#: backend/ticket/constants.py:225 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务裁撤" msgstr "云区域dns 服务部署" -#: backend/ticket/constants.py:225 +#: backend/ticket/constants.py:226 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务替换" msgstr "云区域dns 服务部署" -#: backend/ticket/constants.py:226 +#: backend/ticket/constants.py:227 #, fuzzy #| msgid "云区域dns 服务部署" msgid "云区域dns 服务重装" msgstr "云区域dns 服务部署" -#: backend/ticket/constants.py:227 +#: backend/ticket/constants.py:228 msgid "云区域dbha 服务部署" msgstr "云区域dbha 服务部署" -#: backend/ticket/constants.py:228 +#: backend/ticket/constants.py:229 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务重装" msgstr "云区域dbha 服务部署" -#: backend/ticket/constants.py:229 +#: backend/ticket/constants.py:230 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务替换" msgstr "云区域dbha 服务部署" -#: backend/ticket/constants.py:230 +#: backend/ticket/constants.py:231 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务新增" msgstr "云区域dbha 服务部署" -#: backend/ticket/constants.py:231 +#: backend/ticket/constants.py:232 #, fuzzy #| msgid "云区域dbha 服务部署" msgid "云区域dbha 服务删除" msgstr "云区域dbha 服务部署" -#: backend/ticket/constants.py:232 +#: backend/ticket/constants.py:233 msgid "云区域drs 服务部署" msgstr "云区域drs 服务部署" -#: backend/ticket/constants.py:233 +#: backend/ticket/constants.py:234 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务重启" msgstr "云区域drs 服务部署" -#: backend/ticket/constants.py:234 +#: backend/ticket/constants.py:235 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务新增" msgstr "云区域drs 服务部署" -#: backend/ticket/constants.py:235 +#: backend/ticket/constants.py:236 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务删除" msgstr "云区域drs 服务部署" -#: backend/ticket/constants.py:236 +#: backend/ticket/constants.py:237 #, fuzzy #| msgid "云区域drs 服务部署" msgid "云区域drs 服务替换" msgstr "云区域drs 服务部署" -#: backend/ticket/constants.py:308 +#: backend/ticket/constants.py:309 msgid "生产部署" msgstr "生产部署" -#: backend/ticket/constants.py:310 +#: backend/ticket/constants.py:311 msgid "快速执行" msgstr "快速执行" -#: backend/ticket/constants.py:312 +#: backend/ticket/constants.py:313 msgid "结果忽略执行" msgstr "结果忽略执行" -#: backend/ticket/constants.py:316 +#: backend/ticket/constants.py:317 msgid "交付" msgstr "交付" -#: backend/ticket/constants.py:318 +#: backend/ticket/constants.py:319 msgid "描述任务信息" msgstr "描述任务信息" -#: backend/ticket/constants.py:324 +#: backend/ticket/constants.py:325 msgid "资源交付" msgstr "资源交付" -#: backend/ticket/constants.py:326 +#: backend/ticket/constants.py:327 msgid "资源批量申请" msgstr "资源批量申请" -#: backend/ticket/constants.py:328 +#: backend/ticket/constants.py:329 msgid "资源批量交付" msgstr "资源批量交付" -#: backend/ticket/constants.py:334 +#: backend/ticket/constants.py:335 msgid "前置动作" msgstr "前置动作" -#: backend/ticket/constants.py:335 +#: backend/ticket/constants.py:336 msgid "后继动作" msgstr "后继动作" -#: backend/ticket/constants.py:341 +#: backend/ticket/constants.py:342 msgid "自动重试" msgstr "自动重试" -#: backend/ticket/constants.py:342 +#: backend/ticket/constants.py:343 msgid "手动重试" msgstr "手动重试" -#: backend/ticket/constants.py:348 +#: backend/ticket/constants.py:349 msgid "通用错误代码" msgstr "通用错误代码" -#: backend/ticket/constants.py:349 +#: backend/ticket/constants.py:350 msgid "自动互斥重试错误代码" msgstr "自动互斥重试错误代码" -#: backend/ticket/constants.py:350 +#: backend/ticket/constants.py:351 msgid "手动互斥重试错误代码" msgstr "手动互斥重试错误代码" @@ -14553,7 +14742,7 @@ msgstr "单据提交重复" msgid "单据{ticket_type}提交重复" msgstr "单据{ticket_type}提交重复" -#: backend/ticket/flow_manager/base.py:149 +#: backend/ticket/flow_manager/base.py:94 msgid "{}流程已跳过" msgstr "{}流程已跳过" @@ -14565,16 +14754,16 @@ msgstr "交付成功" msgid "{}执行{}" msgstr "{}执行{}" -#: backend/ticket/flow_manager/inner.py:81 +#: backend/ticket/flow_manager/inner.py:82 #, python-brace-format msgid "任务{status_display}" msgstr "任务{status_display}" -#: backend/ticket/flow_manager/inner.py:205 +#: backend/ticket/flow_manager/inner.py:206 msgid "该任务流程跳过,相关信息可在历史任务中查看" msgstr "该任务流程跳过,相关信息可在历史任务中查看" -#: backend/ticket/flow_manager/inner.py:225 +#: backend/ticket/flow_manager/inner.py:226 #, python-brace-format msgid "(执行结果可忽略)任务状态: {status_display}" msgstr "(执行结果可忽略)任务状态: {status_display}" @@ -14621,19 +14810,19 @@ msgstr "nginx重启失败,错误信息: {}" msgid "资源申请下一个节点不为部署节点,请重新编排" msgstr "资源申请下一个节点不为部署节点,请重新编排" -#: backend/ticket/flow_manager/timer.py:55 +#: backend/ticket/flow_manager/timer.py:56 msgid "定时时间{},已超时{},需手动触发。暂停状态:{}" msgstr "定时时间{},已超时{},需手动触发。暂停状态:{}" -#: backend/ticket/flow_manager/timer.py:62 +#: backend/ticket/flow_manager/timer.py:63 msgid "定时节点已触发" msgstr "定时节点已触发" -#: backend/ticket/flow_manager/timer.py:64 +#: backend/ticket/flow_manager/timer.py:65 msgid "定时时间{},倒计时:{}" msgstr "定时时间{},倒计时:{}" -#: backend/ticket/flow_manager/timer.py:95 +#: backend/ticket/flow_manager/timer.py:96 msgid "【{}】定时流程待确认,是否继续?" msgstr "【{}】定时流程待确认,是否继续?" @@ -14714,7 +14903,7 @@ msgstr "正在自动创建单据,单据详情: {}" msgid "单据{}正在初始化流程" msgstr "单据{}正在初始化流程" -#: backend/ticket/models/ticket.py:246 backend/ticket/models/ticket.py:296 +#: backend/ticket/models/ticket.py:246 backend/ticket/models/ticket.py:302 #: backend/ticket/models/todo.py:31 msgid "关联流程任务" msgstr "关联流程任务" @@ -14767,8 +14956,8 @@ msgstr "操作" msgid "待办操作记录" msgstr "待办操作记录" -#: backend/ticket/serializers.py:71 backend/ticket/views.py:149 -#: backend/ticket/views.py:150 +#: backend/ticket/serializers.py:71 backend/ticket/views.py:172 +#: backend/ticket/views.py:173 msgid "单据详情" msgstr "单据详情" @@ -14870,65 +15059,71 @@ msgstr "确认执行" msgid "终止单据" msgstr "终止单据" -#: backend/ticket/views.py:126 +#: backend/ticket/views.py:136 +#, fuzzy +#| msgid "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" +msgid "实例{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" +msgstr "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" + +#: backend/ticket/views.py:149 msgid "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" msgstr "集群{}已存在相同类型的单据[{}]正在运行,请确认是否重复提交" -#: backend/ticket/views.py:166 +#: backend/ticket/views.py:189 msgid "单据列表" msgstr "单据列表" -#: backend/ticket/views.py:183 +#: backend/ticket/views.py:208 msgid "获取单据流程" msgstr "获取单据流程" -#: backend/ticket/views.py:185 +#: backend/ticket/views.py:210 msgid "流程信息" msgstr "流程信息" -#: backend/ticket/views.py:196 +#: backend/ticket/views.py:221 msgid "单据回调" msgstr "单据回调" -#: backend/ticket/views.py:209 +#: backend/ticket/views.py:234 msgid "单据流程重试" msgstr "单据流程重试" -#: backend/ticket/views.py:223 +#: backend/ticket/views.py:248 msgid "获取单据类型列表" msgstr "获取单据类型列表" -#: backend/ticket/views.py:232 +#: backend/ticket/views.py:257 msgid "节点列表" msgstr "节点列表" -#: backend/ticket/views.py:261 +#: backend/ticket/views.py:286 msgid "待办单据列表" msgstr "待办单据列表" -#: backend/ticket/views.py:299 +#: backend/ticket/views.py:325 msgid "待办处理" msgstr "待办处理" -#: backend/ticket/views.py:320 +#: backend/ticket/views.py:346 msgid "待办单据数" msgstr "待办单据数" -#: backend/ticket/views.py:344 +#: backend/ticket/views.py:370 msgid "查询集群变更单据事件" msgstr "查询集群变更单据事件" -#: backend/ticket/views.py:380 +#: backend/ticket/views.py:406 #, fuzzy #| msgid "查询集群变更单据事件" msgid "查询集群实例变更单据事件" msgstr "查询集群变更单据事件" -#: backend/ticket/views.py:416 +#: backend/ticket/views.py:442 msgid "快速部署云区域组件" msgstr "快速部署云区域组件" -#: backend/ticket/views.py:484 +#: backend/ticket/views.py:514 msgid "云区域组件快速部署单据" msgstr "云区域组件快速部署单据" @@ -14972,298 +15167,55 @@ msgstr "日志版本文件没找到,请联系管理员" msgid "日志详情获取成功" msgstr "日志详情获取成功" -#~ msgid "{}-接口结果返回异常" -#~ msgstr "{}-接口结果返回异常" - -#~ msgid "写入{}服务元信息" -#~ msgstr "写入{}服务元信息" - -#~ msgid "cluster[{}] master_ip[{}] master_port[{}]的分区任务" -#~ msgstr "cluster[{}] master_ip[{}] master_port[{}]的分区任务" - -#~ msgid "下载定点恢复的binlog文件到{}" -#~ msgstr "下载定点恢复的binlog文件到{}" - -#~ msgid "定点恢复之前滚binlog{}" -#~ msgstr "定点恢复之前滚binlog{}" - -#~ msgid "安装mysql-monitor" -#~ msgstr "安装mysql-monitor" - -#~ msgid "清理mysql/spider实例周边配置" -#~ msgstr "清理mysql/spider实例周边配置" - -#~ msgid "清理中控实例周边配置" -#~ msgstr "清理中控实例周边配置" - -#~ msgid "未完成{}场景的定义" -#~ msgstr "未完成{}场景的定义" - -#~ msgid "实例的ip 地址" -#~ msgstr "实例的ip 地址" - -#~ msgid "实例的port 端口信息" -#~ msgstr "实例的port 端口信息" +#~ msgid "[proxy]下发介质包" +#~ msgstr "[proxy]下发介质包" -#~ msgid "实例状态" -#~ msgstr "实例状态" +#~ msgid "[redis]下发介质包" +#~ msgstr "[redis]下发介质包" -#~ msgid "实例版本" -#~ msgstr "实例版本" +#~ msgid "安装Redis实例" +#~ msgstr "安装Redis实例" -#~ msgid "在资源池获取资源失败" -#~ msgstr "在资源池获取资源失败" +#~ msgid "redis实例安装 元数据" +#~ msgstr "redis实例安装 元数据" -#~ msgid "识别不了单据类型所需要的拼接上下文过程,异常退出[{}]" -#~ msgstr "识别不了单据类型所需要的拼接上下文过程,异常退出[{}]" +#~ msgid "[redis master]部署bkdbmon" +#~ msgstr "[redis master]部署bkdbmon" -#~ msgid "在资源池获取资源成功" -#~ msgstr "在资源池获取资源成功" +#~ msgid "[redis slave]部署bkdbmon" +#~ msgstr "[redis slave]部署bkdbmon" -#~ msgid "没有找到对应操作方法,请联系系统管理员:[{}]" -#~ msgstr "没有找到对应操作方法,请联系系统管理员:[{}]" +#~ msgid "[proxy]部署bkdbmon" +#~ msgstr "[proxy]部署bkdbmon" -#~ msgid "申请测试语义实例超时,退出" -#~ msgstr "申请测试语义实例超时,退出" +#~ msgid "proxy安装 元数据" +#~ msgstr "proxy安装 元数据" -#~ msgid "目前暂时没有可用的测试语义实例,等待10秒重新申请" -#~ msgstr "目前暂时没有可用的测试语义实例,等待10秒重新申请" +#~ msgid "[tendisplus]下发介质包" +#~ msgstr "[tendisplus]下发介质包" -#~ msgid "申请到实例被其他流程已申请到,等待10秒重新申请" -#~ msgstr "申请到实例被其他流程已申请到,等待10秒重新申请" +#~ msgid "安装tendisplus实例" +#~ msgstr "安装tendisplus实例" -#~ msgid "权限不足,无法访问!" -#~ msgstr "权限不足,无法访问!" +#~ msgid "tendisplus实例安装 元数据" +#~ msgstr "tendisplus实例安装 元数据" -#~ msgid "节点IP" -#~ msgstr "节点IP" +#~ msgid "redis建立主从元数据" +#~ msgstr "redis建立主从元数据" -#~ msgid "资源池自动分配" -#~ msgstr "资源池自动分配" +#~ msgid "安装predixy实例" +#~ msgstr "安装predixy实例" -#~ msgid "集群名字" -#~ msgstr "集群名字" - -#~ msgid "分组名称" -#~ msgstr "分组名称" - -#~ msgid "集群名称" -#~ msgstr "集群名称" - -#~ msgid "旧实例信息" -#~ msgstr "旧实例信息" - -#~ msgid "新实例信息" -#~ msgstr "新实例信息" - -#~ msgid "重启实例" -#~ msgstr "重启实例" - -#~ msgid "Http端口" -#~ msgstr "Http端口" - -#~ msgid "{}. 新从库机器信息" -#~ msgstr "{}. 新从库机器信息" - -#~ msgid "{}. 目标集群" -#~ msgstr "{}. 目标集群" - -#~ msgid "{}. 集群" -#~ msgstr "{}. 集群" - -#~ msgid "{}. slave列表" -#~ msgstr "{}. slave列表" - -#~ msgid "{}. 匹配DB列表" -#~ msgstr "{}. 匹配DB列表" - -#~ msgid "{}. 忽略DB列表" -#~ msgstr "{}. 忽略DB列表" - -#~ msgid "{}. 匹配Table列表" -#~ msgstr "{}. 匹配Table列表" - -#~ msgid "{}. 忽略Table列表" -#~ msgstr "{}. 忽略Table列表" - -#~ msgid "运行时长" -#~ msgstr "运行时长" - -#~ msgid "是否自动修复" -#~ msgstr "是否自动修复" - -#~ msgid "{}. 集群ID" -#~ msgstr "{}. 集群ID" - -#~ msgid "{}. 备份新机器IP" -#~ msgstr "{}. 备份新机器IP" - -#~ msgid "{}. 备份源" -#~ msgstr "{}. 备份源" - -#~ msgid "{}. 回档时间" -#~ msgstr "{}. 回档时间" - -#~ msgid "{}. 备份文件ID" -#~ msgstr "{}. 备份文件ID" - -#~ msgid "{}. 目标库列表" -#~ msgstr "{}. 目标库列表" - -#~ msgid "{}. 忽略库列表" -#~ msgstr "{}. 忽略库列表" - -#~ msgid "{}. 目标table列表" -#~ msgstr "{}. 目标table列表" - -#~ msgid "{}. 忽略table列表" -#~ msgstr "{}. 忽略table列表" - -#~ msgid "{}. 起止时间" -#~ msgstr "{}. 起止时间" - -#~ msgid "{}. flashback工具地址" -#~ msgstr "{}. flashback工具地址" - -#~ msgid "{}. 记录文件" -#~ msgstr "{}. 记录文件" - -#~ msgid "容灾要求" -#~ msgstr "容灾要求" - -#~ msgid "{}. 清档类型" -#~ msgstr "{}. 清档类型" - -#~ msgid "{}.是否强制执行" -#~ msgstr "{}.是否强制执行" - -#~ msgid "备份文件tag(备份保存时间)" -#~ msgstr "备份文件tag(备份保存时间)" - -#~ msgid "重命名数据库列表信息" -#~ msgstr "重命名数据库列表信息" - -#~ msgid "{}. 目标主库 IP" -#~ msgstr "{}. 目标主库 IP" - -#~ msgid "{}. 目标从库 IP" -#~ msgstr "{}. 目标从库 IP" - -#~ msgid "{}. 新主库-主机信息" -#~ msgstr "{}. 新主库-主机信息" - -#~ msgid "{}. 新从库-主机信息" -#~ msgstr "{}. 新从库-主机信息" - -#~ msgid "{}. 配置ID列表" -#~ msgstr "{}. 配置ID列表" - -#~ msgid "{}-变更的集群" -#~ msgstr "{}-变更的集群" - -#~ msgid "{}-旧Proxy实例信息" -#~ msgstr "{}-旧Proxy实例信息" - -#~ msgid "{}-新Proxy机器信息" -#~ msgstr "{}-新Proxy机器信息" - -#~ msgid "{}. 从库实例信息" -#~ msgstr "{}. 从库实例信息" - -#~ msgid "{}. 所属集群" -#~ msgstr "{}. 所属集群" - -#~ msgid "{}. 目标从库实例信息" -#~ msgstr "{}. 目标从库实例信息" - -#~ msgid "{}. 关联集群" -#~ msgstr "{}. 关联集群" - -#~ msgid "集群数量" -#~ msgstr "集群数量" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 角色: {}\n" -#~ " 备份类型: {}\n" -#~ msgstr "" -#~ "集群[{}]:{}\n" -#~ " 角色: {}\n" -#~ " 备份类型: {}\n" - -#~ msgid "备份规则" -#~ msgstr "备份规则" - -#~ msgid "备份结束" -#~ msgstr "备份结束" - -#~ msgid "结束" -#~ msgstr "结束" - -#~ msgid "集群名:【{}】 已存在,请修改" -#~ msgstr "集群名:【{}】 已存在,请修改" - -#~ msgid "集群容量" -#~ msgstr "集群容量" - -#~ msgid "{}({} x {}分片)" -#~ msgstr "{}({} x {}分片)" - -#~ msgid "集群架构" -#~ msgstr "集群架构" - -#~ msgid "Proxy代理端口" -#~ msgstr "Proxy代理端口" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" -#~ " 文件匹配: {}\n" -#~ msgstr "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" -#~ " 文件匹配: {}\n" - -#~ msgid "删除规则" -#~ msgstr "删除规则" - -#~ msgid "删除结果" -#~ msgstr "删除结果" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" -#~ msgstr "" -#~ "集群[{}]:{}\n" -#~ " 正则匹配: 包含-> ({}), 排除-> ({})\n" - -#~ msgid "提取规则" -#~ msgstr "提取规则" - -#~ msgid "提取结果" -#~ msgstr "提取结果" - -#~ msgid "" -#~ "集群[{}]:{}\n" -#~ " 集群架构: {}\n" -#~ " 强制清档: {}\n" -#~ " 清档前备份: {}\n" -#~ " 目标DB: {}\n" -#~ msgstr "" -#~ "集群[{}]:{}\n" -#~ " 集群架构: {}\n" -#~ " 强制清档: {}\n" -#~ " 清档前备份: {}\n" -#~ " 目标DB: {}\n" - -#~ msgid "是" -#~ msgstr "是" +#, fuzzy +#~| msgid "下发actuator" +#~ msgid "中控Master下发DB-actuator" +#~ msgstr "下发actuator" -#~ msgid "否" -#~ msgstr "否" +#~ msgid "[{}]根据单据类型活动节点找不到对应的授权方式。" +#~ msgstr "[{}]根据单据类型活动节点找不到对应的授权方式。" -#~ msgid "全部" -#~ msgstr "全部" +#~ msgid "HDFS 集群停用" +#~ msgstr "HDFS 集群停用" -#~ msgid "清档规则" -#~ msgstr "清档规则" +#~ msgid "InfluxDB 实例停用" +#~ msgstr "InfluxDB 实例停用" From e55583e1918240a57b3fbe642cb29c36cd3aaddc Mon Sep 17 00:00:00 2001 From: daryl Date: Tue, 20 Jun 2023 19:45:14 +0800 Subject: [PATCH 039/476] =?UTF-8?q?fix(frontend):=20=E8=B0=83=E6=95=B4=20i?= =?UTF-8?q?con-cool=20=E5=BC=95=E5=85=A5=E6=96=B9=E5=BC=8F=20#186?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 1 - dbm-ui/frontend/public/bk-icon/demo.html | 1783 +++++++++++++++++ .../public/bk-icon/fonts/iconcool.eot | Bin 0 -> 38248 bytes .../public/bk-icon/fonts/iconcool.svg | 515 +++++ .../public/bk-icon/fonts/iconcool.ttf | Bin 0 -> 38080 bytes .../public/bk-icon/fonts/iconcool.woff | Bin 0 -> 21900 bytes dbm-ui/frontend/public/bk-icon/iconcool.js | 10 + dbm-ui/frontend/public/bk-icon/iconcool.json | 1 + dbm-ui/frontend/public/bk-icon/style.css | 505 +++++ dbm-ui/frontend/src/main.ts | 2 +- dbm-ui/frontend/src/styles/iconCool.less | 2 +- dbm-ui/frontend/tsconfig.json | 1 + dbm-ui/frontend/vite.config.ts | 1 + 13 files changed, 2818 insertions(+), 3 deletions(-) create mode 100644 dbm-ui/frontend/public/bk-icon/demo.html create mode 100644 dbm-ui/frontend/public/bk-icon/fonts/iconcool.eot create mode 100644 dbm-ui/frontend/public/bk-icon/fonts/iconcool.svg create mode 100644 dbm-ui/frontend/public/bk-icon/fonts/iconcool.ttf create mode 100644 dbm-ui/frontend/public/bk-icon/fonts/iconcool.woff create mode 100644 dbm-ui/frontend/public/bk-icon/iconcool.js create mode 100644 dbm-ui/frontend/public/bk-icon/iconcool.json create mode 100644 dbm-ui/frontend/public/bk-icon/style.css diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index e156793fe6..114117064f 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -16,7 +16,6 @@ "@blueking/bk-weweb": "^0.0.15", "@blueking/bkflow.js": "^0.1.10", "@blueking/ip-selector": "0.0.1-beta.101", - "@tencent/bk-icon-dbm": "0.2.14", "@vueuse/core": "^10.1.2", "axios": "^1.2.1", "bkui-vue": "0.0.1-beta.425", diff --git a/dbm-ui/frontend/public/bk-icon/demo.html b/dbm-ui/frontend/public/bk-icon/demo.html new file mode 100644 index 0000000000..f8eec69c4f --- /dev/null +++ b/dbm-ui/frontend/public/bk-icon/demo.html @@ -0,0 +1,1783 @@ + + + + + + + + + Icon Cool + + +

+

+ +

+
+
单色图标
+
彩色图标
+
+
+
    +
  • + +

    check-circle-fill

    +
  • +
  • + +

    exclamation-fill

    +
  • +
  • + +

    auth

    +
  • +
  • + +

    apply

    +
  • +
  • + +

    close-circle-shape

    +
  • +
  • + +

    right-shape

    +
  • +
  • + +

    bulk-edit

    +
  • +
  • + +

    funnel

    +
  • +
  • + +

    keyboard

    +
  • +
  • + +

    draft

    +
  • +
  • + +

    todolist

    +
  • +
  • + +

    file

    +
  • +
  • + +

    script

    +
  • +
  • + +

    fast-script

    +
  • +
  • + +

    homepage

    +
  • +
  • + +

    template

    +
  • +
  • + +

    unlock-line

    +
  • +
  • + +

    sync-failed

    +
  • +
  • + +

    sync-pending

    +
  • +
  • + +

    sync-success

    +
  • +
  • + +

    sync-default

    +
  • +
  • + +

    pulsar

    +
  • +
  • + +

    abnormal

    +
  • +
  • + +

    normal

    +
  • +
  • + +

    unknown

    +
  • +
  • + +

    code

    +
  • +
  • + +

    visible1

    +
  • +
  • + +

    sync-waiting-01

    +
  • +
  • + +

    script-template

    +
  • +
  • + +

    version

    +
  • +
  • + +

    copy

    +
  • +
  • + +

    database

    +
  • +
  • + +

    eyes

    +
  • +
  • + +

    setting-fill

    +
  • +
  • + +

    resource

    +
  • +
  • + +

    ticket

    +
  • +
  • + +

    edit

    +
  • +
  • + +

    loading

    +
  • +
  • + +

    help-fill

    +
  • +
  • + +

    unlock-line-2

    +
  • +
  • + +

    lock-fill

    +
  • +
  • + +

    un-full-screen

    +
  • +
  • + +

    full-screen

    +
  • +
  • + +

    minus-fill

    +
  • +
  • + +

    plus-fill

    +
  • +
  • + +

    add

    +
  • +
  • + +

    delete-fill

    +
  • +
  • + +

    refresh

    +
  • +
  • + +

    more

    +
  • +
  • + +

    arrow-fill

    +
  • +
  • + +

    attention-fill

    +
  • +
  • + +

    attention

    +
  • +
  • + +

    up-big

    +
  • +
  • + +

    down-big

    +
  • +
  • + +

    arrow-down

    +
  • +
  • + +

    arrow-up

    +
  • +
  • + +

    right-big

    +
  • +
  • + +

    arrow-right

    +
  • +
  • + +

    arrow-left

    +
  • +
  • + +

    mysql

    +
  • +
  • + +

    redis

    +
  • +
  • + +

    mongo-db

    +
  • +
  • + +

    kafka

    +
  • +
  • + +

    approval-node

    +
  • +
  • + +

    down-shape

    +
  • +
  • + +

    import

    +
  • +
  • + +

    master

    +
  • +
  • + +

    cluster

    +
  • +
  • + +

    host

    +
  • +
  • + +

    proxy

    +
  • +
  • + +

    node

    +
  • +
  • + +

    check

    +
  • +
  • + +

    deploy

    +
  • +
  • + +

    switch

    +
  • +
  • + +

    refresh-2

    +
  • +
  • + +

    stop

    +
  • +
  • + +

    dns

    +
  • +
  • + +

    member

    +
  • +
  • + +

    spec

    +
  • +
  • + +

    timed-task

    +
  • +
  • + +

    history

    +
  • +
  • + +

    backup

    +
  • +
  • + +

    account

    +
  • +
  • + +

    note

    +
  • +
  • + +

    single-node

    +
  • +
  • + +

    dba-config

    +
  • +
  • + +

    db-config

    +
  • +
  • + +

    default-node

    +
  • +
  • + +

    position

    +
  • +
  • + +

    plus-circle

    +
  • +
  • + +

    minus-circle

    +
  • +
  • + +

    rtx

    +
  • +
  • + +

    expand-line

    +
  • +
  • + +

    star

    +
  • +
  • + +

    search

    +
  • +
  • + +

    plus-8

    +
  • +
  • + +

    star-fill

    +
  • +
  • + +

    unlock

    +
  • +
  • + +

    return

    +
  • +
  • + +

    link

    +
  • +
  • + +

    new

    +
  • +
  • + +

    drag

    +
  • +
  • + +

    warning-2

    +
  • +
  • + +

    exclamation

    +
  • +
  • + +

    close

    +
  • +
  • + +

    check-line

    +
  • +
  • + +

    early-warning

    +
  • +
  • + +

    warning

    +
  • +
  • + +

    spce

    +
  • +
  • + +

    password

    +
  • +
  • + +

    redis-2

    +
  • +
  • + +

    mysql-2

    +
  • +
  • + +

    es

    +
  • +
  • + +

    hdfs

    +
  • +
  • + +

    delete

    +
  • +
  • + +

    excel

    +
  • +
  • + +

    history-2

    +
  • +
  • + +

    migration

    +
  • +
  • + +

    switch-2

    +
  • +
  • + +

    remote

    +
  • +
  • + +

    clearing

    +
  • +
  • + +

    alert

    +
  • +
  • + +

    rebuild

    +
  • +
  • + +

    clone

    +
  • +
  • + +

    associated

    +
  • +
  • + +

    rollback

    +
  • +
  • + +

    data

    +
  • +
  • + +

    audit

    +
  • +
  • + +

    yijinyong

    +
  • +
  • + +

    kuorongzhong

    +
  • +
  • + +

    zhongqizhong

    +
  • +
  • + +

    suorongzhong

    +
  • +
  • + +

    tihuanzong

    +
  • +
  • + +

    shanchuzhong

    +
  • +
  • + +

    jinyongzhong

    +
  • +
  • + +

    qiyongzhong

    +
  • +
  • + +

    help-fill-2

    +
  • +
  • + +

    2-jiantou-you

    +
  • +
  • + +

    2-jiantou-zuo

    +
  • +
  • + +

    tools

    +
  • +
  • + +

    todos

    +
  • +
  • + +

    manual

    +
  • +
  • + +

    minimap

    +
  • +
  • + +

    backup-2

    +
  • +
  • + +

    host-select

    +
  • +
  • + +

    batch-host-select

    +
  • +
  • + +

    revoke

    +
  • +
  • + +

    en

    +
  • +
  • + +

    cn

    +
  • +
  • + +

    list

    +
  • +
  • + +

    influxdb

    +
  • +
  • + +

    summation

    +
  • +
  • + +

    folder-open

    +
  • +
  • + +

    wenjian

    +
  • +
  • + +

    drag

    +
  • +
  • + +

    gaokeyong

    +
  • +
  • + +

    fenbushijiqun

    +
  • +
  • + +

    danjiedian

    +
  • +
  • + +

    zhongkongji

    +
  • +
  • + +

    wenjian

    +
  • +
+

为什么使用

+
    +
  • 弹性,在网页或者 app 上,展示字体是很便捷的。用字体图标可以很方便的改变 icon 的颜色,或者加入一些其他的效果
  • +
  • 可缩放,可以很方便的改变图标的大小
  • +
  • 矢量,字体图标是矢量的并且具有独立的分辨率,不管在高分辨率还是低分辨率,不管是在网页还是手机端,都具有很好的展示效果,不会出现锯齿或者马赛克模糊
  • +
  • 节省加载时间,字体图标很小,每个小图标只有几 kb,大大节省了加载时间
  • +
+

如何使用

+
    +
  • 将整个目录复制到您的项目里
  • +
  • 引入 style.css
  • +
  • 挑选相应图标并获取类名,如 .bk-icon .icon-demo
  • +
+
+
+
    +
  • + + + +

    check-circle-fill

    +
  • +
  • + + + +

    exclamation-fill

    +
  • +
  • + + + +

    auth

    +
  • +
  • + + + +

    apply

    +
  • +
  • + + + +

    close-circle-shape

    +
  • +
  • + + + +

    right-shape

    +
  • +
  • + + + +

    bulk-edit

    +
  • +
  • + + + +

    funnel

    +
  • +
  • + + + +

    keyboard

    +
  • +
  • + + + +

    draft

    +
  • +
  • + + + +

    todolist

    +
  • +
  • + + + +

    file

    +
  • +
  • + + + +

    script

    +
  • +
  • + + + +

    fast-script

    +
  • +
  • + + + +

    homepage

    +
  • +
  • + + + +

    template

    +
  • +
  • + + + +

    unlock-line

    +
  • +
  • + + + +

    sync-failed

    +
  • +
  • + + + +

    sync-pending

    +
  • +
  • + + + +

    sync-success

    +
  • +
  • + + + +

    sync-default

    +
  • +
  • + + + +

    pulsar

    +
  • +
  • + + + +

    abnormal

    +
  • +
  • + + + +

    normal

    +
  • +
  • + + + +

    unknown

    +
  • +
  • + + + +

    code

    +
  • +
  • + + + +

    visible1

    +
  • +
  • + + + +

    sync-waiting-01

    +
  • +
  • + + + +

    script-template

    +
  • +
  • + + + +

    version

    +
  • +
  • + + + +

    copy

    +
  • +
  • + + + +

    database

    +
  • +
  • + + + +

    eyes

    +
  • +
  • + + + +

    setting-fill

    +
  • +
  • + + + +

    resource

    +
  • +
  • + + + +

    ticket

    +
  • +
  • + + + +

    edit

    +
  • +
  • + + + +

    loading

    +
  • +
  • + + + +

    help-fill

    +
  • +
  • + + + +

    unlock-line-2

    +
  • +
  • + + + +

    lock-fill

    +
  • +
  • + + + +

    un-full-screen

    +
  • +
  • + + + +

    full-screen

    +
  • +
  • + + + +

    minus-fill

    +
  • +
  • + + + +

    plus-fill

    +
  • +
  • + + + +

    add

    +
  • +
  • + + + +

    delete-fill

    +
  • +
  • + + + +

    refresh

    +
  • +
  • + + + +

    more

    +
  • +
  • + + + +

    arrow-fill

    +
  • +
  • + + + +

    attention-fill

    +
  • +
  • + + + +

    attention

    +
  • +
  • + + + +

    up-big

    +
  • +
  • + + + +

    down-big

    +
  • +
  • + + + +

    arrow-down

    +
  • +
  • + + + +

    arrow-up

    +
  • +
  • + + + +

    right-big

    +
  • +
  • + + + +

    arrow-right

    +
  • +
  • + + + +

    arrow-left

    +
  • +
  • + + + +

    mysql

    +
  • +
  • + + + +

    redis

    +
  • +
  • + + + +

    mongo-db

    +
  • +
  • + + + +

    kafka

    +
  • +
  • + + + +

    approval-node

    +
  • +
  • + + + +

    down-shape

    +
  • +
  • + + + +

    import

    +
  • +
  • + + + +

    master

    +
  • +
  • + + + +

    cluster

    +
  • +
  • + + + +

    host

    +
  • +
  • + + + +

    proxy

    +
  • +
  • + + + +

    node

    +
  • +
  • + + + +

    check

    +
  • +
  • + + + +

    deploy

    +
  • +
  • + + + +

    switch

    +
  • +
  • + + + +

    refresh-2

    +
  • +
  • + + + +

    stop

    +
  • +
  • + + + +

    dns

    +
  • +
  • + + + +

    member

    +
  • +
  • + + + +

    spec

    +
  • +
  • + + + +

    timed-task

    +
  • +
  • + + + +

    history

    +
  • +
  • + + + +

    backup

    +
  • +
  • + + + +

    account

    +
  • +
  • + + + +

    note

    +
  • +
  • + + + +

    single-node

    +
  • +
  • + + + +

    dba-config

    +
  • +
  • + + + +

    db-config

    +
  • +
  • + + + +

    default-node

    +
  • +
  • + + + +

    position

    +
  • +
  • + + + +

    plus-circle

    +
  • +
  • + + + +

    minus-circle

    +
  • +
  • + + + +

    rtx

    +
  • +
  • + + + +

    expand-line

    +
  • +
  • + + + +

    star

    +
  • +
  • + + + +

    search

    +
  • +
  • + + + +

    plus-8

    +
  • +
  • + + + +

    star-fill

    +
  • +
  • + + + +

    unlock

    +
  • +
  • + + + +

    return

    +
  • +
  • + + + +

    link

    +
  • +
  • + + + +

    new

    +
  • +
  • + + + +

    drag

    +
  • +
  • + + + +

    warning-2

    +
  • +
  • + + + +

    exclamation

    +
  • +
  • + + + +

    close

    +
  • +
  • + + + +

    check-line

    +
  • +
  • + + + +

    early-warning

    +
  • +
  • + + + +

    warning

    +
  • +
  • + + + +

    spce

    +
  • +
  • + + + +

    password

    +
  • +
  • + + + +

    redis-2

    +
  • +
  • + + + +

    mysql-2

    +
  • +
  • + + + +

    es

    +
  • +
  • + + + +

    hdfs

    +
  • +
  • + + + +

    delete

    +
  • +
  • + + + +

    excel

    +
  • +
  • + + + +

    history-2

    +
  • +
  • + + + +

    migration

    +
  • +
  • + + + +

    switch-2

    +
  • +
  • + + + +

    remote

    +
  • +
  • + + + +

    clearing

    +
  • +
  • + + + +

    alert

    +
  • +
  • + + + +

    rebuild

    +
  • +
  • + + + +

    clone

    +
  • +
  • + + + +

    associated

    +
  • +
  • + + + +

    rollback

    +
  • +
  • + + + +

    data

    +
  • +
  • + + + +

    audit

    +
  • +
  • + + + +

    yijinyong

    +
  • +
  • + + + +

    kuorongzhong

    +
  • +
  • + + + +

    zhongqizhong

    +
  • +
  • + + + +

    suorongzhong

    +
  • +
  • + + + +

    tihuanzong

    +
  • +
  • + + + +

    shanchuzhong

    +
  • +
  • + + + +

    jinyongzhong

    +
  • +
  • + + + +

    qiyongzhong

    +
  • +
  • + + + +

    help-fill-2

    +
  • +
  • + + + +

    2-jiantou-you

    +
  • +
  • + + + +

    2-jiantou-zuo

    +
  • +
  • + + + +

    tools

    +
  • +
  • + + + +

    todos

    +
  • +
  • + + + +

    manual

    +
  • +
  • + + + +

    minimap

    +
  • +
  • + + + +

    backup-2

    +
  • +
  • + + + +

    host-select

    +
  • +
  • + + + +

    batch-host-select

    +
  • +
  • + + + +

    revoke

    +
  • +
  • + + + +

    en

    +
  • +
  • + + + +

    cn

    +
  • +
  • + + + +

    list

    +
  • +
  • + + + +

    influxdb

    +
  • +
  • + + + +

    summation

    +
  • +
  • + + + +

    folder-open

    +
  • +
  • + + + +

    wenjian

    +
  • +
  • + + + +

    drag

    +
  • +
  • + + + +

    gaokeyong

    +
  • +
  • + + + +

    fenbushijiqun

    +
  • +
  • + + + +

    danjiedian

    +
  • +
  • + + + +

    zhongkongji

    +
  • +
  • + + + +

    wenjian

    +
  • +
+

为什么使用

+
    +
  • 支持彩色图标
  • +
  • 跨 SVG 使用,使用 use 可调用文档中加载的所有 SVG 图标
  • +
+

如何使用

+
    +
  • 将下载的资源文件中 iconcool.js 文件外部资源通过 script 标签引入
  • +
  • 在 html 模板文件中挑选对应的对应图标的名称使用,例如: +
    +    <svg aria-hidden="true">
    +      <use xlink:href="#icon-xxx"></use>
    +    </svg>
    +          
    +
  • +
+
+ +
+ + + \ No newline at end of file diff --git a/dbm-ui/frontend/public/bk-icon/fonts/iconcool.eot b/dbm-ui/frontend/public/bk-icon/fonts/iconcool.eot new file mode 100644 index 0000000000000000000000000000000000000000..c05fc100aa107c46f39901177525ccdc98ce05cf GIT binary patch literal 38248 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 _rm=yozn>Dm`4Bx%o?D^ zb0Jkbs0MY)3uPO@ve6cRi$?M7(`C(r({{vGi_|$tGJtphkU7rV20p!@Zh#4SK57^z zdpW+Q{3d;aUN0Db(C<|opu(U3Im}vM1~Q)wJM(Mx00n`7s>SHE5ICqs@NB)9mf&SqJuSniyBt1h!$2!EQj}s8 z#}qe7P1KAl1^yH<0$hP{ElnB9QX3WlR%7k_N?L<4?+f%rpsB9LNOBEbOC4BEzm7Vo z3v22(z>d;-+JN_vH_^>NTWzLp>Y-k|mCQjyWeaXh{j?41?gO-)25AVR)>kM`BQ#1o zXeW))t+We|_P0Z)U^jggNUd?&Lw5kLbtip|?xMS)WpEF075CD8bU)A)57I-lA7-2m z(8F|)9-&9+5cKCCqr>#Lg>JR)80=paPA7~I_Yr+R7BRwT)Ce=Hj4*BHua@*SNtgU+ z%-DzXO`Q*Pw~bKv$HK;bEGcx79v8Y~)<{nZ|D^EE2z^rM8=DNetdy5b8~cqy7ZZLV zkvAmehNNC0saHsj51I6Gd|JYgloQGr{6ivNNaPELjP$VZ4-5aW@Cyr{ueZq2l zM2?Th@ez?XB77nuXGG+T2;YdbLqzyTgnvZZAtLg|%;QAvh@7uRv%Q3_QSuu_zDAQy zlKM4CIcYgA zE%ixDd1>LF7XE3GJ1zXv!Y3`|q=jEb_+^A&M&! + + + + Created by font-carrier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dbm-ui/frontend/public/bk-icon/fonts/iconcool.ttf b/dbm-ui/frontend/public/bk-icon/fonts/iconcool.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d3c679e3b9978dbbafb7812c32358df9be89314f GIT binary patch literal 38080 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 literal 0 HcmV?d00001 diff --git a/dbm-ui/frontend/public/bk-icon/fonts/iconcool.woff b/dbm-ui/frontend/public/bk-icon/fonts/iconcool.woff new file mode 100644 index 0000000000000000000000000000000000000000..cb9c59354d1cc583d9218c3f476585cced447eed GIT binary patch literal 21900 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 McRKF?mi>l}0M3`l_y7O^ literal 0 HcmV?d00001 diff --git a/dbm-ui/frontend/public/bk-icon/iconcool.js b/dbm-ui/frontend/public/bk-icon/iconcool.js new file mode 100644 index 0000000000..77bde219d2 --- /dev/null +++ b/dbm-ui/frontend/public/bk-icon/iconcool.js @@ -0,0 +1,10 @@ +!(function () { + var svgCode = '' + if (document.body) { + document.body.insertAdjacentHTML('afterbegin', svgCode) + } else { + document.addEventListener('DOMContentLoaded', function() { + document.body.insertAdjacentHTML('afterbegin', svgCode) + }) + } +})() \ No newline at end of file diff --git a/dbm-ui/frontend/public/bk-icon/iconcool.json b/dbm-ui/frontend/public/bk-icon/iconcool.json new file mode 100644 index 0000000000..74cc17f433 --- /dev/null +++ b/dbm-ui/frontend/public/bk-icon/iconcool.json @@ -0,0 +1 @@ +{"iconName":"bk-dbm","icons":[{"name":"check-circle-fill","svgCode":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n","codepoint":"\\e1a7"},{"name":"exclamation-fill","svgCode":"\n\n\n\n\n\n","codepoint":"\\e173"},{"name":"auth","svgCode":"","codepoint":"\\e152"},{"name":"apply","svgCode":"","codepoint":"\\e144"},{"name":"close-circle-shape","svgCode":"","codepoint":"\\e1be"},{"name":"right-shape","svgCode":"","codepoint":"\\e1a3"},{"name":"bulk-edit","svgCode":"","codepoint":"\\e15f"},{"name":"funnel","svgCode":"","codepoint":"\\e1bd"},{"name":"keyboard","svgCode":"","codepoint":"\\e1ae"},{"name":"draft","svgCode":"","codepoint":"\\e145"},{"name":"todolist","svgCode":"","codepoint":"\\e146"},{"name":"file","svgCode":"","codepoint":"\\e136"},{"name":"script","svgCode":"","codepoint":"\\e137"},{"name":"fast-script","svgCode":"","codepoint":"\\e151"},{"name":"homepage","svgCode":"","codepoint":"\\e158"},{"name":"template","svgCode":"","codepoint":"\\e147"},{"name":"unlock-line","svgCode":"","codepoint":"\\e166"},{"name":"sync-failed","svgCode":"","codepoint":"\\e18c"},{"name":"sync-pending","svgCode":"","codepoint":"\\e18f"},{"name":"sync-success","svgCode":"","codepoint":"\\e18d"},{"name":"sync-default","svgCode":"","codepoint":"\\e18e"},{"name":"pulsar","svgCode":"","codepoint":"\\e1b8"},{"name":"abnormal","svgCode":"","codepoint":"\\e187"},{"name":"normal","svgCode":"","codepoint":"\\e188"},{"name":"unknown","svgCode":"","codepoint":"\\e189"},{"name":"code","svgCode":"","codepoint":"\\e139"},{"name":"visible1","svgCode":"","codepoint":"\\e1c5"},{"name":"sync-waiting-01","svgCode":"","codepoint":"\\e18a"},{"name":"script-template","svgCode":"","codepoint":"\\e138"},{"name":"version","svgCode":"","codepoint":"\\e156"},{"name":"copy","svgCode":"","codepoint":"\\e103"},{"name":"database","svgCode":"","codepoint":"\\e101"},{"name":"eyes","svgCode":"","codepoint":"\\e102"},{"name":"setting-fill","svgCode":"","codepoint":"\\e104"},{"name":"resource","svgCode":"","codepoint":"\\e105"},{"name":"ticket","svgCode":"","codepoint":"\\e106"},{"name":"edit","svgCode":"","codepoint":"\\e108"},{"name":"loading","svgCode":"","codepoint":"\\e1a8"},{"name":"help-fill","svgCode":"","codepoint":"\\e109"},{"name":"unlock-line-2","svgCode":"","codepoint":"\\e10b"},{"name":"lock-fill","svgCode":"","codepoint":"\\e10c"},{"name":"un-full-screen","svgCode":"","codepoint":"\\e10f"},{"name":"full-screen","svgCode":"","codepoint":"\\e110"},{"name":"minus-fill","svgCode":"","codepoint":"\\e111"},{"name":"plus-fill","svgCode":"","codepoint":"\\e112"},{"name":"add","svgCode":"","codepoint":"\\e116"},{"name":"delete-fill","svgCode":"","codepoint":"\\e117"},{"name":"refresh","svgCode":"","codepoint":"\\e118"},{"name":"more","svgCode":"","codepoint":"\\e119"},{"name":"arrow-fill","svgCode":"","codepoint":"\\e11e"},{"name":"attention-fill","svgCode":"","codepoint":"\\e11f"},{"name":"attention","svgCode":"","codepoint":"\\e120"},{"name":"up-big","svgCode":"","codepoint":"\\e121"},{"name":"down-big","svgCode":"","codepoint":"\\e123"},{"name":"arrow-down","svgCode":"","codepoint":"\\e122"},{"name":"arrow-up","svgCode":"","codepoint":"\\e124"},{"name":"right-big","svgCode":"","codepoint":"\\e125"},{"name":"arrow-right","svgCode":"","codepoint":"\\e126"},{"name":"arrow-left","svgCode":"","codepoint":"\\e127"},{"name":"mysql","svgCode":"","codepoint":"\\e128"},{"name":"redis","svgCode":"","codepoint":"\\e129"},{"name":"mongo-db","svgCode":"","codepoint":"\\e12a"},{"name":"kafka","svgCode":"","codepoint":"\\e12b"},{"name":"approval-node","svgCode":"","codepoint":"\\e155"},{"name":"down-shape","svgCode":"","codepoint":"\\e12c"},{"name":"import","svgCode":"","codepoint":"\\e12d"},{"name":"master","svgCode":"","codepoint":"\\e13a"},{"name":"cluster","svgCode":"","codepoint":"\\e13b"},{"name":"host","svgCode":"","codepoint":"\\e13c"},{"name":"proxy","svgCode":"","codepoint":"\\e13e"},{"name":"node","svgCode":"","codepoint":"\\e13d"},{"name":"check","svgCode":"","codepoint":"\\e13f"},{"name":"deploy","svgCode":"","codepoint":"\\e140"},{"name":"switch","svgCode":"","codepoint":"\\e141"},{"name":"refresh-2","svgCode":"","codepoint":"\\e142"},{"name":"stop","svgCode":"","codepoint":"\\e143"},{"name":"dns","svgCode":"","codepoint":"\\e148"},{"name":"member","svgCode":"","codepoint":"\\e14c"},{"name":"spec","svgCode":"","codepoint":"\\e149"},{"name":"timed-task","svgCode":"","codepoint":"\\e14d"},{"name":"history","svgCode":"","codepoint":"\\e14a"},{"name":"backup","svgCode":"","codepoint":"\\e14f"},{"name":"account","svgCode":"","codepoint":"\\e14b"},{"name":"note","svgCode":"","codepoint":"\\e150"},{"name":"single-node","svgCode":"","codepoint":"\\e14e"},{"name":"dba-config","svgCode":"","codepoint":"\\e154"},{"name":"db-config","svgCode":"","codepoint":"\\e157"},{"name":"default-node","svgCode":"","codepoint":"\\e159"},{"name":"position","svgCode":"","codepoint":"\\e15c"},{"name":"plus-circle","svgCode":"","codepoint":"\\e15d"},{"name":"minus-circle","svgCode":"","codepoint":"\\e15e"},{"name":"rtx","svgCode":"","codepoint":"\\e160"},{"name":"expand-line","svgCode":"","codepoint":"\\e161"},{"name":"star","svgCode":"","codepoint":"\\e162"},{"name":"search","svgCode":"","codepoint":"\\e163"},{"name":"plus-8","svgCode":"","codepoint":"\\e164"},{"name":"star-fill","svgCode":"","codepoint":"\\e165"},{"name":"unlock","svgCode":"","codepoint":"\\e167"},{"name":"return","svgCode":"","codepoint":"\\e168"},{"name":"link","svgCode":"","codepoint":"\\e169"},{"name":"new","svgCode":"","codepoint":"\\e16b"},{"name":"drag","svgCode":"","codepoint":"\\e1a4"},{"name":"warning-2","svgCode":"","codepoint":"\\e18b"},{"name":"exclamation","svgCode":"","codepoint":"\\e16c"},{"name":"close","svgCode":"","codepoint":"\\e16d"},{"name":"check-line","svgCode":"","codepoint":"\\e16e"},{"name":"early-warning","svgCode":"","codepoint":"\\e16f"},{"name":"warning","svgCode":"","codepoint":"\\e170"},{"name":"spce","svgCode":"","codepoint":"\\e171"},{"name":"password","svgCode":"","codepoint":"\\e172"},{"name":"redis-2","svgCode":"","codepoint":"\\e176"},{"name":"mysql-2","svgCode":"","codepoint":"\\e174"},{"name":"es","svgCode":"","codepoint":"\\e177"},{"name":"hdfs","svgCode":"","codepoint":"\\e175"},{"name":"delete","svgCode":"","codepoint":"\\e178"},{"name":"excel","svgCode":"","codepoint":"\\e179"},{"name":"history-2","svgCode":"","codepoint":"\\e17a"},{"name":"migration","svgCode":"","codepoint":"\\e17d"},{"name":"switch-2","svgCode":"","codepoint":"\\e17e"},{"name":"remote","svgCode":"","codepoint":"\\e17f"},{"name":"clearing","svgCode":"","codepoint":"\\e180"},{"name":"alert","svgCode":"","codepoint":"\\e181"},{"name":"rebuild","svgCode":"","codepoint":"\\e182"},{"name":"clone","svgCode":"","codepoint":"\\e183"},{"name":"associated","svgCode":"","codepoint":"\\e184"},{"name":"rollback","svgCode":"","codepoint":"\\e185"},{"name":"data","svgCode":"","codepoint":"\\e186"},{"name":"audit","svgCode":"","codepoint":"\\e190"},{"name":"yijinyong","svgCode":"","codepoint":"\\e19a"},{"name":"kuorongzhong","svgCode":"","codepoint":"\\e19d"},{"name":"zhongqizhong","svgCode":"","codepoint":"\\e19b"},{"name":"suorongzhong","svgCode":"","codepoint":"\\e19e"},{"name":"tihuanzong","svgCode":"","codepoint":"\\e19c"},{"name":"shanchuzhong","svgCode":"","codepoint":"\\e19f"},{"name":"jinyongzhong","svgCode":"","codepoint":"\\e1a0"},{"name":"qiyongzhong","svgCode":"","codepoint":"\\e1a1"},{"name":"help-fill-2","svgCode":"","codepoint":"\\e1a2"},{"name":"2-jiantou-you","svgCode":"","codepoint":"\\e1a5"},{"name":"2-jiantou-zuo","svgCode":"","codepoint":"\\e1a6"},{"name":"tools","svgCode":"","codepoint":"\\e1a9"},{"name":"todos","svgCode":"","codepoint":"\\e1aa"},{"name":"manual","svgCode":"","codepoint":"\\e1ac"},{"name":"minimap","svgCode":"","codepoint":"\\e1ad"},{"name":"backup-2","svgCode":"","codepoint":"\\e1af"},{"name":"host-select","svgCode":"","codepoint":"\\e1b0"},{"name":"batch-host-select","svgCode":"","codepoint":"\\e1b1"},{"name":"revoke","svgCode":"","codepoint":"\\e1b3"},{"name":"en","svgCode":"","codepoint":"\\e1b4"},{"name":"cn","svgCode":"","codepoint":"\\e1b5"},{"name":"list","svgCode":"","codepoint":"\\e1b7"},{"name":"influxdb","svgCode":"","codepoint":"\\e1ba"},{"name":"summation","svgCode":"","codepoint":"\\e1bb"},{"name":"folder-open","svgCode":"","codepoint":"\\e1bc"},{"name":"wenjian","svgCode":"","codepoint":"\\e1bf"},{"name":"drag","svgCode":"","codepoint":"\\e1c0"},{"name":"gaokeyong","svgCode":"","codepoint":"\\e1c2"},{"name":"fenbushijiqun","svgCode":"","codepoint":"\\e1c3"},{"name":"danjiedian","svgCode":"","codepoint":"\\e1c1"},{"name":"zhongkongji","svgCode":"","codepoint":"\\e1c4"},{"name":"wenjian","svgCode":"","codepoint":"\\e1c6"}]} \ No newline at end of file diff --git a/dbm-ui/frontend/public/bk-icon/style.css b/dbm-ui/frontend/public/bk-icon/style.css new file mode 100644 index 0000000000..84ca0d74ef --- /dev/null +++ b/dbm-ui/frontend/public/bk-icon/style.css @@ -0,0 +1,505 @@ +@font-face { + font-family: "bk-dbm"; + src: url("fonts/iconcool.svg#iconcool") format("svg"), +url("fonts/iconcool.ttf") format("truetype"), +url("fonts/iconcool.woff") format("woff"), +url("fonts/iconcool.eot?#iefix") format("embedded-opentype"); + font-weight: normal; + font-style: normal; +} + +.bk-dbm-icon { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'bk-dbm' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + text-align: center; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.db-icon-check-circle-fill:before { + content: "\e1a7"; +} +.db-icon-exclamation-fill:before { + content: "\e173"; +} +.db-icon-auth:before { + content: "\e152"; +} +.db-icon-apply:before { + content: "\e144"; +} +.db-icon-close-circle-shape:before { + content: "\e1be"; +} +.db-icon-right-shape:before { + content: "\e1a3"; +} +.db-icon-bulk-edit:before { + content: "\e15f"; +} +.db-icon-funnel:before { + content: "\e1bd"; +} +.db-icon-keyboard:before { + content: "\e1ae"; +} +.db-icon-draft:before { + content: "\e145"; +} +.db-icon-todolist:before { + content: "\e146"; +} +.db-icon-file:before { + content: "\e136"; +} +.db-icon-script:before { + content: "\e137"; +} +.db-icon-fast-script:before { + content: "\e151"; +} +.db-icon-homepage:before { + content: "\e158"; +} +.db-icon-template:before { + content: "\e147"; +} +.db-icon-unlock-line:before { + content: "\e166"; +} +.db-icon-sync-failed:before { + content: "\e18c"; +} +.db-icon-sync-pending:before { + content: "\e18f"; +} +.db-icon-sync-success:before { + content: "\e18d"; +} +.db-icon-sync-default:before { + content: "\e18e"; +} +.db-icon-pulsar:before { + content: "\e1b8"; +} +.db-icon-abnormal:before { + content: "\e187"; +} +.db-icon-normal:before { + content: "\e188"; +} +.db-icon-unknown:before { + content: "\e189"; +} +.db-icon-code:before { + content: "\e139"; +} +.db-icon-visible1:before { + content: "\e1c5"; +} +.db-icon-sync-waiting-01:before { + content: "\e18a"; +} +.db-icon-script-template:before { + content: "\e138"; +} +.db-icon-version:before { + content: "\e156"; +} +.db-icon-copy:before { + content: "\e103"; +} +.db-icon-database:before { + content: "\e101"; +} +.db-icon-eyes:before { + content: "\e102"; +} +.db-icon-setting-fill:before { + content: "\e104"; +} +.db-icon-resource:before { + content: "\e105"; +} +.db-icon-ticket:before { + content: "\e106"; +} +.db-icon-edit:before { + content: "\e108"; +} +.db-icon-loading:before { + content: "\e1a8"; +} +.db-icon-help-fill:before { + content: "\e109"; +} +.db-icon-unlock-line-2:before { + content: "\e10b"; +} +.db-icon-lock-fill:before { + content: "\e10c"; +} +.db-icon-un-full-screen:before { + content: "\e10f"; +} +.db-icon-full-screen:before { + content: "\e110"; +} +.db-icon-minus-fill:before { + content: "\e111"; +} +.db-icon-plus-fill:before { + content: "\e112"; +} +.db-icon-add:before { + content: "\e116"; +} +.db-icon-delete-fill:before { + content: "\e117"; +} +.db-icon-refresh:before { + content: "\e118"; +} +.db-icon-more:before { + content: "\e119"; +} +.db-icon-arrow-fill:before { + content: "\e11e"; +} +.db-icon-attention-fill:before { + content: "\e11f"; +} +.db-icon-attention:before { + content: "\e120"; +} +.db-icon-up-big:before { + content: "\e121"; +} +.db-icon-down-big:before { + content: "\e123"; +} +.db-icon-arrow-down:before { + content: "\e122"; +} +.db-icon-arrow-up:before { + content: "\e124"; +} +.db-icon-right-big:before { + content: "\e125"; +} +.db-icon-arrow-right:before { + content: "\e126"; +} +.db-icon-arrow-left:before { + content: "\e127"; +} +.db-icon-mysql:before { + content: "\e128"; +} +.db-icon-redis:before { + content: "\e129"; +} +.db-icon-mongo-db:before { + content: "\e12a"; +} +.db-icon-kafka:before { + content: "\e12b"; +} +.db-icon-approval-node:before { + content: "\e155"; +} +.db-icon-down-shape:before { + content: "\e12c"; +} +.db-icon-import:before { + content: "\e12d"; +} +.db-icon-master:before { + content: "\e13a"; +} +.db-icon-cluster:before { + content: "\e13b"; +} +.db-icon-host:before { + content: "\e13c"; +} +.db-icon-proxy:before { + content: "\e13e"; +} +.db-icon-node:before { + content: "\e13d"; +} +.db-icon-check:before { + content: "\e13f"; +} +.db-icon-deploy:before { + content: "\e140"; +} +.db-icon-switch:before { + content: "\e141"; +} +.db-icon-refresh-2:before { + content: "\e142"; +} +.db-icon-stop:before { + content: "\e143"; +} +.db-icon-dns:before { + content: "\e148"; +} +.db-icon-member:before { + content: "\e14c"; +} +.db-icon-spec:before { + content: "\e149"; +} +.db-icon-timed-task:before { + content: "\e14d"; +} +.db-icon-history:before { + content: "\e14a"; +} +.db-icon-backup:before { + content: "\e14f"; +} +.db-icon-account:before { + content: "\e14b"; +} +.db-icon-note:before { + content: "\e150"; +} +.db-icon-single-node:before { + content: "\e14e"; +} +.db-icon-dba-config:before { + content: "\e154"; +} +.db-icon-db-config:before { + content: "\e157"; +} +.db-icon-default-node:before { + content: "\e159"; +} +.db-icon-position:before { + content: "\e15c"; +} +.db-icon-plus-circle:before { + content: "\e15d"; +} +.db-icon-minus-circle:before { + content: "\e15e"; +} +.db-icon-rtx:before { + content: "\e160"; +} +.db-icon-expand-line:before { + content: "\e161"; +} +.db-icon-star:before { + content: "\e162"; +} +.db-icon-search:before { + content: "\e163"; +} +.db-icon-plus-8:before { + content: "\e164"; +} +.db-icon-star-fill:before { + content: "\e165"; +} +.db-icon-unlock:before { + content: "\e167"; +} +.db-icon-return:before { + content: "\e168"; +} +.db-icon-link:before { + content: "\e169"; +} +.db-icon-new:before { + content: "\e16b"; +} +.db-icon-drag:before { + content: "\e1a4"; +} +.db-icon-warning-2:before { + content: "\e18b"; +} +.db-icon-exclamation:before { + content: "\e16c"; +} +.db-icon-close:before { + content: "\e16d"; +} +.db-icon-check-line:before { + content: "\e16e"; +} +.db-icon-early-warning:before { + content: "\e16f"; +} +.db-icon-warning:before { + content: "\e170"; +} +.db-icon-spce:before { + content: "\e171"; +} +.db-icon-password:before { + content: "\e172"; +} +.db-icon-redis-2:before { + content: "\e176"; +} +.db-icon-mysql-2:before { + content: "\e174"; +} +.db-icon-es:before { + content: "\e177"; +} +.db-icon-hdfs:before { + content: "\e175"; +} +.db-icon-delete:before { + content: "\e178"; +} +.db-icon-excel:before { + content: "\e179"; +} +.db-icon-history-2:before { + content: "\e17a"; +} +.db-icon-migration:before { + content: "\e17d"; +} +.db-icon-switch-2:before { + content: "\e17e"; +} +.db-icon-remote:before { + content: "\e17f"; +} +.db-icon-clearing:before { + content: "\e180"; +} +.db-icon-alert:before { + content: "\e181"; +} +.db-icon-rebuild:before { + content: "\e182"; +} +.db-icon-clone:before { + content: "\e183"; +} +.db-icon-associated:before { + content: "\e184"; +} +.db-icon-rollback:before { + content: "\e185"; +} +.db-icon-data:before { + content: "\e186"; +} +.db-icon-audit:before { + content: "\e190"; +} +.db-icon-yijinyong:before { + content: "\e19a"; +} +.db-icon-kuorongzhong:before { + content: "\e19d"; +} +.db-icon-zhongqizhong:before { + content: "\e19b"; +} +.db-icon-suorongzhong:before { + content: "\e19e"; +} +.db-icon-tihuanzong:before { + content: "\e19c"; +} +.db-icon-shanchuzhong:before { + content: "\e19f"; +} +.db-icon-jinyongzhong:before { + content: "\e1a0"; +} +.db-icon-qiyongzhong:before { + content: "\e1a1"; +} +.db-icon-help-fill-2:before { + content: "\e1a2"; +} +.db-icon-2-jiantou-you:before { + content: "\e1a5"; +} +.db-icon-2-jiantou-zuo:before { + content: "\e1a6"; +} +.db-icon-tools:before { + content: "\e1a9"; +} +.db-icon-todos:before { + content: "\e1aa"; +} +.db-icon-manual:before { + content: "\e1ac"; +} +.db-icon-minimap:before { + content: "\e1ad"; +} +.db-icon-backup-2:before { + content: "\e1af"; +} +.db-icon-host-select:before { + content: "\e1b0"; +} +.db-icon-batch-host-select:before { + content: "\e1b1"; +} +.db-icon-revoke:before { + content: "\e1b3"; +} +.db-icon-en:before { + content: "\e1b4"; +} +.db-icon-cn:before { + content: "\e1b5"; +} +.db-icon-list:before { + content: "\e1b7"; +} +.db-icon-influxdb:before { + content: "\e1ba"; +} +.db-icon-summation:before { + content: "\e1bb"; +} +.db-icon-folder-open:before { + content: "\e1bc"; +} +.db-icon-wenjian:before { + content: "\e1bf"; +} +.db-icon-drag:before { + content: "\e1c0"; +} +.db-icon-gaokeyong:before { + content: "\e1c2"; +} +.db-icon-fenbushijiqun:before { + content: "\e1c3"; +} +.db-icon-danjiedian:before { + content: "\e1c1"; +} +.db-icon-zhongkongji:before { + content: "\e1c4"; +} +.db-icon-wenjian:before { + content: "\e1c6"; +} diff --git a/dbm-ui/frontend/src/main.ts b/dbm-ui/frontend/src/main.ts index df053ea0ae..55050c5472 100644 --- a/dbm-ui/frontend/src/main.ts +++ b/dbm-ui/frontend/src/main.ts @@ -26,7 +26,7 @@ import getRouter from './router'; import '@blueking/ip-selector/dist/styles/vue2.6.x.css'; import 'bkui-vue/dist/style.css'; import '@styles/common.less'; -import '@tencent/bk-icon-dbm/src/index'; +import '@public/bk-icon/iconcool'; import { setGlobalDirectives } from '@/directives/index'; import('tippy.js/dist/tippy.css'); import('tippy.js/themes/light.css'); diff --git a/dbm-ui/frontend/src/styles/iconCool.less b/dbm-ui/frontend/src/styles/iconCool.less index e70938c178..d1e1fc107f 100644 --- a/dbm-ui/frontend/src/styles/iconCool.less +++ b/dbm-ui/frontend/src/styles/iconCool.less @@ -13,7 +13,7 @@ @charset "utf-8"; -@import "@tencent/bk-icon-dbm/src/index.css"; +@import "@public/bk-icon/style.css"; [class^="db-icon-"], [class*=" db-icon-"] { diff --git a/dbm-ui/frontend/tsconfig.json b/dbm-ui/frontend/tsconfig.json index 4374aec8b5..bdea43f05c 100644 --- a/dbm-ui/frontend/tsconfig.json +++ b/dbm-ui/frontend/tsconfig.json @@ -21,6 +21,7 @@ "@styles/*": ["src/styles/*"], "@locales/*": ["src/locales/*"], "@images/*": ["src/images/*"], + "@public/*": ["public/*"], }, "typeRoots": [ "./src/types" diff --git a/dbm-ui/frontend/vite.config.ts b/dbm-ui/frontend/vite.config.ts index 07e5b2b152..66af703810 100644 --- a/dbm-ui/frontend/vite.config.ts +++ b/dbm-ui/frontend/vite.config.ts @@ -50,6 +50,7 @@ export default defineConfig(({ mode }) => { '@styles': resolve(__dirname, 'src/styles'), '@locales': resolve(__dirname, 'src/locales'), '@images': resolve(__dirname, 'src/images'), + '@public': resolve(__dirname, 'public'), }, extensions: ['.tsx', '.ts', '.js'], }, From fe352c5a9bd08a544db68dd340017749bc62005a Mon Sep 17 00:00:00 2001 From: fanfanyangyang Date: Thu, 15 Jun 2023 09:39:51 +0800 Subject: [PATCH 040/476] fix(backend): checksum_input_format_modify #187 modify_db_patterns --- .../bamboo/scene/spider/spider_checksum.py | 50 +++++++++++++------ .../flow/utils/mysql/mysql_act_playload.py | 12 ++++- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py index 0cdb884336..386daae9b6 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py @@ -45,7 +45,6 @@ class SpiderChecksumFlow(object): """ 数据校验pt-table-checksum单据的流程引擎 - { "uid": "2022111212001000", "root_id": 123, @@ -54,25 +53,46 @@ class SpiderChecksumFlow(object): "ticket_type": "SPIDER_CHECKSUM", "timing": "2022-11-21 12:04:10", "is_sync_non_innodb": true, - "runtime_hour": 48 + "runtime_hour": 48, "infos": [ { "cluster_id": 2, "immute_domain": "xxx", - "time_zone":"+08:00", + "time_zone": "+08:00", "bk_cloud_id": 0, - "shards": [{ - "shard_id": 0, - "master":{"id":9,"ip":"1.1.1.1","port":20000,"instance_inner_role": "master"}, - "slaves":[ - {"id":10,"ip":"2.2.2.2","port":20000,"instance_inner_role": "slave"} - ]}], - "db_patterns": ["db%"], - "ignore_dbs": ["db1"], - "table_patterns": ["t%"], - "ignore_tables": ["tb2"] - } ] - } + "shards": [ + { + "shard_id": 0, + "master": { + "id": 9, + "ip": "1.1.1.1", + "port": 20000, + "instance_inner_role": "master" + }, + "slaves": [ + { + "id": 10, + "ip": "2.2.2.2", + "port": 20000, + "instance_inner_role": "slave" + } + ], + "db_patterns": [ + "db%" + ], + "ignore_dbs": [ + "db1" + ], + "table_patterns": [ + "t%" + ], + "ignore_tables": [ + "tb2" + ] + } + ] + } + ]} """ def __init__(self, root_id: str, data: Optional[Dict]): diff --git a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py index ddb7e79eba..495976dcfc 100644 --- a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py +++ b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py @@ -1139,6 +1139,14 @@ def get_checksum_payload(self, **kwargs) -> dict: """ 数据校验 """ + db_patterns = [ + ele if ele.endswith("%") else "{}_{}".format(ele, self.ticket_data["shard_id"]) + for ele in self.ticket_data["db_patterns"] + ] + ignore_dbs = [ + ele if ele.endswith("%") else "{}_{}".format(ele, self.ticket_data["shard_id"]) + for ele in self.ticket_data["ignore_dbs"] + ] return { "db_type": DBActuatorTypeEnum.MySQL.value, "action": DBActuatorActionEnum.Checksum.value, @@ -1154,8 +1162,8 @@ def get_checksum_payload(self, **kwargs) -> dict: "slaves": self.ticket_data["slaves"], "master_access_slave_user": kwargs["trans_data"]["master_access_slave_user"], "master_access_slave_password": kwargs["trans_data"]["master_access_slave_password"], - "db_patterns": self.ticket_data["db_patterns"], - "ignore_dbs": self.ticket_data["ignore_dbs"], + "db_patterns": db_patterns, + "ignore_dbs": ignore_dbs, "table_patterns": self.ticket_data["table_patterns"], "ignore_tables": self.ticket_data["ignore_tables"], "runtime_hour": self.ticket_data["runtime_hour"], From f57fee0332872db42efbfc64f18287fc43f01263 Mon Sep 17 00:00:00 2001 From: zhangzhw8 <826035498@qq.com> Date: Wed, 21 Jun 2023 10:51:54 +0800 Subject: [PATCH 041/476] =?UTF-8?q?feat(backend):=20=E6=8F=90=E4=BE=9B?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E6=8E=A5=E5=8F=A3=20#261?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/configuration/views/system.py | 18 ++++++++++++------ dbm-ui/backend/env/__init__.py | 1 + .../bk-dbm/templates/dbm-configmap.yaml | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/dbm-ui/backend/configuration/views/system.py b/dbm-ui/backend/configuration/views/system.py index fa20b474ab..aa98cdea41 100644 --- a/dbm-ui/backend/configuration/views/system.py +++ b/dbm-ui/backend/configuration/views/system.py @@ -62,10 +62,16 @@ def simple(self, request, *args, **kwargs): return Response({q.key: q.value for q in self.queryset}) - @common_swagger_auto_schema( - operation_summary=_("查询相关系统的地址"), - tags=tags, - ) + @common_swagger_auto_schema(operation_summary=_("查询环境变量"), tags=tags) @action(detail=False, methods=["get"]) - def related_system_urls(self, request): - return Response({"BK_CMDB_URL": env.BK_CMDB_URL, "BK_COMPONENT_API_URL": env.BK_COMPONENT_API_URL}) + def environ(self, request): + """按需提供环境变量""" + return Response( + { + "BK_DOMAIN": env.BK_DOMAIN, + "BK_COMPONENT_API_URL": env.BK_COMPONENT_API_URL, + "BK_CMDB_URL": env.BK_CMDB_URL, + "BK_NODEMAN_URL": env.BK_NODEMAN_URL, + "BK_SCR_URL": env.BK_SCR_URL, + } + ) diff --git a/dbm-ui/backend/env/__init__.py b/dbm-ui/backend/env/__init__.py index 32a628c5c7..e659f1a651 100644 --- a/dbm-ui/backend/env/__init__.py +++ b/dbm-ui/backend/env/__init__.py @@ -85,6 +85,7 @@ BK_SAAS_HOST = BK_SAAS_SERVICE_ADDRESS or get_type_env(key="BK_SAAS_HOST", _type=str) # 其他系统访问地址 +BK_DOMAIN = get_type_env(key="BK_DOMAIN", _type=str, default=".example.com") BK_PAAS_URL = get_type_env(key="BK_PAAS_URL", _type=str, default="http://paas.example.com") BK_CMDB_URL = get_type_env(key="BK_CMDB_URL", _type=str, default=BK_PAAS_URL.replace("paas", "cmdb")) BK_JOB_URL = get_type_env(key="BK_JOB_HOST", _type=str, default=None) diff --git a/helm-charts/bk-dbm/templates/dbm-configmap.yaml b/helm-charts/bk-dbm/templates/dbm-configmap.yaml index 5270ca2f46..b67597e6b3 100644 --- a/helm-charts/bk-dbm/templates/dbm-configmap.yaml +++ b/helm-charts/bk-dbm/templates/dbm-configmap.yaml @@ -20,6 +20,7 @@ data: BK_APP_CODE: "{{ .Values.dbm.envs.bkAppCode }}" APP_ID: "{{ .Values.dbm.envs.bkAppCode }}" APP_TOKEN: "{{ .Values.dbm.envs.bkAppToken }}" + BK_DOMAIN: "{{ .Values.global.bkDomain }}" BK_SAAS_HOST: "{{ .Values.dbm.envs.bkSaasUrl }}" BROKER_URL: "{{ .Values.dbm.envs.brokerUrl }}" DBA_APP_BK_BIZ_ID: "{{ .Values.dbm.envs.dbaAppBkBizId }}" From f977690c1af887bd8fe79c79c8609bde87cf0034 Mon Sep 17 00:00:00 2001 From: daryl Date: Wed, 21 Jun 2023 11:38:39 +0800 Subject: [PATCH 042/476] =?UTF-8?q?fix(frontend):=20=E4=BF=AE=E5=A4=8D=20i?= =?UTF-8?q?nflux=E3=80=81pulsar=20=E9=AA=8C=E6=94=B6=E5=8F=8D=E9=A6=88?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20#156?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 2 +- .../src/components/app-selector/index.vue | 6 +- .../src/components/layouts/LocaleSwitch.vue | 14 ++--- dbm-ui/frontend/src/main.ts | 8 +-- dbm-ui/frontend/src/services/common.ts | 4 +- dbm-ui/frontend/src/stores/index.ts | 2 +- ...seRelatedSystem.ts => useSystemEnviron.ts} | 12 ++-- .../src/views/exception/BizPermission.vue | 6 +- .../src/views/pulsar-manage/list/Index.vue | 2 +- .../views/tickets/my-tickets/TicketList.vue | 57 +++++++++---------- .../src/views/tickets/my-todos/TicketList.vue | 35 ++++++++++++ 11 files changed, 90 insertions(+), 58 deletions(-) rename dbm-ui/frontend/src/stores/{useRelatedSystem.ts => useSystemEnviron.ts} (78%) diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index 114117064f..62696e981b 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -18,7 +18,7 @@ "@blueking/ip-selector": "0.0.1-beta.101", "@vueuse/core": "^10.1.2", "axios": "^1.2.1", - "bkui-vue": "0.0.1-beta.425", + "bkui-vue": "0.0.1-beta.442", "date-fns": "^2.28.0", "dayjs": "^1.11.7", "html-to-image": "^1.11.3", diff --git a/dbm-ui/frontend/src/components/app-selector/index.vue b/dbm-ui/frontend/src/components/app-selector/index.vue index 8f73b2d0a6..094e5815e2 100644 --- a/dbm-ui/frontend/src/components/app-selector/index.vue +++ b/dbm-ui/frontend/src/components/app-selector/index.vue @@ -130,7 +130,7 @@ import { useGlobalBizs, - useRelatedSystem, + useSystemEnviron, useUserProfile, } from '@stores'; @@ -160,7 +160,7 @@ const router = useRouter(); const route = useRoute(); const globalBizsStore = useGlobalBizs(); - const relatedSystemStore = useRelatedSystem(); + const systemEnvironStore = useSystemEnviron(); const userProfileStore = useUserProfile(); const { t } = useI18n(); @@ -395,7 +395,7 @@ * 跳转到新建业务 */ const handleToCreate = () => { - const { BK_CMDB_URL } = relatedSystemStore.urls; + const { BK_CMDB_URL } = systemEnvironStore.urls; if (BK_CMDB_URL) { window.open(`${BK_CMDB_URL}/#/resource/business`, '_blank'); } diff --git a/dbm-ui/frontend/src/components/layouts/LocaleSwitch.vue b/dbm-ui/frontend/src/components/layouts/LocaleSwitch.vue index f9bc97a705..c358019b48 100644 --- a/dbm-ui/frontend/src/components/layouts/LocaleSwitch.vue +++ b/dbm-ui/frontend/src/components/layouts/LocaleSwitch.vue @@ -42,16 +42,19 @@ diff --git a/dbm-ui/frontend/src/components/cluster-common/big-data-host-table/es-host-table/index.vue b/dbm-ui/frontend/src/components/cluster-common/big-data-host-table/es-host-table/index.vue index f2ad02bb65..fb943b54b6 100644 --- a/dbm-ui/frontend/src/components/cluster-common/big-data-host-table/es-host-table/index.vue +++ b/dbm-ui/frontend/src/components/cluster-common/big-data-host-table/es-host-table/index.vue @@ -15,47 +15,51 @@
- - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/Index.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/Index.vue deleted file mode 100644 index 5668dbd7e1..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/Index.vue +++ /dev/null @@ -1,206 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/HostSelector.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/HostSelector.vue deleted file mode 100644 index 62bc8d421f..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/HostSelector.vue +++ /dev/null @@ -1,179 +0,0 @@ - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/ResourcePoolSelector.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/ResourcePoolSelector.vue deleted file mode 100644 index 65dac3c997..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/expansion/components/render-node/components/ResourcePoolSelector.vue +++ /dev/null @@ -1,167 +0,0 @@ - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/Index.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/replace/Index.vue index 5b03657347..606500f1b7 100644 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/Index.vue +++ b/dbm-ui/frontend/src/views/pulsar-manage/common/replace/Index.vue @@ -99,34 +99,18 @@ import type PulsarModel from '@services/model/pulsar/pulsar'; import type PulsarNodeModel from '@services/model/pulsar/pulsar-node'; import { createTicket } from '@services/ticket'; - import type { HostDetails } from '@services/types/ip'; import { useGlobalBizs } from '@stores'; import { ClusterTypes } from '@common/const'; - // import HostReplace from './components/render-node-host-replace-table/Index.vue'; - import HostReplace from '@components/cluster-common/host-replace/Index.vue'; + import HostReplace, { + type TReplaceNode, + } from '@components/cluster-common/host-replace/Index.vue'; import { messageError } from '@utils'; - export interface TNodeInfo{ - // 集群id - clusterId: number, - // 集群的节点类型 - role: string, - nodeList: PulsarNodeModel[], - hostList: HostDetails[], - // 资源池规格集群类型 - specClusterType: string, - // 资源池规格集群类型 - specMachineType: string, - // 扩容资源池 - resourceSpec: { - spec_id: number, - count: number - } - } + type TNodeInfo = TReplaceNode interface Props { data: PulsarModel, diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/Index.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/Index.vue deleted file mode 100644 index 3ec01aa85e..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/Index.vue +++ /dev/null @@ -1,293 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/HostSelector.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/HostSelector.vue deleted file mode 100644 index 1e89b73924..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/HostSelector.vue +++ /dev/null @@ -1,135 +0,0 @@ - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/ResourcePoolSelector.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/ResourcePoolSelector.vue deleted file mode 100644 index 019dd529d7..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/replace/components/render-node-host-replace-table/components/ResourcePoolSelector.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/Index.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/Index.vue index 8e521ee154..c204d17fe2 100644 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/Index.vue +++ b/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/Index.vue @@ -36,17 +36,6 @@
- - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/Index.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/Index.vue deleted file mode 100644 index 47d28aca07..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/Index.vue +++ /dev/null @@ -1,350 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/components/SelectOriginalHost.vue b/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/components/SelectOriginalHost.vue deleted file mode 100644 index 1683c50188..0000000000 --- a/dbm-ui/frontend/src/views/pulsar-manage/common/shrink/components/render-node/components/SelectOriginalHost.vue +++ /dev/null @@ -1,218 +0,0 @@ - - - - From b50c1ecbc25b64419b42b6f39a9243f144db23cb Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Fri, 30 Jun 2023 10:28:35 +0800 Subject: [PATCH 066/476] =?UTF-8?q?fix(dbm-services):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=B1=A0=E5=BD=92=E6=A1=A3=E8=A1=A8=E7=BC=BA?= =?UTF-8?q?=E5=B0=91=E5=AD=97=E6=AE=B5=20close=20#348?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/controller/controller.go | 11 ++- .../common/db-resource/internal/lock/lock.go | 66 +++++++++++++++++ .../db-resource/internal/lock/lock_test.go | 42 +++++++++++ .../db-resource/internal/lock/redis_lock.go | 57 --------------- .../internal/lock/redis_lock_test.go | 32 --------- .../internal/model/TbDeviceSpec.go | 35 --------- .../db-resource/internal/model/TbRpDetail.go | 21 ++++-- .../internal/model/TbRpDetailArchive.go | 27 +++++-- .../db-resource/internal/model/model.go | 72 +++---------------- .../db-resource/internal/routers/router.go | 18 ----- .../db-resource/internal/routers/routers.go | 27 +++++++ .../db-resource/internal/svr/bk/disk.go | 2 +- 12 files changed, 193 insertions(+), 217 deletions(-) create mode 100644 dbm-services/common/db-resource/internal/lock/lock_test.go delete mode 100644 dbm-services/common/db-resource/internal/lock/redis_lock.go delete mode 100644 dbm-services/common/db-resource/internal/lock/redis_lock_test.go delete mode 100644 dbm-services/common/db-resource/internal/model/TbDeviceSpec.go delete mode 100644 dbm-services/common/db-resource/internal/routers/router.go diff --git a/dbm-services/common/db-resource/internal/controller/controller.go b/dbm-services/common/db-resource/internal/controller/controller.go index 97f17f35f3..699e9964ca 100644 --- a/dbm-services/common/db-resource/internal/controller/controller.go +++ b/dbm-services/common/db-resource/internal/controller/controller.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package controller TODO package controller @@ -41,7 +51,6 @@ func (c *BaseHandler) Prepare(r *gin.Context, schema interface{}) error { } // SendResponse TODO -// SendResponseT TODO func (c *BaseHandler) SendResponse(r *gin.Context, err error, data interface{}, requestId string) { code, message := errno.DecodeErr(err) r.JSON(http.StatusOK, Response{ diff --git a/dbm-services/common/db-resource/internal/lock/lock.go b/dbm-services/common/db-resource/internal/lock/lock.go index 02804bc982..4ec5ae9573 100644 --- a/dbm-services/common/db-resource/internal/lock/lock.go +++ b/dbm-services/common/db-resource/internal/lock/lock.go @@ -1,2 +1,68 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package lock TODO package lock + +import ( + "context" + "fmt" + "time" + + "dbm-services/common/db-resource/internal/config" + "dbm-services/common/go-pubpkg/logger" + + "github.com/go-redis/redis/v8" +) + +var rdb *redis.Client + +// init TODO +func init() { + logger.Info("redis addr %s", config.AppConfig.Redis.Addr) + rdb = redis.NewClient(&redis.Options{ + Addr: config.AppConfig.Redis.Addr, + Password: config.AppConfig.Redis.Password, + DB: 0, + }) +} + +// RedisLock TODO +type RedisLock struct { + Name string + RandKey string + Expiry time.Duration +} + +// TryLock TODO +func (r *RedisLock) TryLock() (err error) { + ok, err := rdb.SetNX(context.TODO(), r.Name, r.RandKey, r.Expiry).Result() + if err != nil { + return err + } + if !ok { + return fmt.Errorf("setnx %s lock failed", r.Name) + } + return nil +} + +// Unlock TODO +func (r *RedisLock) Unlock() (err error) { + luaStript := `if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end` + v, err := rdb.Eval(context.TODO(), luaStript, []string{r.Name}, []interface{}{r.RandKey}).Int() + if err != nil { + logger.Error("del lock failed %s", err.Error()) + return err + } + if v != 1 { + return fmt.Errorf("unlock failed,key is %s,val %s", r.Name, r.RandKey) + } + return nil +} diff --git a/dbm-services/common/db-resource/internal/lock/lock_test.go b/dbm-services/common/db-resource/internal/lock/lock_test.go new file mode 100644 index 0000000000..b6e5ce72b4 --- /dev/null +++ b/dbm-services/common/db-resource/internal/lock/lock_test.go @@ -0,0 +1,42 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package lock_test + +import ( + "testing" + "time" + + "dbm-services/common/db-resource/internal/lock" + "dbm-services/common/go-pubpkg/cmutil" +) + +func TestRedisLock(t *testing.T) { + t.Log("start testing...") + // lock.InitRedisDb() + l := lock.NewSpinLock(&lock.RedisLock{ + Name: "Tendb", + RandKey: cmutil.RandStr(16), + Expiry: 10 * time.Second, + }, 30, 1*time.Second) + for i := 0; i < 20; i++ { + go func(j int) { + if err := l.Lock(); err != nil { + t.Log(j, "lock failed") + return + } + t.Log(j, "lock success") + time.Sleep(100 * time.Millisecond) + l.Unlock() + }(i) + } + + time.Sleep(20 * time.Second) +} diff --git a/dbm-services/common/db-resource/internal/lock/redis_lock.go b/dbm-services/common/db-resource/internal/lock/redis_lock.go deleted file mode 100644 index 31384fe689..0000000000 --- a/dbm-services/common/db-resource/internal/lock/redis_lock.go +++ /dev/null @@ -1,57 +0,0 @@ -package lock - -import ( - "context" - "fmt" - "time" - - "dbm-services/common/db-resource/internal/config" - "dbm-services/common/go-pubpkg/logger" - - "github.com/go-redis/redis/v8" -) - -var rdb *redis.Client - -// init TODO -func init() { - logger.Info("redis addr %s", config.AppConfig.Redis.Addr) - rdb = redis.NewClient(&redis.Options{ - Addr: config.AppConfig.Redis.Addr, - Password: config.AppConfig.Redis.Password, - DB: 0, - }) -} - -// RedisLock TODO -type RedisLock struct { - Name string - RandKey string - Expiry time.Duration -} - -// TryLock TODO -func (r *RedisLock) TryLock() (err error) { - ok, err := rdb.SetNX(context.TODO(), r.Name, r.RandKey, r.Expiry).Result() - if err != nil { - return err - } - if !ok { - return fmt.Errorf("setnx %s lock failed", r.Name) - } - return nil -} - -// Unlock TODO -func (r *RedisLock) Unlock() (err error) { - luaStript := `if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end` - v, err := rdb.Eval(context.TODO(), luaStript, []string{r.Name}, []interface{}{r.RandKey}).Int() - if err != nil { - logger.Error("del lock failed %s", err.Error()) - return err - } - if v != 1 { - return fmt.Errorf("unlock failed,key is %s,val %s", r.Name, r.RandKey) - } - return nil -} diff --git a/dbm-services/common/db-resource/internal/lock/redis_lock_test.go b/dbm-services/common/db-resource/internal/lock/redis_lock_test.go deleted file mode 100644 index a7b0b1a2f9..0000000000 --- a/dbm-services/common/db-resource/internal/lock/redis_lock_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package lock_test - -import ( - "testing" - "time" - - "dbm-services/common/db-resource/internal/lock" - "dbm-services/common/go-pubpkg/cmutil" -) - -func TestRedisLock(t *testing.T) { - t.Log("start testing...") - // lock.InitRedisDb() - l := lock.NewSpinLock(&lock.RedisLock{ - Name: "Tendb", - RandKey: cmutil.RandStr(16), - Expiry: 10 * time.Second, - }, 30, 1*time.Second) - for i := 0; i < 20; i++ { - go func(j int) { - if err := l.Lock(); err != nil { - t.Log(j, "lock failed") - return - } - t.Log(j, "lock success") - time.Sleep(100 * time.Millisecond) - l.Unlock() - }(i) - } - - time.Sleep(20 * time.Second) -} diff --git a/dbm-services/common/db-resource/internal/model/TbDeviceSpec.go b/dbm-services/common/db-resource/internal/model/TbDeviceSpec.go deleted file mode 100644 index c13f9f89a5..0000000000 --- a/dbm-services/common/db-resource/internal/model/TbDeviceSpec.go +++ /dev/null @@ -1,35 +0,0 @@ -package model - -import ( - "fmt" - - "dbm-services/common/go-pubpkg/logger" -) - -// TbDeviceSpec TODO -type TbDeviceSpec struct { - ID int `gorm:"primaryKey;column:id;type:int(11);not null" json:"-"` - ResourceType string `gorm:"column:resource_type;type:int(11);not null" json:"resource_type"` - DeviceClass string `gorm:"unique;column:device_class;type:varchar(64);not null" json:"device_class"` - CPUNum int `gorm:"column:cpu_num;type:int(11);not null" json:"cpu_num"` - DramCap int `gorm:"column:dram_cap;type:int(11);not null" json:"dram_cap"` - SsdCap int `gorm:"column:ssd_cap;type:int(11);not null" json:"ssd_cap"` - SsdNum int `gorm:"column:ssd_num;type:int(11);not null" json:"ssd_num"` - HddCap int `gorm:"column:hdd_cap;type:int(11);not null" json:"hdd_cap"` - IsLocalStorge int `gorm:"column:is_local_storge;type:int(11);not null" json:"is_local_storge"` -} - -// TbDeviceSpecName TODO -func TbDeviceSpecName() string { - return "tb_device_spec" -} - -// GetDeviceSpecFromClass TODO -func GetDeviceSpecFromClass(deviceClass string) (m TbDeviceSpec, err error) { - err = DB.Self.Table(TbDeviceSpecName()).Where("device_class = ? ", deviceClass).First(&m).Error - if err != nil { - logger.Error(fmt.Sprintf("Query DeviceSpec By DeviceClass Failed %s", err.Error())) - return - } - return -} diff --git a/dbm-services/common/db-resource/internal/model/TbRpDetail.go b/dbm-services/common/db-resource/internal/model/TbRpDetail.go index cdd397c260..0d8209c320 100644 --- a/dbm-services/common/db-resource/internal/model/TbRpDetail.go +++ b/dbm-services/common/db-resource/internal/model/TbRpDetail.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package model import ( @@ -56,11 +66,12 @@ type TbRpDetail struct { Status string `gorm:"column:status;type:varchar(20);not null" json:"status"` // Unused: 未使用 Used: 已经售卖被使用: Preselected:预占用 BkAgentId string `gorm:"index:idx_bk_agent_id;column:bk_agent_id;type:varchar(64);not null" json:"bk_agent_id"` // gse Agent当前运行状态码, -1:未知 0:初始安装 1:启动中 2:运行中 3:有损状态 4:繁忙状态 5:升级中 6:停止中 7:解除安装 - AgentStatusCode int `gorm:"column:gse_agent_status_code;type:int(11);not null" json:"gse_agent_status_code"` - AgentStatusUpdateTime time.Time `gorm:"column:agent_status_update_time;type:timestamp;default:1970-01-01 08:00:01" json:"agent_status_update_time"` // 消费时间 - ConsumeTime time.Time `gorm:"column:consume_time;type:timestamp;default:1970-01-01 08:00:01" json:"consume_time"` // 消费时间 - UpdateTime time.Time `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"update_time"` // 最后修改时间 - CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"create_time"` // 创建时间 + AgentStatusCode int `gorm:"column:gse_agent_status_code;type:int(11);not null" json:"gse_agent_status_code"` + // agent status 最后一次更新时间 + AgentStatusUpdateTime time.Time `gorm:"column:agent_status_update_time;type:timestamp;default:1970-01-01 08:00:01" json:"agent_status_update_time"` + ConsumeTime time.Time `gorm:"column:consume_time;type:timestamp;default:1970-01-01 08:00:01" json:"consume_time"` // 消费时间 + UpdateTime time.Time `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"update_time"` // 最后修改时间 + CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"create_time"` // 创建时间 } // TableName TODO diff --git a/dbm-services/common/db-resource/internal/model/TbRpDetailArchive.go b/dbm-services/common/db-resource/internal/model/TbRpDetailArchive.go index 7b969ab729..a522b1296d 100644 --- a/dbm-services/common/db-resource/internal/model/TbRpDetailArchive.go +++ b/dbm-services/common/db-resource/internal/model/TbRpDetailArchive.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package model import ( @@ -36,12 +46,17 @@ type TbRpDetailArchive struct { NetDeviceID string `gorm:"column:net_device_id;type:varchar(128)" json:"net_device_id"` // 网络设备ID, 判断是同交换机 Label string `gorm:"column:label;type:json" json:"label"` // 标签 LabelMap map[string]string `gorm:"-"` - IsInit int `gorm:"column:is_init;type:int(11);comment:'是否初始化过'" json:"-"` // 是否初始化过 - IsIdle int `gorm:"column:is_idle;type:int(11);comment:'是否空闲检查过'" json:"-"` // 是否空闲检查过 - Status string `gorm:"column:status;type:varchar(20);not null" json:"status"` // Unused: 未使用 Used: 已经售卖被使用: Preselected:预占用 - ConsumeTime time.Time `gorm:"column:consume_time;type:timestamp;default:1970-01-01 08:00:01" json:"consume_time"` // 消费时间 - UpdateTime time.Time `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"update_time"` // 最后修改时间 - CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"create_time"` // 创建时间 + IsInit int `gorm:"column:is_init;type:int(11);comment:'是否初始化过'" json:"-"` // 是否初始化过 + IsIdle int `gorm:"column:is_idle;type:int(11);comment:'是否空闲检查过'" json:"-"` // 是否空闲检查过 + Status string `gorm:"column:status;type:varchar(20);not null" json:"status"` // Unused: 未使用 Used: 已经售卖被使用: Preselected:预占用 + BkAgentId string `gorm:"index:idx_bk_agent_id;column:bk_agent_id;type:varchar(64);not null" json:"bk_agent_id"` + // gse Agent当前运行状态码, -1:未知 0:初始安装 1:启动中 2:运行中 3:有损状态 4:繁忙状态 5:升级中 6:停止中 7:解除安装 + AgentStatusCode int `gorm:"column:gse_agent_status_code;type:int(11);not null" json:"gse_agent_status_code"` + // agent status 最后一次更新时间 + AgentStatusUpdateTime time.Time `gorm:"column:agent_status_update_time;type:timestamp;default:1970-01-01 08:00:01" json:"agent_status_update_time"` + ConsumeTime time.Time `gorm:"column:consume_time;type:timestamp;default:1970-01-01 08:00:01" json:"consume_time"` // 消费时间 + UpdateTime time.Time `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"update_time"` // 最后修改时间 + CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP()" json:"create_time"` // 创建时间 } // initarchive TODO diff --git a/dbm-services/common/db-resource/internal/model/model.go b/dbm-services/common/db-resource/internal/model/model.go index f0cf5ff84b..89d3714b8c 100644 --- a/dbm-services/common/db-resource/internal/model/model.go +++ b/dbm-services/common/db-resource/internal/model/model.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package model TODO package model @@ -32,7 +42,6 @@ var DB *Database var CMDBDB *Database func init() { - log.Println("init db model..") createSysDb() orm_db := initSelfDB() sqlDB, err := orm_db.DB() @@ -128,67 +137,6 @@ func migration() { DB.Self.AutoMigrate(&TbRpDetail{}, &TbRequestLog{}, &TbRpDetailArchive{}, &TbRpApplyDetailLog{}, &TbRpOperationInfo{}) } -// QueryCountSelfCommon TODO -func (db Database) QueryCountSelfCommon(sqltext string) (int, error) { - var count int - c_db := db.Self.Raw(sqltext) - if c_db.Error != nil { - return 0, c_db.Error - } - if err := c_db.Row().Scan(&count); err != nil { - return 0, err - } - return count, nil -} - -// QuerySelfCommon TODO -func (db *Database) QuerySelfCommon(sqltext string) ([]map[string]interface{}, error) { - cursor, err := db.SelfSqlDB.Query(sqltext) - if err != nil || cursor.Err() != nil { - return nil, fmt.Errorf("db query failed, err: %+v", err) - } - defer cursor.Close() - columns, err := cursor.Columns() - if err != nil { - return nil, fmt.Errorf("get columns failed, err: %+v", err) - } - columnTypes, err := cursor.ColumnTypes() - if err != nil { - return nil, fmt.Errorf("get column types failed, err: %+v", err) - } - - count := len(columns) - values := make([]interface{}, count) - scanArgs := make([]interface{}, count) - for i := range values { - scanArgs[i] = &values[i] - } - - dataRows := make([]map[string]interface{}, 0) - for cursor.Next() { - row := make(map[string]interface{}) - err := cursor.Scan(scanArgs...) - if err != nil { - return nil, fmt.Errorf("scan data failed, err: %+v", err) - } - for i, col := range columns { - columnType := columnTypes[i] - columnType.ScanType() - var v interface{} - val := values[i] - b, ok := val.([]byte) - if ok { - v = string(b) - } else { - v = val - } - row[col] = v - } - dataRows = append(dataRows, row) - } - return dataRows, err -} - // JSONQueryExpression json query expression, implements clause.Expression interface to use as querier type JSONQueryExpression struct { column string diff --git a/dbm-services/common/db-resource/internal/routers/router.go b/dbm-services/common/db-resource/internal/routers/router.go deleted file mode 100644 index f71fe1887a..0000000000 --- a/dbm-services/common/db-resource/internal/routers/router.go +++ /dev/null @@ -1,18 +0,0 @@ -package routers - -import ( - "dbm-services/common/db-resource/internal/controller/apply" - "dbm-services/common/db-resource/internal/controller/manage" - - "github.com/gin-gonic/gin" -) - -// RegisterRoutes TODO -func RegisterRoutes(engine *gin.Engine) { - // 注册路由 - apply := apply.ApplyHandler{} - apply.RegisterRouter(engine) - // 机器资源管理 - manage := manage.MachineResourceHandler{} - manage.RegisterRouter(engine) -} diff --git a/dbm-services/common/db-resource/internal/routers/routers.go b/dbm-services/common/db-resource/internal/routers/routers.go index c0dc2a6696..f433fcfc3a 100644 --- a/dbm-services/common/db-resource/internal/routers/routers.go +++ b/dbm-services/common/db-resource/internal/routers/routers.go @@ -1,2 +1,29 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package routers TODO package routers + +import ( + "dbm-services/common/db-resource/internal/controller/apply" + "dbm-services/common/db-resource/internal/controller/manage" + + "github.com/gin-gonic/gin" +) + +// RegisterRoutes TODO +func RegisterRoutes(engine *gin.Engine) { + // 注册路由 + apply := apply.ApplyHandler{} + apply.RegisterRouter(engine) + // 机器资源管理 + manage := manage.MachineResourceHandler{} + manage.RegisterRouter(engine) +} diff --git a/dbm-services/common/db-resource/internal/svr/bk/disk.go b/dbm-services/common/db-resource/internal/svr/bk/disk.go index dc8c6c4699..db23eaa1ab 100644 --- a/dbm-services/common/db-resource/internal/svr/bk/disk.go +++ b/dbm-services/common/db-resource/internal/svr/bk/disk.go @@ -148,7 +148,7 @@ func GetDiskInfo(hosts []string, bk_cloud_id, bk_biz_id int) (resp GetDiskResp, } time.Sleep(1 * time.Second) } - // 在查询一遍转态 + // 再查询一遍状态 jobStatus, err = jober.GetJobStatus(&GetJobInstanceStatusParam{ BKBizId: bk_biz_id, JobInstanceID: job.JobInstanceID, From a46672d7b76cfded6840f70db63902fa50b323fb Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Tue, 6 Jun 2023 15:49:20 +0800 Subject: [PATCH 067/476] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=20spider=20r?= =?UTF-8?q?emote=20db=20=E4=BA=92=E5=88=87=E5=92=8C=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E5=88=87=E6=8D=A2command=20=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/controller/apply/apply.go | 2 +- dbm-services/common/go-pubpkg/cmutil/slice.go | 48 +- .../spiderctlcmd/add_temporary_spider.go | 1 - .../cluster_backend_migrate_cutover.go | 86 +++ .../spiderctlcmd/cluster_backend_switch.go | 107 +++ .../internal/subcmd/spiderctlcmd/cmd.go | 2 + .../internal/subcmd/subcmd_helper.go | 2 +- .../dbactuator/pkg/components/base.go | 23 +- .../pkg/components/mysql/cutover/base.go | 44 +- .../pkg/components/mysql/cutover/cutover.go | 12 +- .../spiderctl/backend_migrate_cutover.go | 497 ++++++++++++++ .../components/spiderctl/backend_switch.go | 634 ++++++++++++++++++ .../init_cluster_routing_relationship.go | 4 +- .../dbactuator/pkg/native/dbworker.go | 14 +- .../db-tools/dbactuator/pkg/native/tdbctl.go | 179 +++++ .../dbactuator/pkg/native/tdbctl_test.go | 53 ++ .../db-tools/dbactuator/pkg/util/slice.go | 53 +- 17 files changed, 1656 insertions(+), 105 deletions(-) create mode 100644 dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_migrate_cutover.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_switch.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl_test.go diff --git a/dbm-services/common/db-resource/internal/controller/apply/apply.go b/dbm-services/common/db-resource/internal/controller/apply/apply.go index daf4b8011c..8cab805b37 100644 --- a/dbm-services/common/db-resource/internal/controller/apply/apply.go +++ b/dbm-services/common/db-resource/internal/controller/apply/apply.go @@ -47,7 +47,7 @@ func (c *ApplyHandler) ConfirmApply(r *gin.Context) { return } requestId := r.GetString("request_id") - hostIds := cmutil.RemoveDuplicateIntElement(param.HostIds) + hostIds := cmutil.RemoveDuplicate(param.HostIds) var cnt int64 err := model.DB.Self.Table(model.TbRpApplyDetailLogName()).Where("request_id = ?", param.RequestId).Count(&cnt).Error if err != nil { diff --git a/dbm-services/common/go-pubpkg/cmutil/slice.go b/dbm-services/common/go-pubpkg/cmutil/slice.go index 126feed90c..18b1bc2664 100644 --- a/dbm-services/common/go-pubpkg/cmutil/slice.go +++ b/dbm-services/common/go-pubpkg/cmutil/slice.go @@ -33,10 +33,15 @@ func StringsHas(ss []string, val string) bool { return false } +// UniqueInts Returns unique items in a slice +func UniqueInts(slice []int) []int { + return RemoveDuplicate(slice) +} + // RemoveDuplicate 通过map主键唯一的特性过滤重复元素 -func RemoveDuplicate(arr []string) []string { - resArr := make([]string, 0) - tmpMap := make(map[string]struct{}) +func RemoveDuplicate[T int | string](arr []T) []T { + resArr := make([]T, 0) + tmpMap := make(map[T]struct{}) for _, val := range arr { // 判断主键为val的map是否存在 if _, ok := tmpMap[val]; !ok { @@ -44,7 +49,6 @@ func RemoveDuplicate(arr []string) []string { tmpMap[val] = struct{}{} } } - return resArr } @@ -97,26 +101,6 @@ func RemoveEmpty(input []string) []string { return result } -// RemoveDuplicateIntElement TODO -func RemoveDuplicateIntElement(arry []int) []int { - result := make([]int, 0, len(arry)) - temp := map[int]struct{}{} - for _, item := range arry { - if _, ok := temp[item]; !ok { - temp[item] = struct{}{} - result = append(result, item) - } - } - return result -} - -// ArryToInterfaceArry TODO -func ArryToInterfaceArry(arrys ...interface{}) []interface{} { - var result []interface{} - result = append(result, arrys...) - return result -} - // ElementNotInArry TODO func ElementNotInArry(ele string, arry []string) bool { if len(arry) <= 0 { @@ -188,19 +172,3 @@ func HasElem(elem interface{}, slice interface{}) bool { } return false } - -// UniqueInts Returns unique items in a slice -func UniqueInts(slice []int) []int { - // create a map with all the values as key - uniqMap := make(map[int]struct{}) - for _, v := range slice { - uniqMap[v] = struct{}{} - } - - // turn the map keys into a slice - uniqSlice := make([]int, 0, len(uniqMap)) - for v := range uniqMap { - uniqSlice = append(uniqSlice, v) - } - return uniqSlice -} diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/add_temporary_spider.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/add_temporary_spider.go index c616759764..dc50d36c04 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/add_temporary_spider.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/add_temporary_spider.go @@ -34,7 +34,6 @@ func NewAddTmpSpiderCommand() *cobra.Command { util.CheckErr(act.Validate()) util.CheckErr(act.Init()) util.CheckErr(act.Run()) - }, } return cmd diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_migrate_cutover.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_migrate_cutover.go new file mode 100644 index 0000000000..b20f5778ef --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_migrate_cutover.go @@ -0,0 +1,86 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package spiderctlcmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/internal/subcmd" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl" + "dbm-services/mysql/db-tools/dbactuator/pkg/util" +) + +// ClusterBackendMigrateCutOverAct TODO +type ClusterBackendMigrateCutOverAct struct { + *subcmd.BaseOptions + Service spiderctl.SpiderClusterBackendMigrateCutoverComp +} + +// NewClusterMigrateCutOverCommand TODO +func NewClusterMigrateCutOverCommand() *cobra.Command { + act := ClusterBackendMigrateCutOverAct{ + BaseOptions: subcmd.GBaseOptions, + } + cmd := &cobra.Command{ + Use: "cluster-backend-migrate-cutover", + Short: "spider集群后端迁移切换", + Example: fmt.Sprintf(`dbactuator spiderctl cluster-backend-migrate-cutover %s %s`, + subcmd.CmdBaseExampleStr, subcmd.ToPrettyJson(act.Service.Example()), + ), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(act.Validate()) + util.CheckErr(act.Init()) + util.CheckErr(act.Run()) + }, + } + return cmd +} + +// Init TODO +func (d *ClusterBackendMigrateCutOverAct) Init() (err error) { + if err = d.Deserialize(&d.Service.Params); err != nil { + logger.Error("DeserializeAndValidate failed, %v", err) + return err + } + d.Service.GeneralParam = subcmd.GeneralRuntimeParam + return nil +} + +// Run TODO +func (d *ClusterBackendMigrateCutOverAct) Run() (err error) { + // 是一个切片 + steps := subcmd.Steps{ + { + FunName: "[未切换]: 初始化", + Func: d.Service.Init, + }, + { + FunName: "[未切换]: 切换前置检查", + Func: d.Service.PreCheck, + }, + { + FunName: "[主分片切换中]: 开始切换", + Func: d.Service.CutOver, + }, + { + FunName: "[已完成切换]: 断开数据同步", + Func: d.Service.StopRepl, + }, + } + if err = steps.Run(); err != nil { + return err + } + logger.Info("cluster backend migrate cutover successfully") + return nil +} diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_switch.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_switch.go new file mode 100644 index 0000000000..e69ae86f5e --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cluster_backend_switch.go @@ -0,0 +1,107 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package spiderctlcmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/internal/subcmd" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl" + "dbm-services/mysql/db-tools/dbactuator/pkg/util" +) + +// ClusterBackendSwitchAct TODO +type ClusterBackendSwitchAct struct { + *subcmd.BaseOptions + Service spiderctl.SpiderClusterBackendSwitchComp +} + +// NewClusterBackendSwitchCommand TODO +func NewClusterBackendSwitchCommand() *cobra.Command { + act := ClusterBackendSwitchAct{ + BaseOptions: subcmd.GBaseOptions, + } + cmd := &cobra.Command{ + Use: "cluster-backend-switch", + Short: "spider集群后端切换", + Example: fmt.Sprintf(`dbactuator spiderctl cluster-backend-switch %s %s`, + subcmd.CmdBaseExampleStr, subcmd.ToPrettyJson(act.Service.Example()), + ), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(act.Validate()) + util.CheckErr(act.Init()) + util.CheckErr(act.Run()) + }, + } + return cmd +} + +// Init TODO +func (d *ClusterBackendSwitchAct) Init() (err error) { + if err = d.Deserialize(&d.Service.Params); err != nil { + logger.Error("DeserializeAndValidate failed, %v", err) + return err + } + d.Service.GeneralParam = subcmd.GeneralRuntimeParam + return nil +} + +// Run TODO +func (d *ClusterBackendSwitchAct) Run() (err error) { + // 是一个切片 + steps := subcmd.Steps{ + { + FunName: "[未切换]: 初始化", + Func: d.Service.Init, + }, + { + FunName: "[未切换]: 切换前置检查", + Func: d.Service.PreCheck, + }, + { + FunName: "[主分片切换中]: 开始切换主分片", + Func: d.Service.CutOver, + }, + { + FunName: "[主分片切换成功]: 断开NewMaster的同步", + Func: d.Service.StopRepl, + }, + } + if err = steps.Run(); err != nil { + return err + } + logger.Info("master spt switching has been completed") + // 如果非强制切换,则需要执行互切的后续操作 + if !d.Service.Params.Force { + flowSteps := subcmd.Steps{ + { + FunName: "[主分片切换成功]: 授权repl给OldMaster", + Func: d.Service.GrantReplForNewSlave, + }, + { + FunName: "[主分片切换成功]: 建立复制关系", + Func: d.Service.ChangeMasterToNewMaster, + }, + { + FunName: "[开始切换从分片]: 切换从分片", + Func: d.Service.SwitchSlaveSpt, + }, + } + if err = flowSteps.Run(); err != nil { + return err + } + } + logger.Info("cluster backend switch successfully") + return nil +} diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cmd.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cmd.go index bc6448eab0..77b44b641f 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cmd.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/spiderctlcmd/cmd.go @@ -27,6 +27,8 @@ func NewSpiderCtlCommand() *cobra.Command { NewAddTmpSpiderCommand(), AddSlaveClusterRoutingCommand(), NewUnInstallSpiderCtlCommand(), + NewClusterMigrateCutOverCommand(), + NewClusterBackendSwitchCommand(), }, }, } diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/subcmd_helper.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/subcmd_helper.go index f100f7d040..96ede3df71 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/subcmd_helper.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/subcmd_helper.go @@ -222,7 +222,7 @@ func (d *Definition) ExpandProperties(defs *Definitions) { for pname, prop := range d.Properties { prop.depth = d.depth prop.name = pname - if util.StringsHas(d.Required, pname) { + if util.ContainElem(d.Required, pname) { prop.required = true } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go index 8bae6b4dcf..c2f1ebc68d 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go @@ -24,16 +24,29 @@ type RuntimeAccountParam struct { TdbctlAccoutParam } +// GetAllSysAccount TODO +func (g *RuntimeAccountParam) GetAllSysAccount() (accounts []string) { + accounts = append(accounts, g.AdminUser) + accounts = append(accounts, g.DbBackupUser) + accounts = append(accounts, g.MonitorAccessAllUser) + accounts = append(accounts, g.MonitorUser) + accounts = append(accounts, g.ReplUser) + accounts = append(accounts, g.YwUser) + accounts = append(accounts, g.TdbctlUser) + return +} + // GetAccountRepl TODO func GetAccountRepl(g *GeneralParam) MySQLReplAccount { Repl := MySQLReplAccount{} - if g == nil { + switch { + case g == nil: return Repl - } else if &g.RuntimeAccountParam == nil { + case g.RuntimeAccountParam == RuntimeAccountParam{}: return Repl - } else if &g.RuntimeAccountParam.MySQLAccountParam == nil { + case g.RuntimeAccountParam.MySQLAccountParam == MySQLAccountParam{}: return Repl - } else { - return g.RuntimeAccountParam.MySQLAccountParam.MySQLReplAccount + default: + return g.RuntimeAccountParam.MySQLReplAccount } } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/base.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/base.go index 2c4a525a6c..efc686d979 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/base.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/base.go @@ -389,6 +389,7 @@ func (m *MySQLClusterDetail) MSVarsCheck(checkVars []string) (err error) { type MSCheck struct { SlavedbConn *native.DbWorker NeedCheckSumRd bool // 需要存在校验记录 + NotVerifyChecksum bool // 是否检查checksum AllowDiffCount int // 允许存在差异的校验记录的行数 AllowDelaySec int // 允许存在的延迟差异 AllowDelayBinlogByte int // 允许binlog的最大延迟 @@ -406,8 +407,17 @@ func NewMsCheck(dbConn *native.DbWorker) *MSCheck { } // Check TODO -// ValidateCheckSum 校验checksum 表 func (s *MSCheck) Check() (err error) { + slaveStatus, err := s.SlavedbConn.ShowSlaveStatus() + if err != nil { + return err + } + if !slaveStatus.ReplSyncIsOk() { + return fmt.Errorf( + "IOThread:%s,SQLThread:%s", + slaveStatus.SlaveIORunning, slaveStatus.SlaveSQLRunning, + ) + } // 检查主从同步delay binlog size total, err := s.SlavedbConn.TotalDelayBinlogSize() if err != nil { @@ -417,14 +427,30 @@ func (s *MSCheck) Check() (err error) { if total > s.AllowDelayBinlogByte { return fmt.Errorf("the total delay binlog size %d 超过了最大允许值 %d", total, s.AllowDelayBinlogByte) } + var delaysec int + c := fmt.Sprintf( + `select check_result as slave_delay from %s.master_slave_check + WHERE check_item='slave_delay_sec';`, native.INFODBA_SCHEMA, + ) + if err = s.SlavedbConn.Queryxs(&delaysec, c); err != nil { + logger.Error("查询slave delay sec: %s", err.Error()) + return err + } + if delaysec > s.AllowDelaySec { + return fmt.Errorf("slave 延迟时间 %d, 超过了上限 %d", delaysec, s.AllowDelaySec) + } // 以为内部版本需要校验的参数 if s.SlavedbConn.IsEmptyInstance() { logger.Info("主从关系正常,从库是空实例,跳过检查checksum表") return nil } + // 如果不需要检查checksum table 则直接返回 + if s.NotVerifyChecksum { + return + } var cnt int - c := fmt.Sprintf( + c = fmt.Sprintf( "select count(distinct db, tbl) as cnt from %s.checksum where ts > date_sub(now(), interval 14 day)", native.INFODBA_SCHEMA, ) @@ -452,21 +478,11 @@ func (s *MSCheck) Check() (err error) { logger.Error("查询数据校验差异表失败: %s", err.Error()) return err } - c = fmt.Sprintf( - `select check_result as slave_delay from %s.master_slave_check - WHERE check_item='slave_delay_sec';`, native.INFODBA_SCHEMA, - ) + if cnt > s.AllowDiffCount { return fmt.Errorf("checksum 不同值的 chunk 个数是 %d, 超过了上限 %d", cnt, s.AllowDiffCount) } - var delaysec int - if err = s.SlavedbConn.Queryxs(&delaysec, c); err != nil { - logger.Error("查询slave delay sec: %s", err.Error()) - return err - } - if delaysec > s.AllowDelaySec { - return fmt.Errorf("slave 延迟时间 %d, 超过了上限 %d", delaysec, s.AllowDelaySec) - } + return nil } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go index bdf73c9886..9be13ac50c 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go @@ -200,13 +200,17 @@ func (m *CutOverToSlaveComp) PreCheck() (err error) { return nil } - if err = m.cluster.AltSlaveIns.dbConn.CheckSlaveReplStatus(); err != nil { + if err = m.cluster.AltSlaveIns.dbConn.CheckSlaveReplStatus(func() (resp native.ShowSlaveStatusResp, err error) { + return m.cluster.AltSlaveIns.dbConn.ShowSlaveStatus() + }); err != nil { logger.Error("检查主从同步状态出错: %s", err.Error()) return err } if m.isCutOverPair { - if err = m.cluster.AltSlaveIns.Slave.dbConn.CheckSlaveReplStatus(); err != nil { + if err = m.cluster.AltSlaveIns.Slave.dbConn.CheckSlaveReplStatus(func() (resp native.ShowSlaveStatusResp, err error) { + return m.cluster.AltSlaveIns.Slave.dbConn.ShowSlaveStatus() + }); err != nil { return err } } @@ -265,7 +269,9 @@ func (m *CutOverToSlaveComp) CutOver() (binPos string, err error) { } if !m.Params.IsDeadMaster { - if err = m.cluster.AltSlaveIns.dbConn.CheckSlaveReplStatus(); err != nil { + if err = m.cluster.AltSlaveIns.dbConn.CheckSlaveReplStatus(func() (resp native.ShowSlaveStatusResp, err error) { + return m.cluster.AltSlaveIns.dbConn.ShowSlaveStatus() + }); err != nil { logger.Error("再次检查下主从状态 %s", err.Error()) return "", err } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go new file mode 100644 index 0000000000..5319e02957 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go @@ -0,0 +1,497 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package spiderctl + +import ( + "errors" + "fmt" + "time" + + "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/pkg/components" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover" + "dbm-services/mysql/db-tools/dbactuator/pkg/native" +) + +// scene 1 +// +// spider --> master <-- slave +// slave_spider ----------^ +// +// after cutover +// +// spider --> new_master <-- new_slave +// slave_spider ----------------^ + +// scene 2 +// the spider cluster not have slave +// +// spider --> master +// +// after cutover +// +// spider --> new_master + +// SpiderClusterBackendMigrateCutoverComp TODO +type SpiderClusterBackendMigrateCutoverComp struct { + GeneralParam *components.GeneralParam `json:"general"` + Params *RemotedbdrMigrateCutoverParam `json:"extend"` + ctx +} + +// 迁移切换前置条件: +// 带切换的实例, dest master,dest slave 需要提前给tdbctl中控授权 + +// RemotedbdrMigrateCutoverParam TODO +type RemotedbdrMigrateCutoverParam struct { + // tdbctl host port + Host string `json:"host" validate:"required,ip"` + Port int `json:"port" validate:"required,lt=65536,gte=3306"` + // 客户端连接检查 + ClientConnCheck bool `json:"client_conn_check"` + // 主从延迟检查 + SlaveDelayCheck bool `json:"slave_delay_check"` + // 数据校验结果检查 + VerifyChecksum bool `json:"verify_checksum"` + MigrateCutoverPairs []MigrateCutoverPair `json:"migrate_cutover_pairs"` +} + +type ctx struct { + CutOverCtx + destMasterConn map[IPPORT]*native.DbWorker + destSlaveConn map[IPPORT]*native.DbWorker + cutOverPairs []CutOverParis + existRemoteSlave bool + checkVars []string +} + +// CutOverParis TODO +type CutOverParis struct { + MasterSvr native.Server + SlaveSvr native.Server + DestMaster CutoverUnit + DestSlave CutoverUnit +} + +// MigrateCutoverPair TODO +type MigrateCutoverPair struct { + Master Instance `json:"origin_master" validate:"required"` + DestMaster CutoverUnit `json:"dest_master" validate:"required"` + DestSlave CutoverUnit `json:"dest_slave"` +} + +const ( + // DelayThreshold TODO + // #slave io_thread behand master time + // my $allowed_slave_delay_max = 120; + // #slave system time behand master time + // my $allowed_time_delay_max = 10; + // my $exec_delay_threshold = 1024; #kbyte + DelayThreshold = 1024 * 10 // 10k +) + +// destSlaveIsEmpty TODO +// 如果参数 +func (m *MigrateCutoverPair) destSlaveIsEmpty() bool { + return m.DestSlave == CutoverUnit{} +} + +// CutoverUnit TODO +type CutoverUnit struct { + Host string `json:"host" validate:"required,ip"` + Port int `json:"port" validate:"required,lt=65536,gte=3306"` + // account password used by the tdbctl system + User string `json:"user"` + Password string `json:"password"` +} + +// GetAlterNodeSql TODO +func (c *CutoverUnit) GetAlterNodeSql(svrName string) string { + return fmt.Sprintf("TDBCTL ALTER NODE %s options(user '%s', password '%s', host '%s', port %d);", + svrName, + c.User, + c.Password, c.Host, c.Port) +} + +// GetHostPort TODO +func (c *CutoverUnit) GetHostPort() string { + return fmt.Sprintf("%s:%d", c.Host, c.Port) +} + +// Conn TODO +func (c *CutoverUnit) Conn() (conn *native.DbWorker, err error) { + conn, err = native.InsObject{ + Host: c.Host, + Port: c.Port, + User: c.User, + Pwd: c.Password, + }.Conn() + return +} + +// Example TODO +func (s *SpiderClusterBackendMigrateCutoverComp) Example() interface{} { + return SpiderClusterBackendMigrateCutoverComp{ + Params: &RemotedbdrMigrateCutoverParam{ + Host: "1.1.1.1", + Port: 26000, + ClientConnCheck: true, + SlaveDelayCheck: true, + VerifyChecksum: true, + MigrateCutoverPairs: []MigrateCutoverPair{ + { + Master: Instance{ + Host: "2.2.2.2", + Port: 3006, + }, + DestMaster: CutoverUnit{ + Host: "3.3.3.3", + Port: 3306, + User: "xx", + Password: "xx", + }, + DestSlave: CutoverUnit{ + Host: "4.4.4.4", + Port: 3306, + User: "xx", + Password: "xx", + }, + }, + { + Master: Instance{ + Host: "2.2.2.2", + Port: 3007, + }, + DestMaster: CutoverUnit{ + Host: "3.3.3.3", + Port: 3307, + User: "xx", + Password: "xx", + }, + DestSlave: CutoverUnit{ + Host: "4.4.4.4", + Port: 3307, + User: "xx", + Password: "xx", + }, + }, + }, + }, + } +} + +// Init TODO +func (s *SpiderClusterBackendMigrateCutoverComp) Init() (err error) { + logger.Info("cutover param is %v", s.Params.MigrateCutoverPairs) + var conn *native.DbWorker + conn, err = native.InsObject{ + Host: s.Params.Host, + Port: s.Params.Port, + User: s.GeneralParam.RuntimeAccountParam.AdminUser, + Pwd: s.GeneralParam.RuntimeAccountParam.AdminPwd, + }.Conn() + if err != nil { + return err + } + s.tdbCtlConn = &native.TdbctlDbWork{DbWorker: *conn} + // 查询mysql.servers tables + servers, err := s.tdbCtlConn.SelectServers() + if err != nil { + return err + } + // connect spider + s.spidersConn, err = ConnSpiders(servers) + if err != nil { + return err + } + // conn dest master slave + if err = s.connDest(); err != nil { + return err + } + s.getSysUsers(servers, append(s.GeneralParam.RuntimeExtend.MySQLSysUsers, + s.GeneralParam.RuntimeAccountParam.GetAllSysAccount()...)) + ipPortServersMap, svrNameServersMap := transServersToMap(servers) + s.ipPortServersMap = ipPortServersMap + s.svrNameServersMap = svrNameServersMap + s.checkVars = []string{"character_set_server", "lower_case_table_names", "time_zone", "binlog_format", + "log_bin_compress"} + return nil +} + +// PreCheck TODO +func (s *SpiderClusterBackendMigrateCutoverComp) PreCheck() (err error) { + if err := s.cutOverParisParamCheck(); err != nil { + return err + } + // check dest master with dest slave replicate status + if s.existRemoteSlave { + logger.Info("check whether the master slave synchronization status to be switched is normal") + if err = replStatusCheck(s.destSlaveConn, s.Params.VerifyChecksum, 10); err != nil { + return err + } + } + // compare origin master with dest master variables + if err = s.validateServers(); err != nil { + return err + } + logger.Info("check whether the key variables of the source master and the target master are consistent") + if err = s.checkPairsVariables(); err != nil { + return err + } + if s.Params.ClientConnCheck { + if err := s.CheckSpiderAppProcesslist(); err != nil { + return err + } + } + // 检查数据checksum和延迟等 + var allow_delay int + if s.Params.SlaveDelayCheck { + allow_delay = 1 + } + // check origin master with dest master replicate status + if err = replStatusCheck(s.destMasterConn, s.Params.VerifyChecksum, allow_delay); err != nil { + return err + } + return err +} + +func (s *SpiderClusterBackendMigrateCutoverComp) checkPairsVariables() (err error) { + for _, pair := range s.cutOverPairs { + svrName := pair.MasterSvr.ServerName + destMasterConn, ok := s.destMasterConn[pair.DestMaster.GetHostPort()] + if !ok { + return fmt.Errorf("get %s conn from destMasterConn map failed", pair.DestMaster.GetHostPort()) + } + if err = s.tdbCtlConn.MySQLVarsCompare(svrName, destMasterConn, s.checkVars); err != nil { + return err + } + } + return +} + +// cutOverParisParamCheck 参数中、目标的master 和目标slave 检查 +// 目标slave 只能都为空、或者呀完全匹配目标master的个数 +func (s *SpiderClusterBackendMigrateCutoverComp) cutOverParisParamCheck() (err error) { + destSlaveNum := 0 + s.existRemoteSlave = false + for _, ins := range s.Params.MigrateCutoverPairs { + if ins.destSlaveIsEmpty() { + if destSlaveNum > 0 { + return fmt.Errorf("you must send slave param for master: %s", ins.DestMaster.GetHostPort()) + } + continue + } + destSlaveNum++ + } + slaveSptServers := s.getSlaveSptServers() + slaveSpiderServers := s.getSlaveSpiderServers() + // 如果传参中并没有待切换的slave + // 但是在mysql.server 表中查询到了spider slave 相关信息 + // 则需要抛出异常 + if destSlaveNum == 0 && len(slaveSptServers) > 0 && len(slaveSpiderServers) > 0 { + return errors.New(`the origin spider cluster exist spider spt and slave spider, + but this time cutover not have waited cutover slaves`) + } + // 其他情况只切换spider master对应的主分片 + if destSlaveNum == len(s.Params.MigrateCutoverPairs) { + s.existRemoteSlave = true + } + return nil +} + +func (s *SpiderClusterBackendMigrateCutoverComp) connDest() (err error) { + s.destMasterConn = make(map[string]*native.DbWorker) + s.destSlaveConn = make(map[string]*native.DbWorker) + for _, ins := range s.Params.MigrateCutoverPairs { + destMasterAddr := ins.DestMaster.GetHostPort() + logger.Info("connecting %s ...", destMasterAddr) + masterConn, err := ins.DestMaster.Conn() + if err != nil { + return err + } + s.destMasterConn[destMasterAddr] = masterConn + if !ins.destSlaveIsEmpty() { + slaveConn, err := ins.DestMaster.Conn() + if err != nil { + return err + } + s.destSlaveConn[ins.DestSlave.GetHostPort()] = slaveConn + } + } + logger.Info("dest master conn %v", s.destMasterConn) + return +} + +func replStatusCheck(conns map[string]*native.DbWorker, validateChecksum bool, allowDelayThreshold int) (err error) { + for addr, conn := range conns { + mscheck := &cutover.MSCheck{ + SlavedbConn: conn, + NeedCheckSumRd: validateChecksum, + NotVerifyChecksum: !validateChecksum, + AllowDiffCount: 10, + AllowDelaySec: allowDelayThreshold, + AllowDelayBinlogByte: DelayThreshold, + } + if err = mscheck.Check(); err != nil { + return fmt.Errorf("slave %s, master slave data check failed %w", addr, err) + } + } + return +} + +func (s *SpiderClusterBackendMigrateCutoverComp) validateServers() (err error) { + for _, ins := range s.Params.MigrateCutoverPairs { + var mastersvr native.Server + var exist bool + var pair CutOverParis + if mastersvr, exist = s.ipPortServersMap[ins.Master.IpPort()]; !exist { + return fmt.Errorf("master %s: not found in mysql.servers", ins.Master.IpPort()) + } + if !native.SvrNameIsMasterShard(mastersvr.ServerName) { + return fmt.Errorf("%s in tdbctl server name is not master shard", ins.Master.IpPort()) + } + if s.existRemoteSlave { + slaveSptName := native.GetSlaveShardNameByMasterShardName(mastersvr.ServerName) + logger.Info("slave spt name is:%s", slaveSptName) + slavesvr, exists := s.svrNameServersMap[slaveSptName] + if !exists { + return fmt.Errorf("the key %s,not found in svrNameServersMap ", slaveSptName) + } + pair.SlaveSvr = slavesvr + pair.DestSlave = ins.DestSlave + } else { + pair.MasterSvr = mastersvr + pair.DestMaster = ins.DestMaster + } + s.cutOverPairs = append(s.cutOverPairs, pair) + } + return +} + +// CutOver TODO +func (s *SpiderClusterBackendMigrateCutoverComp) CutOver() (err error) { + var flushed bool + logger.Info("the switching operation will be performed") + // change the central control route + logger.Info("start refreshing the primary spt route") + var rollbackSqls []string + if rollbackSqls, err = s.switchSpt(); err != nil { + return err + } + // release the lock until after performing the rollback routing + defer s.Unlock() + defer func() { + if err != nil && len(rollbackSqls) > 0 { + _, xerr := s.tdbCtlConn.ExecMore(rollbackSqls) + if xerr != nil { + logger.Error("rollbackup tdbctl router failed %s", xerr.Error()) + err = fmt.Errorf("%w,rollbackup err:%w", err, xerr) + return + } + logger.Info("rollback route successfully~") + if flushed { + if ferr := s.flushrouting(); ferr != nil { + err = fmt.Errorf("%w,flush rollback route err:%w", err, ferr) + return + } + logger.Info("rollback route successfully~") + } + } + }() + logger.Info("update tdbctl mysql.servers successfully") + // lock all spider write + logger.Info("start locking the spider") + if err = s.LockaAllSpidersWrite(); err != nil { + return err + } + logger.Info("lock all spider successfully,record the location of each instance binlog") + // record the binlog position information during the handover + if err = s.CheckMsSyncStatusAndRecordBinlogPos(); err != nil { + return err + } + logger.Info("doing tdbctl flush routing force ... ") + return s.flushrouting() +} + +// StopRepl TODO +func (s *SpiderClusterBackendMigrateCutoverComp) StopRepl() (err error) { + for hostPort, destMasterConn := range s.destMasterConn { + logger.Info("%s: execute stop slave,reset slave", hostPort) + if _, err = destMasterConn.ExecMore([]string{"stop slave;", "reset slave all;"}); err != nil { + return err + } + } + return nil +} + +// CheckMsSyncStatusAndRecordBinlogPos TODO +func (s *SpiderClusterBackendMigrateCutoverComp) CheckMsSyncStatusAndRecordBinlogPos() (err error) { + for hostPort, destMasterConn := range s.destMasterConn { + logger.Info("check replicate status...") + slaveStatus, err := destMasterConn.ShowSlaveStatus() + if err != nil { + return err + } + if !slaveStatus.ReplSyncIsOk() { + return fmt.Errorf("%s replication status is abnormal ,IO Thread: %s,SQL Thread:%s", hostPort, + slaveStatus.SlaveIORunning, + slaveStatus.SlaveSQLRunning) + } + cmutil.Retry(cmutil.RetryConfig{ + DelayTime: 1 * time.Second, + Times: 10, + }, func() error { + delaytotalByte, err := destMasterConn.TotalDelayBinlogSize() + if err != nil { + return err + } + if delaytotalByte <= 0 || (!s.Params.SlaveDelayCheck && delaytotalByte < DelayThreshold) { + logger.Info("synchronization delay check is normal") + } else { + return fmt.Errorf("slave binlog still behand master %d byte", delaytotalByte) + } + return nil + }) + logger.Info("record %s master status", hostPort) + pos, err := destMasterConn.ShowMasterStatus() + if err != nil { + logger.Warn("%s show master status failed %s", hostPort, err.Error()) + return nil + } + logger.Info("%s,current pos is binlog_file:%s,binlog_pos:%d,gitid_sets:%s", hostPort, pos.File, + pos.Position, + pos.ExecutedGtidSet) + } + return nil +} + +func (s *SpiderClusterBackendMigrateCutoverComp) switchSpt() (rollbackRouters []string, err error) { + logger.Info("start switch master spt ...") + var alterSqls []string + for _, pair := range s.cutOverPairs { + masterSvrName := pair.MasterSvr.ServerName + rollbackRouters = append(rollbackRouters, pair.MasterSvr.GetAlterNodeSql(masterSvrName)) + alterSql := pair.DestMaster.GetAlterNodeSql(masterSvrName) + logger.Info("will execute master spt switch sql:%s", alterSql) + alterSqls = append(alterSqls, alterSql) + if s.existRemoteSlave { + slaveSvrName := pair.SlaveSvr.ServerName + rollbackRouters = append(rollbackRouters, pair.SlaveSvr.GetAlterNodeSql(slaveSvrName)) + alterSql := pair.SlaveSvr.GetAlterNodeSql(slaveSvrName) + logger.Info("will execute slave spt switch sql:%s", alterSql) + } + } + if _, err = s.tdbCtlConn.ExecMore(alterSqls); err != nil { + return + } + return rollbackRouters, err +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go new file mode 100644 index 0000000000..5a42fc30be --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go @@ -0,0 +1,634 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package spiderctl + +import ( + "fmt" + "regexp" + "strings" + "time" + + "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/pkg/components" + "dbm-services/mysql/db-tools/dbactuator/pkg/native" +) + +// SpiderClusterBackendSwitchComp TODO +type SpiderClusterBackendSwitchComp struct { + GeneralParam *components.GeneralParam `json:"general"` + Params *SpiderRemotedbSwitchParam `json:"extend"` + runtimeCtx +} +type runtimeCtx struct { + CutOverCtx + realSwitchSvrPairs []SvrPairs + slavesConn map[IPPORT]*native.DbWorker + mastesConn map[IPPORT]*native.DbWorker +} + +// SpiderRemotedbSwitchParam TODO +type SpiderRemotedbSwitchParam struct { + Host string `json:"host" validate:"required,ip"` + Port int `json:"port" validate:"required,lt=65536,gte=3306"` + // 客户端连接检查 + ClientConnCheck bool `json:"client_conn_check"` + // 主从延迟检查 + SlaveDelayCheck bool `json:"slave_delay_check"` + // 数据校验结果检查 + VerifyChecksum bool `json:"verify_checksum"` + SwitchParis []SwitchUnit `json:"switch_paris" validate:"required,gt=0,dive"` + // force: 忽略部分切换前检查 + Force bool `json:"force"` +} + +// CutOverCtx TODO +type CutOverCtx struct { + tdbCtlConn *native.TdbctlDbWork + spidersConn map[string]*native.DbWorker + ipPortServersMap map[IPPORT]native.Server + svrNameServersMap map[SVRNAME]native.Server + newMasterPosInfos map[string]native.MasterStatusResp + sysUsers []string +} + +// SvrPairs TODO +type SvrPairs struct { + MptName string + SptName string + Master *native.Server + Slave *native.Server +} + +// SwitchUnit TODO +type SwitchUnit struct { + Master Instance `json:"master" validate:"required"` + Slave Instance `json:"slave" validate:"required"` +} + +// IpPort TODO +func (i Instance) IpPort() string { + return fmt.Sprintf("%s:%d", i.Host, i.Port) +} + +// Example TODO +func (r *SpiderClusterBackendSwitchComp) Example() interface{} { + return SpiderClusterBackendSwitchComp{ + Params: &SpiderRemotedbSwitchParam{ + Host: "1.1.1.1", + Port: 26000, + ClientConnCheck: true, + SlaveDelayCheck: true, + VerifyChecksum: true, + SwitchParis: []SwitchUnit{ + { + Master: Instance{ + Host: "2.2.2.2", + Port: 3306, + }, + Slave: Instance{ + Host: "3.3.3.3", + Port: 3306, + }, + }, + { + Master: Instance{ + Host: "2.2.2.2", + Port: 3307, + }, + Slave: Instance{ + Host: "3.3.3.3", + Port: 3307, + }, + }, + }, + }, + } +} + +// Init TODO +func (r *SpiderClusterBackendSwitchComp) Init() (err error) { + r.ipPortServersMap = make(map[string]native.Server) + logger.Info("tdbctl connecting ...") + if err = r.connTdbctl(); err != nil { + logger.Error("Connect %d failed:%s", r.Params.Port, err.Error()) + return err + } + logger.Info("query tdbctl servers") + servers, err := r.tdbCtlConn.SelectServers() + if err != nil { + return err + } + // connect spider + logger.Info("connecting all spider ...") + r.spidersConn, err = ConnSpiders(servers) + if err != nil { + return err + } + logger.Info("get all sys users ...") + r.getSysUsers(servers, append(r.GeneralParam.RuntimeExtend.MySQLSysUsers, + r.GeneralParam.RuntimeAccountParam.GetAllSysAccount()...)) + ipPortServersMap, svrNameServersMap := transServersToMap(servers) + r.ipPortServersMap = ipPortServersMap + r.svrNameServersMap = svrNameServersMap + logger.Info("connect backend instance ...") + r.mastesConn = make(map[string]*native.DbWorker) + r.slavesConn = make(map[string]*native.DbWorker) + for _, swpair := range r.Params.SwitchParis { + masterAddr := swpair.Master.IpPort() + slaveAddr := swpair.Slave.IpPort() + masterSvr, ok := ipPortServersMap[masterAddr] + if !ok { + return fmt.Errorf("%s: servers not exist in ipPortServersMap", masterAddr) + } + slaveSvr, ok := ipPortServersMap[slaveAddr] + if !ok { + return fmt.Errorf("%s: servers not exist in ipPortServersMap", slaveAddr) + } + masterConn, err := masterSvr.GetConn() + if err != nil { + return err + } + r.mastesConn[masterAddr] = masterConn + slaveConn, err := slaveSvr.GetConn() + if err != nil { + return err + } + r.slavesConn[slaveAddr] = slaveConn + } + return nil +} + +// PreCheck TODO +func (r *SpiderClusterBackendSwitchComp) PreCheck() (err error) { + // verify whether the instance relationship in the parameters is consistent with tdbctl servers + logger.Info("verify whether the instance relationship in the parameters is consistent with tdbctl servers") + if err = r.validateServers(); err != nil { + return err + } + if err = r.consistencySwitchCheck(); err != nil { + if r.Params.Force { + logger.Warn(err.Error()) + return nil + } + return err + } + return nil +} + +func (r *SpiderClusterBackendSwitchComp) consistencySwitchCheck() (err error) { + // 检查复制关系 + if err = r.checkReplicationRelation(); err != nil { + return err + } + if r.Params.ClientConnCheck { + if err := r.CheckSpiderAppProcesslist(); err != nil { + return err + } + } + // 检查数据checksum和延迟等 + var allow_delay int + if r.Params.SlaveDelayCheck { + allow_delay = 1 + } + if err = replStatusCheck(r.slavesConn, r.Params.VerifyChecksum, allow_delay); err != nil { + return err + } + return nil +} + +// ConnSpiders TODO +func ConnSpiders(servers []native.Server) (conns map[string]*native.DbWorker, err error) { + conns = make(map[string]*native.DbWorker) + spider_regexp := regexp.MustCompile(native.SPIDER_PREFIX) + for _, server := range servers { + if spider_regexp.MatchString(server.ServerName) { + conn, err := native.InsObject{ + Host: server.Host, + Port: server.Port, + User: server.Username, + Pwd: server.Password, + }.Conn() + if err != nil { + return nil, err + } + key := fmt.Sprintf("%s:%d", server.Host, server.Port) + conns[key] = conn + } + } + return +} + +// checkReplicationRelation TODO +// checkSlaveStatus 检查remotedb remotedr 同步关系是否正常 +func (r *SpiderClusterBackendSwitchComp) checkReplicationRelation() (err error) { + for _, switch_pair := range r.Params.SwitchParis { + slaveptname, err := r.getSvrName(switch_pair.Slave.IpPort()) + if err != nil { + return err + } + slaveStaus, err := r.tdbCtlConn.ShowSlaveStatus(slaveptname) + if err != nil { + return err + } + // 检查从库实际的复制主库是否正确 + replMaster := fmt.Sprintf("%s:%d", slaveStaus.MasterHost, slaveStaus.MasterPort) + if strings.Compare(replMaster, switch_pair.Master.IpPort()) != 0 { + return fmt.Errorf("the %s real repl from %s,but the send param master is %s", switch_pair.Slave.IpPort(), + replMaster, switch_pair.Master.IpPort()) + } + err = r.tdbCtlConn.CheckSlaveReplStatus(func() (resp native.ShowSlaveStatusResp, err error) { + return r.tdbCtlConn.ShowSlaveStatus(slaveptname) + }) + if err != nil { + return err + } + } + return +} + +func (r *SpiderClusterBackendSwitchComp) checkReplicationStatus() (err error) { + for _, switch_pair := range r.Params.SwitchParis { + slaveptname, err := r.getSvrName(switch_pair.Slave.IpPort()) + if err != nil { + return err + } + logger.Info("check %s replicate status ...", switch_pair.Slave.IpPort()) + err = r.tdbCtlConn.CheckSlaveReplStatus(func() (resp native.ShowSlaveStatusResp, err error) { + return r.tdbCtlConn.ShowSlaveStatus(slaveptname) + }) + if err != nil { + return err + } + } + return +} + +func (r *SpiderClusterBackendSwitchComp) getSvrName(hostport string) (svrName string, err error) { + if svr, ok := r.ipPortServersMap[hostport]; ok { + return svr.ServerName, nil + } + return "", fmt.Errorf("get servers empty by %s", hostport) +} + +// IPPORT TODO +type IPPORT = string + +// SVRNAME TODO +type SVRNAME = string + +func transServersToMap(servers []native.Server) (map[IPPORT]native.Server, map[SVRNAME]native.Server) { + m := make(map[IPPORT]native.Server) + sm := make(map[string]native.Server) + for _, server := range servers { + key := fmt.Sprintf("%s:%d", server.Host, server.Port) + m[key] = server + sm[server.ServerName] = server + } + return m, sm +} + +func (r *SpiderClusterBackendSwitchComp) validateServers() (err error) { + svrmap := r.ipPortServersMap + for _, ms := range r.Params.SwitchParis { + var mastersvr, slavesvr native.Server + var exist bool + mh := ms.Master.IpPort() + if mastersvr, exist = svrmap[mh]; !exist { + return fmt.Errorf("master %s: not found in mysql.servers", mh) + } + if !native.SvrNameIsMasterShard(mastersvr.ServerName) { + return fmt.Errorf("%s in tdbctl server name:%s is not master shard", mh, mastersvr.ServerName) + } + sh := ms.Slave.IpPort() + if slavesvr, exist = svrmap[sh]; !exist { + return fmt.Errorf("slave %s: not found in mysql.servers", sh) + } + if !native.SvrNameIsSlaveShard(slavesvr.ServerName) { + return fmt.Errorf("%s in tdbctl server name:%s is not slave shard", sh, slavesvr.ServerName) + } + masterShardNum := native.GetShardNumberFromMasterServerName(mastersvr.ServerName) + slaveShardNum := native.GetShardNumberFromSlaveServerName(slavesvr.ServerName) + if cmutil.IsEmpty(masterShardNum) { + return fmt.Errorf("the master %s shard id is empty", mh) + } + if cmutil.IsEmpty(slaveShardNum) { + return fmt.Errorf("the slave %s shard id is empty", sh) + } + if strings.Compare(masterShardNum, slaveShardNum) != 0 { + return fmt.Errorf("master slave shard id is not equal,master shard id is %s,slave shard id is %s", + masterShardNum, + slaveShardNum) + } + r.realSwitchSvrPairs = append(r.realSwitchSvrPairs, SvrPairs{ + MptName: mastersvr.ServerName, + SptName: slavesvr.ServerName, + Master: &mastersvr, + Slave: &slavesvr, + }) + } + return nil +} + +func (r *SpiderClusterBackendSwitchComp) connTdbctl() (err error) { + // connection central control + conn, err := native.InsObject{ + Host: r.Params.Host, + Port: r.Params.Port, + User: r.GeneralParam.RuntimeAccountParam.AdminUser, + Pwd: r.GeneralParam.RuntimeAccountParam.AdminPwd, + }.Conn() + r.tdbCtlConn = &native.TdbctlDbWork{DbWorker: *conn} + return err +} + +// CutOver TODO +func (r *SpiderClusterBackendSwitchComp) CutOver() (err error) { + var flushed bool + logger.Info("the switching operation will be performed") + // 更改中控路由 + logger.Info("refresh the tdbctl route") + defer r.Unlock() + var rollbackRouters []string + if rollbackRouters, err = r.switchMaterSpt(); err != nil { + return err + } + defer func() { + if err != nil { + if len(rollbackRouters) > 0 { + logger.Info("start execute rollback router sql ... ") + _, rerr := r.tdbCtlConn.ExecMore(rollbackRouters) + if rerr != nil { + logger.Error("failed to roll back tdbctl routing") + return + } + logger.Info("rollback route successfully~") + if flushed { + ferr := r.flushrouting() + if ferr != nil { + return + } + logger.Info("flush rollback route successfully~") + } + } + } + }() + // lock all spider write + logger.Info("start locking the spider node") + if err = r.LockaAllSpidersWrite(); err != nil { + return err + } + // 再次检查复制状态 + if !r.Params.Force { + if err = r.checkReplicationStatus(); err != nil { + return err + } + } + logger.Info("记录各个节点binlog的位置") + // record the binlog position information during the handover + if err = r.recordBinLogPos(); err != nil { + return err + } + // flush 到中控生效 + logger.Info("执行:tdbctl flush routing force") + return r.flushrouting() +} + +func (r *SpiderClusterBackendSwitchComp) switchMaterSpt() (rollbackRouterSqls []string, err error) { + for _, ins_pair := range r.realSwitchSvrPairs { + switch_sql := ins_pair.Slave.GetAlterNodeSql(ins_pair.MptName) + rollbackRouterSqls = append(rollbackRouterSqls, ins_pair.Master.GetAlterNodeSql(ins_pair.MptName)) + // log的时候需要隐藏密码 + logger.Info("will execute switch sql:%s", switch_sql) + _, err = r.tdbCtlConn.Exec(switch_sql) + if err != nil { + return rollbackRouterSqls, err + } + } + return +} + +// SwitchSlaveSpt TODO +func (r *SpiderClusterBackendSwitchComp) SwitchSlaveSpt() (err error) { + // switch spider rout + var rollback_switch_sqls []string + defer func() { + if err != nil && len(rollback_switch_sqls) > 0 { + _, xerr := r.tdbCtlConn.ExecMore(rollback_switch_sqls) + if xerr != nil { + logger.Error("rollbackup tdbctl router failed %s", xerr.Error()) + } + err = fmt.Errorf("%w,rollbackup err:%w", err, xerr) + } + }() + + for _, ins_pair := range r.realSwitchSvrPairs { + switch_sql := ins_pair.Master.GetAlterNodeSql(ins_pair.SptName) + rollback_switch_sqls = append(rollback_switch_sqls, ins_pair.Slave.GetAlterNodeSql(ins_pair.SptName)) + // log的时候需要隐藏密码 + logger.Info("will execute switch sql:%s", switch_sql) + _, err = r.tdbCtlConn.Exec(switch_sql) + if err != nil { + return err + } + } + return +} + +func (r *SpiderClusterBackendSwitchComp) recordBinLogPos() (err error) { + r.newMasterPosInfos = make(map[string]native.MasterStatusResp) + for _, swpair := range r.Params.SwitchParis { + conn, ok := r.slavesConn[swpair.Slave.IpPort()] + if !ok { + return fmt.Errorf("get %s conn failed", swpair.Slave.IpPort()) + } + pos, err := conn.ShowMasterStatus() + if err != nil { + return err + } + logger.Info("%s,current pos is binlog_file:%s,binlog_pos:%d,gitid_sets:%s", swpair.Slave.IpPort(), pos.File, + pos.Position, + pos.ExecutedGtidSet) + r.newMasterPosInfos[swpair.Slave.IpPort()] = pos + } + return +} + +// GrantReplForNewSlave TODO +func (r *SpiderClusterBackendSwitchComp) GrantReplForNewSlave() (err error) { + for _, swpair := range r.Params.SwitchParis { + conn, ok := r.slavesConn[swpair.Slave.IpPort()] + if !ok { + return fmt.Errorf("get %s conn failed", swpair.Slave.IpPort()) + } + if _, err = conn.ExecMore(r.grantReplSql(swpair.Master.Host)); err != nil { + return err + } + } + return nil +} + +// StopRepl TODO +func (r *SpiderClusterBackendSwitchComp) StopRepl() (err error) { + for _, swpair := range r.Params.SwitchParis { + conn, ok := r.slavesConn[swpair.Slave.IpPort()] + if !ok { + return fmt.Errorf("get %s conn failed", swpair.Slave.IpPort()) + } + if _, err = conn.ExecMore([]string{"stop slave;", "reset slave all;"}); err != nil { + return err + } + } + return nil +} + +func (r *SpiderClusterBackendSwitchComp) grantReplSql(host string) []string { + var execSQLs []string + repl_user := r.GeneralParam.RuntimeAccountParam.ReplUser + repl_pwd := r.GeneralParam.RuntimeAccountParam.ReplPwd + logger.Info("repl user:%s,repl_pwd:%s", repl_user, repl_pwd) + execSQLs = append(execSQLs, fmt.Sprintf("CREATE USER /*!50706 IF NOT EXISTS */ `%s`@`%s` IDENTIFIED BY '%s';", + repl_user, host, repl_pwd)) + execSQLs = append(execSQLs, fmt.Sprintf("GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO `%s`@`%s`;", repl_user, + host)) + return execSQLs +} + +// ChangeMasterToNewMaster TODO +func (r *SpiderClusterBackendSwitchComp) ChangeMasterToNewMaster() (err error) { + repl_user := r.GeneralParam.RuntimeAccountParam.ReplUser + repl_pwd := r.GeneralParam.RuntimeAccountParam.ReplPwd + for _, swpair := range r.Params.SwitchParis { + conn := r.mastesConn[swpair.Master.IpPort()] + pos := r.newMasterPosInfos[swpair.Slave.IpPort()] + changeMastersql := fmt.Sprintf( + `CHANGE MASTER TO MASTER_HOST='%s', + MASTER_USER ='%s', + MASTER_PASSWORD='%s', + MASTER_PORT=%d, + MASTER_LOG_FILE='%s', + MASTER_LOG_POS=%d`, + swpair.Slave.Host, + repl_user, + repl_pwd, + swpair.Slave.Port, + pos.File, + pos.Position, + ) + logger.Info("change master to %s", swpair.Slave.IpPort()) + if _, err = conn.Exec(changeMastersql); err != nil { + return err + } + logger.Info("start slave") + if _, err = conn.Exec("start slave;"); err != nil { + return err + } + err = cmutil.Retry(cmutil.RetryConfig{ + Times: 30, + DelayTime: 1 * time.Second, + }, func() error { + ss, serr := conn.ShowSlaveStatus() + if serr != nil { + return serr + } + if ss.ReplSyncIsOk() { + return nil + } + return fmt.Errorf("wating..., IOThread:%s,SQLThread:%s", ss.SlaveIORunning, ss.SlaveSQLRunning) + }) + if err != nil { + return err + } + } + return err +} + +func (c *CutOverCtx) getSysUsers(servers []native.Server, sysUsers []string) { + for _, server := range servers { + sysUsers = append(sysUsers, server.Username) + } + // get sys user + c.sysUsers = cmutil.RemoveDuplicate(sysUsers) + logger.Info("system user: %v", c.sysUsers) +} + +func (c *CutOverCtx) getSlaveSptServers() (slaveSptServers []native.Server) { + for svrName, server := range c.svrNameServersMap { + if native.SvrNameIsSlaveShard(svrName) { + slaveSptServers = append(slaveSptServers, server) + } + } + return +} + +func (c *CutOverCtx) getSlaveSpiderServers() (slaveSpiderServers []native.Server) { + for svrName, server := range c.svrNameServersMap { + if native.SvrNameIsSlaveSpiderShard(svrName) { + slaveSpiderServers = append(slaveSpiderServers, server) + } + } + return +} + +// CheckSpiderAppProcesslist TODO +func (ctx *CutOverCtx) CheckSpiderAppProcesslist() (err error) { + for addr, spider_conn := range ctx.spidersConn { + pls, err := spider_conn.ShowApplicationProcesslist(ctx.sysUsers) + if err != nil { + return err + } + if len(pls) > 0 { + return fmt.Errorf("spider: %s have application processlist %v", addr, pls) + } + } + return +} + +// LockaAllSpidersWrite TODO +func (ctx *CutOverCtx) LockaAllSpidersWrite() (err error) { + for addr, spider_conn := range ctx.spidersConn { + _, err = spider_conn.Exec("flush table with read lock;") + if err != nil { + return fmt.Errorf("lock tables at %s,err:%w", addr, err) + } + } + return +} + +// Unlock TODO +func (ctx *CutOverCtx) Unlock() (err error) { + for addr, spider_conn := range ctx.spidersConn { + err = cmutil.Retry(cmutil.RetryConfig{ + Times: 3, + DelayTime: 1 * time.Second, + }, func() error { + _, ierr := spider_conn.Exec("unlock tables") + if ierr != nil { + return ierr + } + return nil + }) + if err != nil { + return fmt.Errorf("addr:%s,err:%w", addr, err) + } + } + return +} + +func (c *CutOverCtx) flushrouting() (err error) { + if err = cmutil.Retry(cmutil.RetryConfig{Times: 3, DelayTime: 1 * time.Second}, func() error { + _, ferr := c.tdbCtlConn.Exec("tdbctl flush routing force") + return ferr + }); err != nil { + return err + } + return +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/init_cluster_routing_relationship.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/init_cluster_routing_relationship.go index 51ebfab063..d1063ad83e 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/init_cluster_routing_relationship.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/init_cluster_routing_relationship.go @@ -30,8 +30,8 @@ type InitClusterRoutingParam struct { // Instance TODO type Instance struct { - Host string `json:"host"` - Port int `json:"port"` + Host string `json:"host" validate:"required,ip" ` + Port int `json:"port" validate:"required,lt=65536,gte=3306"` ShardID int `json:"shard_id"` } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go b/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go index 4d78efbefb..21e7437dfd 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go @@ -255,7 +255,7 @@ func (h *DbWorker) ShowSlaveStatus() (resp ShowSlaveStatusResp, err error) { return } -// TotalDelayBinlogSize 获取Slave 延迟的总binlog size +// TotalDelayBinlogSize 获取Slave 延迟的总binlog size,total 单位byte func (h *DbWorker) TotalDelayBinlogSize() (total int, err error) { maxbinlogsize_str, err := h.GetSingleGlobalVar("max_binlog_size") if err != nil { @@ -661,11 +661,11 @@ func (h *DbWorker) ShowPrivForUser(created bool, userhost string) (grants []stri // CheckSlaveReplStatus TODO // 检查从库的同步状态是否Ok -func (h *DbWorker) CheckSlaveReplStatus() (err error) { +func (h *DbWorker) CheckSlaveReplStatus(fn func() (resp ShowSlaveStatusResp, err error)) (err error) { return util.Retry( util.RetryConfig{Times: 10, DelayTime: 1}, func() error { - ss, err := h.ShowSlaveStatus() + ss, err := fn() if err != nil { return err } @@ -675,7 +675,7 @@ func (h *DbWorker) CheckSlaveReplStatus() (err error) { if !ss.SecondsBehindMaster.Valid { return fmt.Errorf("SecondsBehindMaster Val Is Null") } - if ss.SecondsBehindMaster.Int64 > 10 { + if ss.SecondsBehindMaster.Int64 > 5 { return fmt.Errorf("SecondsBehindMaster Great Than 10 Sec") } return nil @@ -695,6 +695,10 @@ func (h *DbWorker) MySQLVarsCompare(referInsConn *DbWorker, checkVars []string) if err != nil { return err } + return compareDbVariables(referVars, compareVars, checkVars) +} + +func compareDbVariables(referVars, compareVars map[string]string, checkVars []string) (err error) { var errMsg []string for _, varName := range checkVars { referV, r_ok := referVars[varName] @@ -710,7 +714,7 @@ func (h *DbWorker) MySQLVarsCompare(referInsConn *DbWorker, checkVars []string) if len(errMsg) > 0 { return fmt.Errorf(strings.Join(errMsg, "\n")) } - return + return nil } // ResetSlave TODO diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl.go b/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl.go new file mode 100644 index 0000000000..899542044f --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl.go @@ -0,0 +1,179 @@ +package native + +import ( + "fmt" + "regexp" +) + +// TdbctlDbWork TODO +type TdbctlDbWork struct { + DbWorker +} + +// Server TODO +type Server struct { + ServerName string `db:"Server_name"` + Host string `db:"Host"` + Db string `db:"Db"` + Username string `db:"Username"` + Password string `db:"Password"` + Port int `db:"Port"` + Wrapper string `db:"Wrapper"` +} + +// GetConn TODO +func (s *Server) GetConn() (conn *DbWorker, err error) { + return InsObject{ + Host: s.Host, + Port: s.Port, + User: s.Username, + Pwd: s.Password, + }.Conn() +} + +// GetEndPoint TODO +func (s *Server) GetEndPoint() string { + return fmt.Sprintf("%s:%d", s.Host, s.Port) +} + +// GetAlterNodeSql TODO +// +// "tdbctl create node wrapper 'mysql_slave' options(user '%s', password '%s', host '%s', port %d, number %d);", +func (s *Server) GetAlterNodeSql(serverName string) (sqlStr string) { + return fmt.Sprintf("TDBCTL ALTER NODE %s options(user '%s', password '%s', host '%s', port %d);", + serverName, + s.Username, + s.Password, s.Host, s.Port) +} + +// SHARDPREFIX TODO +const ( + SHARDPREFIX = "SPT" + SLAVE_SHARDPREFIX = "SPT_SLAVE" + SPIDER_PREFIX = "SPIDER" + SPIDER_SLAVE_PREFIX = "SPIDER_SLAVE" +) + +// SvrNameIsMasterShard TODO +func SvrNameIsMasterShard(svrName string) bool { + m := regexp.MustCompile(fmt.Sprintf(`%s\d+`, SHARDPREFIX)) + return m.MatchString(svrName) +} + +// SvrNameIsSlaveShard TODO +func SvrNameIsSlaveShard(svrName string) bool { + m := regexp.MustCompile(fmt.Sprintf(`%s\d+`, SLAVE_SHARDPREFIX)) + return m.MatchString(svrName) +} + +// SvrNameIsSlaveSpiderShard TODO +func SvrNameIsSlaveSpiderShard(svrName string) bool { + m := regexp.MustCompile(fmt.Sprintf(`%s\d+`, SPIDER_SLAVE_PREFIX)) + return m.MatchString(svrName) +} + +// GetMasterShardNameByShardNum TODO +func GetMasterShardNameByShardNum(num string) string { + return SPIDER_PREFIX + num +} + +// GetSlaveShardNameByShardNum TODO +func GetSlaveShardNameByShardNum(num string) string { + return SPIDER_SLAVE_PREFIX + num +} + +// GetSlaveShardNameByMasterShardName TODO +func GetSlaveShardNameByMasterShardName(masterShardName string) string { + num := GetShardNumberFromMasterServerName(masterShardName) + return GetSlaveShardNameByShardNum(num) +} + +// GetShardNumberFromMasterServerName TODO +func GetShardNumberFromMasterServerName(serverName string) string { + m := regexp.MustCompile(SHARDPREFIX) + return m.ReplaceAllString(serverName, "") +} + +// GetShardNumberFromSlaveServerName TODO +func GetShardNumberFromSlaveServerName(serverName string) string { + m := regexp.MustCompile(SLAVE_SHARDPREFIX) + return m.ReplaceAllString(serverName, "") +} + +// AlterNode TODO +func (t *TdbctlDbWork) AlterNode(server_name string, user, password, host string, port int) (int64, error) { + return t.Exec("tdbctl alter node ? options(user ?,password ?,host ?,port ?)", server_name, user, password, host, + port) +} + +// SelectServers TODO +func (t *TdbctlDbWork) SelectServers() (servers []Server, err error) { + err = t.Queryx(&servers, "select * from mysql.servers") + return +} + +// get_exec_special_node_cmd TODO +func (t *TdbctlDbWork) get_exec_special_node_cmd(serverName string) string { + return fmt.Sprintf("TDBCTL CONNECT NODE %s EXECUTE", serverName) +} + +// GetSingleGlobalVar TODO +func (t *TdbctlDbWork) GetSingleGlobalVar(serverName, varName string) (val string, err error) { + var item MySQLGlobalVariableItem + if err = t.Queryxs(&item, fmt.Sprintf("%s 'show global variables like \"%s\"'", t.get_exec_special_node_cmd( + serverName), varName)); err != nil { + return "", err + } + return item.Value, nil +} + +// QueryGlobalVariables TODO +func (t *TdbctlDbWork) QueryGlobalVariables(serverName string) (map[string]string, error) { + result := make(map[string]string) + rows, err := t.Db.Query(fmt.Sprintf(" %s 'SHOW GLOBAL VARIABLES'", t.get_exec_special_node_cmd( + serverName))) + if err != nil { + return result, err + } + defer rows.Close() + for rows.Next() { + var key, val string + err := rows.Scan(&key, &val) + if err != nil { + continue + } + result[key] = val + } + return result, nil +} + +// MySQLVarsCompare TODO +func (h *TdbctlDbWork) MySQLVarsCompare(serverName string, referInsConn *DbWorker, checkVars []string) (err error) { + referVars, err := referInsConn.QueryGlobalVariables() + if err != nil { + return err + } + compareVars, err := h.QueryGlobalVariables(serverName) + if err != nil { + return err + } + return compareDbVariables(referVars, compareVars, checkVars) +} + +// ShowSlaveStatus TODO +func (t *TdbctlDbWork) ShowSlaveStatus(serverName string) (data ShowSlaveStatusResp, err error) { + err = t.Queryxs(&data, fmt.Sprintf("%s 'show slave status'", t.get_exec_special_node_cmd(serverName))) + return +} + +// ShowMasterStatus TODO +func (t *TdbctlDbWork) ShowMasterStatus(serverName string) (data MasterStatusResp, err error) { + err = t.Queryxs(&data, fmt.Sprintf("%s 'show master status'", t.get_exec_special_node_cmd(serverName))) + return +} + +// LockTables TODO +func (t *TdbctlDbWork) LockTables(serverName string) (data MasterStatusResp, err error) { + _, err = t.Exec(fmt.Sprintf("%s 'lock table with read lock'", t.get_exec_special_node_cmd(serverName))) + return +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl_test.go b/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl_test.go new file mode 100644 index 0000000000..b6ce789e82 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/native/tdbctl_test.go @@ -0,0 +1,53 @@ +package native_test + +import ( + "log" + "os" + "strconv" + "testing" + + "dbm-services/mysql/db-tools/dbactuator/pkg/native" +) + +var tdbctldbWork *native.TdbctlDbWork + +func init() { + port, _ := strconv.Atoi(os.Getenv("PORT")) + conn, err := native.InsObject{ + Host: os.Getenv("HOST"), + Port: port, + User: os.Getenv("USER"), + Pwd: os.Getenv("PASSWORD"), + }.Conn() + if err != nil { + log.Fatal(err) + } + tdbctldbWork = &native.TdbctlDbWork{DbWorker: *conn} +} + +func TestTdbctlShowAppProcesslist(t *testing.T) { + pcls, err := tdbctldbWork.ShowApplicationProcesslist([]string{"root"}) + if err != nil { + t.Fatal(err) + return + } + t.Log(pcls) +} + +func TestTdbctlGetVariables(t *testing.T) { + val, err := tdbctldbWork.GetSingleGlobalVar("SPT0", "character_set_server") + if err != nil { + t.Fatal(err) + return + } + t.Log(val) +} + +func TestTdbctlAllVariables(t *testing.T) { + val, err := tdbctldbWork.QueryGlobalVariables("SPT0") + if err != nil { + t.Fatal(err) + return + } + t.Log(val) +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/slice.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/slice.go index 32e9926704..5812ef6cac 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/slice.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/slice.go @@ -10,9 +10,9 @@ import ( "github.com/pkg/errors" ) -// IntsHas check the []int contains the given value -func IntsHas(ints []int, val int) bool { - for _, ele := range ints { +// 判断val 是否在elems 中 +func ContainElem[T int | int64 | string](elems []T, val T) bool { + for _, ele := range elems { if ele == val { return true } @@ -20,24 +20,19 @@ func IntsHas(ints []int, val int) bool { return false } +// IntsHas check the []int contains the given value +func IntsHas(ints []int, val int) bool { + return ContainElem(ints, val) +} + // Int64sHas check the []int64 contains the given value func Int64sHas(ints []int64, val int64) bool { - for _, ele := range ints { - if ele == val { - return true - } - } - return false + return ContainElem(ints, val) } // StringsHas check the []string contains the given element func StringsHas(ss []string, val string) bool { - for _, ele := range ss { - if ele == val { - return true - } - } - return false + return ContainElem(ss, val) } // StringsHasICase check the []string contains the given element. insensitive case @@ -51,36 +46,28 @@ func StringsHasICase(ss []string, val string) bool { return false } -// UniqueStrings Returns unique items in a slice -func UniqueStrings(slice []string) []string { - // create a map with all the values as key - uniqMap := make(map[string]struct{}) +func UniqueSlice[T string | int](slice []T) []T { + uniqMap := make(map[T]struct{}) for _, v := range slice { uniqMap[v] = struct{}{} } // turn the map keys into a slice - uniqSlice := make([]string, 0, len(uniqMap)) + uniqSlice := make([]T, 0, len(uniqMap)) for v := range uniqMap { uniqSlice = append(uniqSlice, v) } return uniqSlice } +// UniqueStrings Returns unique items in a slice +func UniqueStrings(slice []string) []string { + return UniqueSlice(slice) +} + // UniqueInts Returns unique items in a slice func UniqueInts(slice []int) []int { - // create a map with all the values as key - uniqMap := make(map[int]struct{}) - for _, v := range slice { - uniqMap[v] = struct{}{} - } - - // turn the map keys into a slice - uniqSlice := make([]int, 0, len(uniqMap)) - for v := range uniqMap { - uniqSlice = append(uniqSlice, v) - } - return uniqSlice + return UniqueSlice(slice) } // IsConsecutiveStrings 是否是连续数字 @@ -202,7 +189,7 @@ func StringsInsertIndex(ss []string, index int, new string) []string { // @return dst func FilterOutStringSlice(src []string, filters []string) (dst []string) { for _, v := range src { - if !StringsHas(filters, v) { + if !ContainElem(filters, v) { dst = append(dst, v) } } From 3268ba419ec33834d9333aa76f04a2fda5b5e0e7 Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Fri, 30 Jun 2023 14:29:40 +0800 Subject: [PATCH 068/476] =?UTF-8?q?chore(mysql):=20=E6=8A=BD=E5=87=BA?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E6=96=B9=E6=B3=95=E5=88=B0=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E5=8C=85=20close=20#352?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../go-pubpkg}/bkrepo/bkrepo.go | 50 +++-- .../go-pubpkg}/bkrepo/bkrepo_test.go | 2 +- .../mysql/db-simulation/app/syntax/syntax.go | 2 +- .../mysql/db-simulation/pkg/bkrepo/bkrepo.go | 174 ------------------ .../components/mysql/semantic_dump_schema.go | 2 +- .../dbactuator/pkg/util/bkrepo/bkrepo_test.go | 21 --- .../util/db_table_filter/mydumper_regex.go | 4 - .../db-tools/dbactuator/pkg/util/dbcnf.go | 2 +- .../db-tools/dbactuator/pkg/util/filelock.go | 1 - .../pkg/util/mysqlutil/change_master.go | 7 +- .../pkg/util/mysqlutil/mysqlclient_exec.go | 2 +- .../db-tools/dbactuator/pkg/util/util.go | 12 -- 12 files changed, 45 insertions(+), 234 deletions(-) rename dbm-services/{mysql/db-tools/dbactuator/pkg/util => common/go-pubpkg}/bkrepo/bkrepo.go (84%) rename dbm-services/{mysql/db-simulation/pkg => common/go-pubpkg}/bkrepo/bkrepo_test.go (94%) delete mode 100644 dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo_test.go diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo.go b/dbm-services/common/go-pubpkg/bkrepo/bkrepo.go similarity index 84% rename from dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo.go rename to dbm-services/common/go-pubpkg/bkrepo/bkrepo.go index 2778ce6058..2ba57cea0b 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo.go +++ b/dbm-services/common/go-pubpkg/bkrepo/bkrepo.go @@ -16,8 +16,8 @@ import ( "strconv" "strings" + util "dbm-services/common/go-pubpkg/cmutil" "dbm-services/common/go-pubpkg/logger" - "dbm-services/mysql/db-tools/dbactuator/pkg/util" ) /* @@ -56,8 +56,13 @@ func (b *BkRepoClient) getBaseUrl() string { if err != nil { log.Fatal(err) } - u.Path = path.Join(u.Path, "generic", b.BkRepoProject, b.BkRepoPubBucket) - return u.String() + r, err := url.Parse(path.Join(u.Path, "generic", b.BkRepoProject, b.BkRepoPubBucket)) + if err != nil { + log.Fatal(err) + } + uri := u.ResolveReference(r).String() + logger.Info("uri:%s", uri) + return uri } // Download 从制品库下载文件 @@ -65,13 +70,13 @@ func (b *BkRepoClient) getBaseUrl() string { // @receiver b func (b *BkRepoClient) Download(sqlpath, filename, downloaddir string) (err error) { uri := b.getBaseUrl() + path.Join("/", sqlpath, filename) + "?download=true" - logger.Info("The download uri %s", uri) + logger.Info("The download url is %s", uri) req, err := http.NewRequest(http.MethodGet, uri, nil) if err != nil { return err } if strings.Contains(filename, "..") { - return fmt.Errorf("%s 存在路径穿越风险", filename) + return fmt.Errorf("%s there is a risk of path crossing", filename) } fileAbPath, err := filepath.Abs(path.Join(downloaddir, filename)) if err != nil { @@ -87,6 +92,13 @@ func (b *BkRepoClient) Download(sqlpath, filename, downloaddir string) (err erro return err } defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + bs, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + return fmt.Errorf("respone code is %d,respone body is :%s", resp.StatusCode, string(bs)) + } size, err := io.Copy(f, resp.Body) if err != nil { return err @@ -96,9 +108,12 @@ func (b *BkRepoClient) Download(sqlpath, filename, downloaddir string) (err erro if err != nil { return err } - + logger.Info("node detail %v", fileNodeInfo) if size != int64(fileNodeInfo.Size) { - return fmt.Errorf("当前文件&源文件大小不一致,当前文件是:%d,制品库文件是:%d", size, fileNodeInfo.Size) + bs, _ := os.ReadFile(fileAbPath) + return fmt.Errorf("body:%s,current file:%s source file size is inconsistent,current file is:%d,bkrepo file is:%d", + string(bs), filename, size, + fileNodeInfo.Size) } currentFileMd5, err := util.GetFileMd5(fileAbPath) @@ -106,7 +121,9 @@ func (b *BkRepoClient) Download(sqlpath, filename, downloaddir string) (err erro return err } if currentFileMd5 != fileNodeInfo.Md5 { - return fmt.Errorf("当前文件&源文件md5b不一致,当前文件是:%s,制品库文件是:%s", currentFileMd5, fileNodeInfo.Md5) + return fmt.Errorf("current file:%s source file md5 is inconsistent,current file is:%s,bkrepo file is:%s", filename, + currentFileMd5, + fileNodeInfo.Md5) } return nil } @@ -126,10 +143,13 @@ type FileNodeInfo struct { // @receiver b func (b *BkRepoClient) QueryFileNodeInfo(filepath, filename string) (realData FileNodeInfo, err error) { var baseResp BkRepoRespone - uri := b.BkRepoEndpoint + path.Join( - "repository/api/node/detail/", b.BkRepoProject, b.BkRepoPubBucket, filepath, - filename, - ) + uri, err := url.JoinPath(b.BkRepoEndpoint, "repository/api/node/detail/", b.BkRepoProject, b.BkRepoPubBucket, filepath, + filename) + if err != nil { + logger.Error("url join path failed %s", err.Error()) + return + } + logger.Info("query node detail url %s", uri) req, err := http.NewRequest(http.MethodGet, uri, nil) if err != nil { return FileNodeInfo{}, err @@ -256,10 +276,8 @@ func UploadDirectToBkRepo(filepath string, targetURL string, username string, pa // UploadFile 上传文件到蓝盾制品库 // filepath: 本地需要上传文件的路径 // targetURL: 仓库文件完整路径 -func UploadFile( - filepath string, targetURL string, username string, password string, BkCloudId int, - DBCloudToken string, -) (*BkRepoRespone, error) { +func UploadFile(filepath, targetURL, username, password string, BkCloudId int, DBCloudToken string) (*BkRepoRespone, + error) { logger.Info("start upload files from %s to %s", filepath, targetURL) if BkCloudId == 0 { return UploadDirectToBkRepo(filepath, targetURL, username, password) diff --git a/dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo_test.go b/dbm-services/common/go-pubpkg/bkrepo/bkrepo_test.go similarity index 94% rename from dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo_test.go rename to dbm-services/common/go-pubpkg/bkrepo/bkrepo_test.go index 7e29fa36fd..11dbc6fd88 100644 --- a/dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo_test.go +++ b/dbm-services/common/go-pubpkg/bkrepo/bkrepo_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "dbm-services/mysql/db-simulation/pkg/bkrepo" + "dbm-services/common/go-pubpkg/bkrepo" ) func TestDownload(t *testing.T) { diff --git a/dbm-services/mysql/db-simulation/app/syntax/syntax.go b/dbm-services/mysql/db-simulation/app/syntax/syntax.go index 2f8f9a33fd..453c525ca5 100644 --- a/dbm-services/mysql/db-simulation/app/syntax/syntax.go +++ b/dbm-services/mysql/db-simulation/app/syntax/syntax.go @@ -18,10 +18,10 @@ import ( "sync" "time" + "dbm-services/common/go-pubpkg/bkrepo" "dbm-services/common/go-pubpkg/logger" "dbm-services/mysql/db-simulation/app" "dbm-services/mysql/db-simulation/app/config" - "dbm-services/mysql/db-simulation/pkg/bkrepo" ) // CheckSyntax TODO diff --git a/dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo.go b/dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo.go deleted file mode 100644 index b79b9d579d..0000000000 --- a/dbm-services/mysql/db-simulation/pkg/bkrepo/bkrepo.go +++ /dev/null @@ -1,174 +0,0 @@ -// Package bkrepo TODO -package bkrepo - -import ( - "encoding/json" - "fmt" - "io" - "log" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strings" - - util "dbm-services/common/go-pubpkg/cmutil" - "dbm-services/common/go-pubpkg/logger" -) - -/* - API: GET /generic/{project}/{repo}/{path}?download=true - API 名称: download - 功能说明: - - 中文:下载通用制品文件 - English:download generic file - 请求体 此接口请求体为空 -*/ - -// BkRepoClient TODO -type BkRepoClient struct { - Client *http.Client - BkRepoProject string - BkRepoPubBucket string - BkRepoEndpoint string - BkRepoUser string - BkRepoPwd string -} - -// BkRepoRespone TODO -type BkRepoRespone struct { - Code int `json:"code"` - Message string `json:"message"` - Data json.RawMessage `json:"data"` - TraceId string `json:"traceId"` -} - -// getBaseUrl TODO -// -// @receiver b -func (b *BkRepoClient) getBaseUrl() string { - u, err := url.Parse(b.BkRepoEndpoint) - if err != nil { - log.Fatal(err) - } - r, err := url.Parse(path.Join(u.Path, "generic", b.BkRepoProject, b.BkRepoPubBucket)) - if err != nil { - log.Fatal(err) - } - uri := u.ResolveReference(r).String() - logger.Info("uri:%s", uri) - return uri -} - -// Download 从制品库下载文件 -// -// @receiver b -func (b *BkRepoClient) Download(sqlpath, filename, downloaddir string) (err error) { - uri := b.getBaseUrl() + path.Join("/", sqlpath, filename) + "?download=true" - logger.Info("The download url is %s", uri) - req, err := http.NewRequest(http.MethodGet, uri, nil) - if err != nil { - return err - } - if strings.Contains(filename, "..") { - return fmt.Errorf("%s there is a risk of path crossing", filename) - } - fileAbPath, err := filepath.Abs(path.Join(downloaddir, filename)) - if err != nil { - return err - } - f, err := os.Create(fileAbPath) - if err != nil { - return err - } - req.SetBasicAuth(b.BkRepoUser, b.BkRepoPwd) - resp, err := b.Client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - logger.Info("respone code %d", resp.StatusCode) - if resp.StatusCode != http.StatusOK { - bs, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return fmt.Errorf("respone code is %d,respone body is :%s", resp.StatusCode, string(bs)) - } - size, err := io.Copy(f, resp.Body) - if err != nil { - return err - } - logger.GetLogger().Info(fmt.Sprintf("Downloaded a file %s with size %d", filename, size)) - fileNodeInfo, err := b.QueryFileNodeInfo(sqlpath, filename) - if err != nil { - return err - } - logger.Info("node detail %v", fileNodeInfo) - if size != int64(fileNodeInfo.Size) { - bs, _ := os.ReadFile(fileAbPath) - return fmt.Errorf("body:%s,current file:%s source file size is inconsistent,current file is:%d,bkrepo file is:%d", - string(bs), filename, size, - fileNodeInfo.Size) - } - - currentFileMd5, err := util.GetFileMd5(fileAbPath) - if err != nil { - return err - } - if currentFileMd5 != fileNodeInfo.Md5 { - return fmt.Errorf("current file:%s source file md5 is inconsistent,current file is:%s,bkrepo file is:%s", filename, - currentFileMd5, - fileNodeInfo.Md5) - } - return nil -} - -// FileNodeInfo TODO -type FileNodeInfo struct { - Name string `json:"name"` - Sha256 string `json:"sha256"` - Md5 string `json:"md5"` - Size int `json:"size"` - Metadata map[string]string `json:"metadata"` -} - -// QueryFileNodeInfo TODO -// QueryMetaData 查询文件元数据信息 -// -// @receiver b -func (b *BkRepoClient) QueryFileNodeInfo(filepath, filename string) (realData FileNodeInfo, err error) { - var baseResp BkRepoRespone - u, err := url.Parse(b.BkRepoEndpoint) - if err != nil { - return - } - r, err := url.Parse(path.Join("repository/api/node/detail/", b.BkRepoProject, b.BkRepoPubBucket, filepath, filename)) - if err != nil { - logger.Error(err.Error()) - return - } - uri := u.ResolveReference(r).String() - logger.Info("query node detail url %s", uri) - req, err := http.NewRequest(http.MethodGet, uri, nil) - if err != nil { - return FileNodeInfo{}, err - } - resp, err := b.Client.Do(req) - if err != nil { - return FileNodeInfo{}, err - } - defer resp.Body.Close() - if err = json.NewDecoder(resp.Body).Decode(&baseResp); err != nil { - return FileNodeInfo{}, err - } - if baseResp.Code != 0 { - return FileNodeInfo{}, fmt.Errorf("bkrepo Return Code: %d,Messgae:%s", baseResp.Code, baseResp.Message) - } - if err = json.Unmarshal([]byte(baseResp.Data), &realData); err != nil { - return FileNodeInfo{}, err - } - return -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go index 48bf300377..41cfc19e75 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go @@ -9,13 +9,13 @@ import ( "regexp" "strings" + "dbm-services/common/go-pubpkg/bkrepo" "dbm-services/common/go-pubpkg/logger" "dbm-services/mysql/db-tools/dbactuator/pkg/components" "dbm-services/mysql/db-tools/dbactuator/pkg/components/computil" "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" "dbm-services/mysql/db-tools/dbactuator/pkg/native" "dbm-services/mysql/db-tools/dbactuator/pkg/util" - "dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo" "dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil" "dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil" ) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo_test.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo_test.go deleted file mode 100644 index 539b30df29..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo/bkrepo_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package bkrepo_test - -import ( - "net/url" - "path" - "testing" - - "dbm-services/mysql/db-tools/dbactuator/pkg/util/bkrepo" -) - -func TestUploadFile(t *testing.T) { - t.Log("start...") - r, err := url.Parse(path.Join("/generic", "/")) - t.Log(r.String()) - resp, err := bkrepo.UploadFile("/tmp/1.sql", "", "", "", 0, "") - if err != nil { - t.Log(err.Error()) - return - } - t.Log(resp) -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/db_table_filter/mydumper_regex.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/db_table_filter/mydumper_regex.go index bb7c63ef3e..873394c51d 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/db_table_filter/mydumper_regex.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/db_table_filter/mydumper_regex.go @@ -61,7 +61,3 @@ func buildRegexString(patterns []string) string { } return ss } - -func isAllPattern(ss string) bool { - return ss == `.*\.` -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/dbcnf.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/dbcnf.go index 56a7a4e48c..14f45a915b 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/dbcnf.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/dbcnf.go @@ -221,7 +221,7 @@ func (m *CnfFile) GetBinLogDir() (binlogDir, namePrefix string, err error) { if val, err := m.GetMySQLCnfByKey(MysqldSec, k); err == nil { if filepath.IsAbs(val) { if binlogDir, namePrefix, err = m.ParseLogBinBasename(val); err == nil { - return binlogDir, namePrefix, err + return binlogDir, namePrefix, nil } } } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/filelock.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/filelock.go index 3a44ed004a..3fdf750c05 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/filelock.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/filelock.go @@ -158,7 +158,6 @@ func (fl *FLock) FileIncrSafe(incr int, retryInterval int) (succ int, err error) return fl.FileIncrSafe(incr, retryInterval) } } - return 1, nil } // FileUnlockIncr TODO diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/change_master.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/change_master.go index eb27e9f8f4..f682a1545b 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/change_master.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/change_master.go @@ -45,7 +45,12 @@ func (c *ChangeMaster) GetSQL() string { ) } else { sql = fmt.Sprintf( - `CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER ='%s', MASTER_PASSWORD='%s',MASTER_LOG_FILE='%s', MASTER_LOG_POS=%d`, + `CHANGE MASTER TO MASTER_HOST='%s', + MASTER_PORT=%d, + MASTER_USER ='%s', + MASTER_PASSWORD='%s', + MASTER_LOG_FILE='%s', + MASTER_LOG_POS=%d`, c.MasterHost, c.MasterPort, c.MasterUser, diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go index 2cb57c5627..0786025961 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go @@ -102,11 +102,11 @@ func (e ExecuteSqlAtLocal) ExcuteCommand(command string) (err error) { defer func() { // 写入error 文件 ef, errO := os.OpenFile(e.ErrFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) - defer ef.Close() if errO != nil { logger.Warn("打开日志时失败! %s", errO.Error()) return } + defer ef.Close() _, errW := ef.Write(stderr.Bytes()) if errW != nil { logger.Warn("写错误日志时失败! %s", err.Error()) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/util.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/util.go index f78e1abfbe..bcce9daf9e 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/util.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/util.go @@ -8,9 +8,7 @@ import ( "io" "math/rand" "net" - "net/url" "os" - "path" "reflect" "regexp" "runtime" @@ -313,16 +311,6 @@ func GetFileModifyTime(filename string) (bool, int64) { return false, 0 } -// UrlJoinPath utl.JoinPath go1.919 -func UrlJoinPath(p, subPath string) (string, error) { - u, err := url.Parse(p) - if err != nil { - return "", err - } - u.Path = path.Join(u.Path, subPath) - return u.String(), nil -} - // FileIsEmpty TODO func FileIsEmpty(path string) error { fileInfo, err := os.Stat(path) From cb2ac7233c2fcb2fc6944fc4ded7921820ef162d Mon Sep 17 00:00:00 2001 From: yksitu <1297650644@qq.com> Date: Fri, 30 Jun 2023 11:00:28 +0800 Subject: [PATCH 069/476] =?UTF-8?q?feat(spider):=20=E5=A2=9E=E5=8A=A0spide?= =?UTF-8?q?r=E8=8A=82=E7=82=B9=E7=BC=A9=E5=AE=B9=E7=9A=84=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=8A=9F=E8=83=BD=20#241?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: line too long --- .../api/cluster/tendbcluster/handler.py | 26 ++ dbm-ui/backend/flow/consts.py | 3 + .../scene/mysql/common/get_mysql_sys_user.py | 34 +++ .../scene/spider/common/common_sub_flow.py | 196 ++++++++++++- .../bamboo/scene/spider/common/exceptions.py | 12 + .../bamboo/scene/spider/spider_add_nodes.py | 9 +- .../scene/spider/spider_reduce_nodes.py | 168 +++++++++++ .../backend/flow/engine/controller/spider.py | 8 + .../collections/mysql/exec_actuator_script.py | 26 +- .../collections/spider/ctl_drop_routing.py | 75 +++++ .../collections/spider/ctl_switch_to_slave.py | 267 ++++++++++++++++++ .../collections/spider/drop_spider_ronting.py | 139 +++++++++ dbm-ui/backend/flow/urls.py | 3 + .../flow/utils/mysql/mysql_act_dataclass.py | 2 +- .../flow/utils/spider/get_spider_incr.py | 8 +- .../flow/utils/spider/spider_act_dataclass.py | 32 +++ .../flow/utils/spider/spider_db_meta.py | 10 + .../backend/flow/views/spider_reduce_nodes.py | 32 +++ 18 files changed, 1012 insertions(+), 38 deletions(-) create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/get_mysql_sys_user.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_reduce_nodes.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/spider/ctl_switch_to_slave.py create mode 100644 dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py create mode 100644 dbm-ui/backend/flow/views/spider_reduce_nodes.py diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py index 857e5d8f27..281e9a202c 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py @@ -12,6 +12,8 @@ from django.db import transaction +from backend import env +from backend.components import CCApi from backend.configuration.constants import DBType from backend.db_meta import api from backend.db_meta.api.cluster.base.handler import ClusterHandler @@ -254,3 +256,27 @@ def add_spider_master( spider_masters: list, ): pass + + @classmethod + @transaction.atomic + def reduce_spider( + cls, + cluster_id: int, + spiders: list, + ): + """ + 对已有的集群删除待卸载的spider节点 + """ + cluster = Cluster.objects.get(id=cluster_id) + for info in spiders: + # 同一台spider机器专属于一个集群 + spider = cluster.proxyinstance_set.get(machine__ip=info["ip"]) + # 先删除额外的spider关联信息,否则直接删除实例,会报ProtectedError 异常 + spider.tendbclusterspiderext.delete() + spider.delete(keep_parents=True) + if not spider.machine.proxyinstance_set.exists(): + # 这个 api 不需要检查返回值, 转移主机到空闲模块,转移模块这里会把服务实例删除 + CCApi.transfer_host_to_recyclemodule( + {"bk_biz_id": env.DBA_APP_BK_BIZ_ID, "bk_host_id": [spider.machine.bk_host_id]} + ) + spider.machine.delete(keep_parents=True) diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index ef53a94d7d..a0c77b3784 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -103,6 +103,9 @@ # ES默认部署的实例数 ES_DEFAULT_INSTANCE_NUM = 1 +# MySQL 系统内置账号列表 +MYSQL_SYS_USER = ["system user", "event_scheduler"] + class StateType(str, StructuredEnum): CREATED = EnumField("CREATED", _("创建态")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/get_mysql_sys_user.py b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/get_mysql_sys_user.py new file mode 100644 index 0000000000..813ad7e66c --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/get_mysql_sys_user.py @@ -0,0 +1,34 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from backend import env +from backend.core.encrypt.constants import RSAConfigType +from backend.core.encrypt.handlers import RSAHandler +from backend.db_proxy.constants import ExtensionType +from backend.db_proxy.models import DBExtension + + +def get_mysql_sys_users(bk_cloud_id) -> list: + """ + 增加方法:收集SaaS内mysql/spider的系统账号列表,作为固定参数传入待执行Actuator指令 + """ + sys_users_map = { + ExtensionType.DRS: env.DRS_USERNAME, + ExtensionType.DBHA: env.DBHA_USERNAME, + } + sys_users = [] + for key, value in sys_users_map.items(): + if value: + sys_users.append(value) + else: + rsa = RSAHandler.get_or_generate_rsa_in_db(RSAConfigType.get_rsa_cloud_name(bk_cloud_id)) + info = DBExtension.get_latest_extension(bk_cloud_id=bk_cloud_id, extension_type=key) + sys_users.append(RSAHandler.decrypt_password(rsa.rsa_private_key.content, info.details["user"])) + + return sys_users diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py index ece68d07b4..7df0e99ec5 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py @@ -13,26 +13,38 @@ from django.utils.translation import ugettext as _ from backend.configuration.constants import DBType +from backend.constants import IP_PORT_DIVIDER from backend.db_meta.enums import ClusterType, InstanceStatus, TenDBClusterSpiderRole -from backend.db_meta.models import Cluster, ProxyInstance +from backend.db_meta.models import Cluster from backend.flow.consts import AUTH_ADDRESS_DIVIDER, DBA_ROOT_USER, TDBCTL_USER from backend.flow.engine.bamboo.scene.common.builder import SubBuilder from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList +from backend.flow.plugins.components.collections.common.delete_cc_service_instance import DelCCServiceInstComponent +from backend.flow.plugins.components.collections.mysql.clear_machine import MySQLClearMachineComponent from backend.flow.plugins.components.collections.mysql.clone_user import CloneUserComponent from backend.flow.plugins.components.collections.mysql.dns_manage import MySQLDnsManageComponent from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent from backend.flow.plugins.components.collections.mysql.trans_flies import TransFileComponent from backend.flow.plugins.components.collections.spider.add_spider_routing import AddSpiderRoutingComponent +from backend.flow.plugins.components.collections.spider.ctl_drop_routing import CtlDropRoutingComponent +from backend.flow.plugins.components.collections.spider.ctl_switch_to_slave import CtlSwitchToSlaveComponent +from backend.flow.plugins.components.collections.spider.spider_db_meta import SpiderDBMetaComponent from backend.flow.utils.mysql.mysql_act_dataclass import ( CreateDnsKwargs, + DBMetaOPKwargs, + DelServiceInstKwargs, DownloadMediaKwargs, ExecActuatorKwargs, InstanceUserCloneKwargs, ) from backend.flow.utils.mysql.mysql_act_playload import MysqlActPayload from backend.flow.utils.spider.get_spider_incr import get_spider_master_incr -from backend.flow.utils.spider.spider_act_dataclass import AddSpiderRoutingKwargs -from backend.flow.utils.spider.spider_bk_config import get_spider_version_and_charset +from backend.flow.utils.spider.spider_act_dataclass import ( + AddSpiderRoutingKwargs, + CtlDropRoutingKwargs, + CtlSwitchToSlaveKwargs, +) +from backend.flow.utils.spider.spider_db_meta import SpiderDBMeta """ 定义一些TenDB cluster流程上可能会用到的子流程,以便于减少代码的重复率 @@ -477,3 +489,181 @@ def add_ctl_node_with_gtid( sub_pipeline.add_parallel_acts(acts_list=acts_list) return sub_pipeline.build_sub_process(sub_name=_("部署spider-ctl集群")) + + +def reduce_spider_slaves_flow( + cluster: Cluster, + reduce_spiders: list, + root_id: str, + parent_global_data: dict, + spider_role: TenDBClusterSpiderRole, +): + """ + 减少spider节点的子流程, 提供给集群缩容接入层或者替换类单据所用 + @param cluster: 待操作的集群 + @param reduce_spiders: 待卸载的spider节点机器信息 + @param root_id: flow流程的root_id + @param parent_global_data: 本次子流程的对应上层流程的全局只读上下文 + @param spider_role: 本次操作的spider角色 + """ + + sub_pipeline = SubBuilder(root_id=root_id, data=parent_global_data) + + # 拼接执行原子任务活动节点需要的通用的私有参数结构体, 减少代码重复率,但引用时注意内部参数值传递的问题 + exec_act_kwargs = ExecActuatorKwargs( + cluster_type=ClusterType.TenDBCluster, + bk_cloud_id=cluster.bk_cloud_id, + ) + + # 获取集群对应的spider端口 + spider_port = cluster.proxyinstance_set.first().port + spider_admin_port = cluster.proxyinstance_set.first().admin_port + + # 先回收集群所有服务实例内容,避免出现误报监控 + del_instance_list = [] + for spider in reduce_spiders: + del_instance_list.append({"ip": spider["ip"], "port": spider_port}) + + sub_pipeline.add_act( + act_name=_("删除注册CC系统的服务实例"), + act_component_code=DelCCServiceInstComponent.code, + kwargs=asdict( + DelServiceInstKwargs( + cluster_id=cluster.id, + del_instance_list=del_instance_list, + ) + ), + ) + + # 阶段1 下发spider安装介质包 + sub_pipeline.add_act( + act_name=_("下发db-actuator介质"), + act_component_code=TransFileComponent.code, + kwargs=asdict( + DownloadMediaKwargs( + bk_cloud_id=cluster.bk_cloud_id, + exec_ip=[ip_info["ip"] for ip_info in reduce_spiders], + file_list=GetFileList(db_type=DBType.MySQL).get_db_actuator_package(), + ) + ), + ) + + # 阶段2 卸载相关db组件 + acts_list = [] + for spider in reduce_spiders: + exec_act_kwargs.exec_ip = spider["ip"] + exec_act_kwargs.cluster = {"spider_port": spider_port} + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_uninstall_spider_payload.__name__ + acts_list.append( + { + "act_name": _("卸载spider实例"), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + } + ) + sub_pipeline.add_parallel_acts(acts_list=acts_list) + + # 阶段3 如果这次卸载的是spider-master,需要卸载对应的中控实例 + if spider_role == TenDBClusterSpiderRole.SPIDER_MASTER.value: + + # 回收对应ctl的路由信息,如果涉及到ctl primary,先切换,再回收 + reduce_ctls = cluster.proxyinstance_set.filter(machine__ip__in=[ip_info["ip"] for ip_info in reduce_spiders]) + sub_pipeline.add_sub_pipeline( + sub_flow=reduce_ctls_routing( + root_id=root_id, parent_global_data=parent_global_data, cluster=cluster, reduce_ctls=list(reduce_ctls) + ) + ) + + # 卸载ctl的进程 + acts_list = [] + for ctl in reduce_spiders: + exec_act_kwargs.exec_ip = ctl["ip"] + exec_act_kwargs.cluster = {"spider_ctl_port": spider_admin_port} + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_uninstall_spider_ctl_payload.__name__ + acts_list.append( + { + "act_name": _("卸载中控实例"), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + } + ) + sub_pipeline.add_parallel_acts(acts_list=acts_list) + + # 阶段4 清空相关集群元信息;相关的cmdb注册信息 + sub_pipeline.add_act( + act_name=_("清理db_meta元信息"), + act_component_code=SpiderDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.reduce_spider_nodes_apply.__name__, + ) + ), + ) + + # 阶段5 清理机器配置,这里不需要做实例级别的配置清理,因为目前平台spider的单机单实例部署,专属一套集群 + exec_act_kwargs.exec_ip = [ip_info["ip"] for ip_info in reduce_spiders] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_clear_machine_crontab.__name__ + sub_pipeline.add_act( + act_name=_("清理机器周边配置"), + act_component_code=MySQLClearMachineComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + + return sub_pipeline.build_sub_process(sub_name=_("下架spider节点")) + + +def reduce_ctls_routing(root_id: str, parent_global_data: dict, cluster: Cluster, reduce_ctls: list): + """ + 根据回收spider-ctl,构建专属的中控实例路由删除的子流程 + """ + reduce_ctl_primary = None + reduce_ctl_secondary_list = [] + + # 计算每个待回收的ctl的角色,分配下架行为 + for ctl in reduce_ctls: + if f"{ctl.machine.ip}{IP_PORT_DIVIDER}{ctl.admin_port}" == cluster.tendbcluster_ctl_primary_address(): + # 本次回收事件涉及到ctl主节点回收,则加入这次回收流程 + reduce_ctl_primary = f"{ctl.machine.ip}{IP_PORT_DIVIDER}{ctl.admin_port}" + else: + reduce_ctl_secondary_list.append(f"{ctl.machine.ip}{IP_PORT_DIVIDER}{ctl.admin_port}") + + sub_pipeline = SubBuilder(root_id=root_id, data=parent_global_data) + + if reduce_ctl_primary: + # 选择新节点作为primary,过滤待回收的节点 + all_ctl = cluster.proxyinstance_set.filter( + tendbclusterspiderext__spider_role=TenDBClusterSpiderRole.SPIDER_MASTER + ) + + # 因为ctl集群是采用GTID+半同步数据同步,所以理论上选择任意一个从节点作为主,数据不会丢失 + new_ctl_primary = all_ctl.exclude(machine__ip__in=[ip_info["ip"] for ip_info in reduce_ctls]).first() + + sub_pipeline.add_act( + act_name=_("切换ctl中控集群"), + act_component_code=CtlSwitchToSlaveComponent.code, + kwargs=asdict( + CtlSwitchToSlaveKwargs( + cluster_id=cluster.id, + reduce_ctl_primary=reduce_ctl_primary, + new_ctl_primary=f"{new_ctl_primary.machine.ip}{IP_PORT_DIVIDER}{new_ctl_primary.admin_port}", + ) + ), + ) + + acts_list = [] + for ctl in reduce_ctl_secondary_list: + acts_list.append( + { + "act_name": _("卸载中控实例路由[{}]".format(ctl)), + "act_component_code": CtlDropRoutingComponent.code, + "kwargs": asdict( + CtlDropRoutingKwargs( + cluster_id=cluster.id, + reduce_ctl=ctl, + ) + ), + } + ) + sub_pipeline.add_parallel_acts(acts_list=acts_list) + + return sub_pipeline.build_sub_process(sub_name=_("删除中控的路由节点")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/exceptions.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/exceptions.py index 75dd17e22a..d824a3dea4 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/exceptions.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/exceptions.py @@ -33,3 +33,15 @@ class AddSpiderNodeFailedException(TenDBClusterFlowBaseException): ERROR_CODE = "003" MESSAGE = _("添加spider节点路由失败") MESSAGE_TPL = _("{message}") + + +class CtlSwitchToSlaveFailedException(TenDBClusterFlowBaseException): + ERROR_CODE = "004" + MESSAGE = _("中控集群切换失败") + MESSAGE_TPL = _("{message}") + + +class DropSpiderNodeFailedException(TenDBClusterFlowBaseException): + ERROR_CODE = "005" + MESSAGE = _("删除spider节点路由失败") + MESSAGE_TPL = _("{message}") diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py index 9aa6f5cd70..e6024bc813 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py @@ -58,9 +58,6 @@ def add_spider_nodes(self): sub_flow_context = copy.deepcopy(self.data) sub_flow_context.pop("infos") - # 拼接子流程的全局参数 - sub_flow_context.update(info) - # 获取对应集群相关对象 cluster = Cluster.objects.get(id=info["cluster_id"]) @@ -69,6 +66,9 @@ def add_spider_nodes(self): bk_biz_id=cluster.bk_biz_id, db_module_id=cluster.db_module_id ) + # 拼接子流程的全局参数 + sub_flow_context.update(info) + # 补充这次单据需要的隐形参数,spider版本以及字符集 sub_flow_context["spider_charset"] = spider_charset sub_flow_context["spider_version"] = spider_version @@ -81,7 +81,6 @@ def add_spider_nodes(self): elif info["add_spider_role"] == TenDBClusterSpiderRole.SPIDER_SLAVE: # 先判断集群是否存在已添加从集群,如果没有则跳过这次扩容,判断依据是集群是存在有且只有一个的从域名 - cluster = Cluster.objects.get(id=info["cluster_id"]) slave_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.SLAVE_ENTRY) if not slave_dns: logger.warning(_("[{}]The cluster has not added a slave cluster, skip".format(cluster.name))) @@ -103,7 +102,7 @@ def add_spider_master_notes(self, sub_flow_context: dict, cluster: Cluster): """ 定义spider master集群部署子流程 目前产品形态 spider专属一套集群,所以流程只支持spider单机单实例安装 - todo 目前spider-master扩容功能中,当前中控版本需要调整,等最新版本做联调工作 + todo 目前spider-master扩容功能开发中,当前中控版本需要调整,等最新版本做联调工作 """ # 启动子流程 diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_reduce_nodes.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_reduce_nodes.py new file mode 100644 index 0000000000..ed43dadcef --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_reduce_nodes.py @@ -0,0 +1,168 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import copy +import logging.config +from dataclasses import asdict +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.db_meta.enums import TenDBClusterSpiderRole +from backend.db_meta.models import Cluster +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.spider.common.common_sub_flow import reduce_spider_slaves_flow +from backend.flow.engine.bamboo.scene.spider.common.exceptions import NormalSpiderFlowException +from backend.flow.plugins.components.collections.common.pause import PauseComponent +from backend.flow.plugins.components.collections.mysql.dns_manage import MySQLDnsManageComponent +from backend.flow.plugins.components.collections.spider.drop_spider_ronting import DropSpiderRoutingComponent +from backend.flow.utils.mysql.mysql_act_dataclass import RecycleDnsRecordKwargs +from backend.flow.utils.spider.spider_act_dataclass import DropSpiderRoutingKwargs + +logger = logging.getLogger("flow") + + +class TenDBClusterReduceNodesFlow(object): + """ + 构建TenDB Cluster 减少 spider 节点;添加不同角色的spider,处理方式不一样 + 目前只支持spider_master/spider_slave 角色的减少 + 节点减少不是无脑操作,应该有数量上限制:spider_master至少需要保留2台;spider_slave至少需要保留1台 + 支持不同云区域的合并操作 + """ + + def __init__(self, root_id: str, data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param data : 单据传递参数 + """ + self.root_id = root_id + self.data = data + self.mix_spider_master_count = 2 + self.mix_spider_slave_count = 1 + + def __calc_reduce_spiders( + self, cluster: Cluster, reduce_spider_role: TenDBClusterSpiderRole, spider_reduced_to_count: int + ): + """ + 根据每个子单据的操作spider角色和缩容剩余数量,来计算出合理的待回收spider节点列表 + @param cluster: 集群对象 + @param reduce_spider_role: 待回收角色 + @param spider_reduced_to_count: 缩容至数量 + """ + # 检测 + spiders_count = cluster.proxyinstance_set.filter(tendbclusterspiderext__spider_role=reduce_spider_role).count() + if reduce_spider_role == TenDBClusterSpiderRole.SPIDER_MASTER.value and ( + spider_reduced_to_count < self.mix_spider_master_count or spider_reduced_to_count >= spiders_count + ): + + raise NormalSpiderFlowException( + message=_( + "集群最后不能少于{}个spider_master实例,或者不能大于集群存量[{}]".format(self.mix_spider_master_count, spiders_count) + ) + ) + + if reduce_spider_role == TenDBClusterSpiderRole.SPIDER_SLAVE.value and ( + spider_reduced_to_count < self.mix_spider_slave_count or spider_reduced_to_count >= spiders_count + ): + + raise NormalSpiderFlowException( + message=_( + "集群最后不能少于{}个spider_slave实例,或者不能大于集群存量[{}]".format(self.mix_spider_slave_count, spiders_count) + ) + ) + + # 计算合理的待下架的spider节点列表 + + ctl_primary = cluster.tendbcluster_ctl_primary_address() + + # 选择上尽量避开ctl_primary的选择, 避免做一次切换逻辑 + reduce_spiders = cluster.proxyinstance_set.filter( + tendbclusterspiderext__spider_role=reduce_spider_role + ).exclude(machine__ip=ctl_primary.split(":"[0]))[: spiders_count - spider_reduced_to_count] + + return [{"ip": s.machine.ip} for s in reduce_spiders] + + def reduce_spider_nodes(self): + """ + 定义TenDB Cluster缩容接入层的后端流程 + todo 目前spider-master缩容功能开发中,当前中控版本需要调整,等最新版本做联调工作 + """ + + pipeline = Builder(root_id=self.root_id, data=self.data) + sub_pipelines = [] + for info in self.data["infos"]: + # 拼接子流程需要全局参数 + sub_flow_context = copy.deepcopy(self.data) + sub_flow_context.pop("infos") + + # 拼接子流程的全局参数 + sub_flow_context.update(info) + + # 卸载spider实例级别默认先为True, 看看是否后续让用户自行选择? + sub_flow_context["force"] = True + + # 获取对应集群相关对象 + cluster = Cluster.objects.get(id=info["cluster_id"]) + + # 计算待下架的spider节点列表,转化成全局参数 + reduce_spiders = self.__calc_reduce_spiders( + cluster=cluster, + reduce_spider_role=info["reduce_spider_role"], + spider_reduced_to_count=int(info["spider_reduced_to_count"]), + ) + sub_flow_context["reduce_spiders"] = reduce_spiders + + # 启动子流程 + sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(sub_flow_context)) + + # 删除spider的路由关系 + sub_pipeline.add_act( + act_name=_("删除spider的路由关系"), + act_component_code=DropSpiderRoutingComponent.code, + kwargs=asdict( + DropSpiderRoutingKwargs( + cluster_id=cluster.id, + is_safe=self.data["is_safe"], + reduce_spiders=reduce_spiders, + ) + ), + ) + + # 回收对应的域名关系 + sub_pipeline.add_act( + act_name=_("回收对应spider集群映射"), + act_component_code=MySQLDnsManageComponent.code, + kwargs=asdict( + RecycleDnsRecordKwargs( + bk_cloud_id=cluster.bk_cloud_id, + dns_op_exec_port=cluster.proxyinstance_set.first().port, + exec_ip=[info["ip"] for info in reduce_spiders], + ), + ), + ) + + # 后续流程需要在这里加一个暂停节点,让用户在合适的时间执行下架 + sub_pipeline.add_act(act_name=_("人工确认"), act_component_code=PauseComponent.code, kwargs={}) + + # 根据场景执行下架spider子流程 + sub_pipeline.add_sub_pipeline( + sub_flow=reduce_spider_slaves_flow( + cluster=cluster, + reduce_spiders=reduce_spiders, + root_id=self.root_id, + parent_global_data=sub_flow_context, + spider_role=info["reduce_spider_role"], + ) + ) + + sub_pipelines.append(sub_pipeline.build_sub_process(sub_name=_("[{}]减少spider节点流程".format(cluster.name)))) + + pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) + pipeline.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/controller/spider.py b/dbm-ui/backend/flow/engine/controller/spider.py index 2bbecfe994..a7649167de 100644 --- a/dbm-ui/backend/flow/engine/controller/spider.py +++ b/dbm-ui/backend/flow/engine/controller/spider.py @@ -21,6 +21,7 @@ from backend.flow.engine.bamboo.scene.spider.spider_cluster_full_backup import TenDBClusterFullBackupFlow from backend.flow.engine.bamboo.scene.spider.spider_cluster_truncate_database import SpiderTruncateDatabaseFlow from backend.flow.engine.bamboo.scene.spider.spider_partition import SpiderPartitionFlow +from backend.flow.engine.bamboo.scene.spider.spider_reduce_nodes import TenDBClusterReduceNodesFlow from backend.flow.engine.bamboo.scene.spider.spider_rename_database_flow import SpiderRenameDatabaseFlow from backend.flow.engine.bamboo.scene.spider.spider_slave_cluster_deploy import TenDBSlaveClusterApplyFlow from backend.flow.engine.controller.base import BaseController @@ -121,3 +122,10 @@ def add_spider_nodes_scene(self): def full_backup(self): flow = TenDBClusterFullBackupFlow(root_id=self.root_id, data=self.ticket_data) flow.full_backup_flow() + + def reduce_spider_nodes_scene(self): + """ + 缩容接入层的场景 + """ + flow = TenDBClusterReduceNodesFlow(root_id=self.root_id, data=self.ticket_data) + flow.reduce_spider_nodes() diff --git a/dbm-ui/backend/flow/plugins/components/collections/mysql/exec_actuator_script.py b/dbm-ui/backend/flow/plugins/components/collections/mysql/exec_actuator_script.py index 28d55bdd35..0bf85ece25 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/mysql/exec_actuator_script.py +++ b/dbm-ui/backend/flow/plugins/components/collections/mysql/exec_actuator_script.py @@ -21,11 +21,8 @@ from backend import env from backend.components import JobApi -from backend.core.encrypt.constants import RSAConfigType -from backend.core.encrypt.handlers import RSAHandler -from backend.db_proxy.constants import ExtensionType -from backend.db_proxy.models import DBExtension from backend.flow.consts import DBA_ROOT_USER +from backend.flow.engine.bamboo.scene.mysql.common.get_mysql_sys_user import get_mysql_sys_users from backend.flow.models import FlowNode from backend.flow.plugins.components.collections.common.base_service import BkJobService from backend.flow.utils.mysql.mysql_act_playload import MysqlActPayload @@ -54,25 +51,6 @@ def __get_exec_ips(self, kwargs, trans_data) -> list: return exec_ips - @staticmethod - def __get_mysql_sys_users(bk_cloud_id) -> list: - """ - 增加方法:收集SaaS内mysql/spider的系统账号列表,作为固定参数传入待执行Actuator指令 - """ - sys_users_map = { - ExtensionType.DRS: env.DRS_USERNAME, - ExtensionType.DBHA: env.DBHA_USERNAME, - } - sys_users = [] - for key, value in sys_users_map.items(): - if value: - sys_users.append(value) - else: - rsa = RSAHandler.get_or_generate_rsa_in_db(RSAConfigType.get_rsa_cloud_name(bk_cloud_id)) - info = DBExtension.get_latest_extension(bk_cloud_id=bk_cloud_id, extension_type=key) - sys_users.append(RSAHandler.decrypt_password(rsa.rsa_private_key.content, info.details["user"])) - return sys_users - def _execute(self, data, parent_data) -> bool: """ 执行fast_execute_script脚本 @@ -126,7 +104,7 @@ def _execute(self, data, parent_data) -> bool: # 拼接mysql系统账号固定参数 if "general" in db_act_template["payload"]: db_act_template["payload"]["general"].update( - {"runtime_extend": {"mysql_sys_users": self.__get_mysql_sys_users(kwargs["bk_cloud_id"])}} + {"runtime_extend": {"mysql_sys_users": get_mysql_sys_users(kwargs["bk_cloud_id"])}} ) # payload参数转换base64格式 diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py new file mode 100644 index 0000000000..e186e3afd0 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py @@ -0,0 +1,75 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.utils.translation import ugettext_lazy as _ +from pipeline.component_framework.component import Component + +from backend.components import DRSApi +from backend.db_meta.models import Cluster +from backend.flow.engine.bamboo.scene.spider.common.exceptions import CtlSwitchToSlaveFailedException +from backend.flow.plugins.components.collections.common.base_service import BaseService + + +class CtlDropRoutingService(BaseService): + def _execute(self, data, parent_data): + kwargs = data.get_one_of_inputs("kwargs") + + reduce_ctl = kwargs["reduce_ctl"] + + # 获取cluster对象 + cluster = Cluster.objects.get(id=kwargs["cluster_id"]) + ctl_primary = cluster.tendbcluster_ctl_primary_address() + + rpc_params = { + "addresses": [ctl_primary], + "cmds": [], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + + # 查询reduce_ctl对应的server_name + reduce_ip = reduce_ctl.split(":")[0] + reduce_port = reduce_ctl.split(":")[1] + + select_sql = [ + "set tc_admin = 1", + f"select Server_name from mysql.servers where host = '{reduce_ip}' and port = {reduce_port}", + ] + rpc_params["cmds"] = select_sql + res = DRSApi.rpc(rpc_params) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("select mysql.servers failed: {}".format(res[0]["error_msg"])) + ) + + if not res[0]["cmd_results"][1]["table_data"]: + self.log_warning(f"Node [{reduce_ctl}] no longer has routing information") + return True + + else: + server_name = res[0]["cmd_results"][1]["table_data"][0]["Server_name"] + + # 删除节点路由信息 + exec_sql = [ + "set tc_admin=1", + f"TDBCTL DROP NODE IF EXISTS {server_name}", + ] + rpc_params["cmds"] = exec_sql + res = DRSApi.rpc(rpc_params) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("exec TDBCTL-DROP-NODE failed: {}".format(res[0]["error_msg"])) + ) + return True + + +class CtlDropRoutingComponent(Component): + name = __name__ + code = "ctl_drop_routing" + bound_service = CtlDropRoutingService diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_switch_to_slave.py b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_switch_to_slave.py new file mode 100644 index 0000000000..61ce54bdb7 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_switch_to_slave.py @@ -0,0 +1,267 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from time import sleep + +from django.utils.translation import ugettext_lazy as _ +from pipeline.component_framework.component import Component + +from backend.components import DBConfigApi, DRSApi, MySQLPrivManagerApi +from backend.components.dbconfig.constants import FormatType, LevelName +from backend.constants import IP_PORT_DIVIDER +from backend.core.encrypt.handlers import RSAHandler +from backend.db_meta.enums import TenDBClusterSpiderRole +from backend.db_meta.models import Cluster +from backend.flow.consts import TDBCTL_USER, ConfigTypeEnum, NameSpaceEnum, PrivRole +from backend.flow.engine.bamboo.scene.spider.common.exceptions import CtlSwitchToSlaveFailedException +from backend.flow.plugins.components.collections.common.base_service import BaseService + + +class CtlSwitchToSlaveService(BaseService): + """ + 定义spider(tenDB cluster)集群的中控集群做主节点提示,适用于spider裁撤场合调用 + 这里暂时不考虑主从互切场景,仅仅做提升主节点场景,因为互切展示没有需求 + 幂等的内容包括: 预检测、断开同步、选择新的主节点、重新同步新主节点 + 私有变量的主要结构体kwargs: + { + “cluster_id”: id, 待关联的集群id + "reduce_ctl_primary": 传入的待删除的中控primary实例,格式“ip:port” + "new_ctl_primary": 传入的待提升primary的中控实例,格式“ip:port” + } + """ + + def _is_running_process(self, rds_params): + """ + 检测待回收的primary是否存在running状态的线程 + """ + check_sql = ( + f"select * from information_schema.TDBCTL_CLUSTER_PROCESSLIST where user = '{TDBCTL_USER}'" + + " and command != 'Sleep' and info not like '%INFORMATION_SCHEMA.PROCESSLIST';" + ) + rds_params["cmds"] = ["set tc_admin=1"] + [check_sql] + res = DRSApi.rpc(rds_params) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("select processlist failed: {}".format(res[0]["error_msg"])) + ) + + if res[0]["cmd_results"][1]["table_data"]: + self.log_warning(f"There are also {res[0]['cmd_results'][1]['rows_affected']} non-sleep state threads") + return False + + return True + + def _prepare_check(self, cluster: Cluster, reduce_ctl_primary: str): + """ + 检测当前是否可以执行切换 + todo 是否需要检验checksum结果? + """ + cmds = ["set tc_admin=1"] + rpc_params = { + "addresses": [reduce_ctl_primary], + "cmds": cmds, + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + # 检测待下架的中控primary是否能连接上 + check_sql = "select 1;" + rpc_params["cmds"] = cmds + [check_sql] + res = DRSApi.rpc(rpc_params) + if "connection refused" in res[0]["error_msg"]: + # 任务待下架的节点已经故障,应该不做下面的处理,作为故障机处理 + self.log_warning(res[0]["error_msg"]) + return False + + # 检测原primary节点是否正在执行中控命令 + if self._is_running_process(rds_params=rpc_params): + # 如果第一次检验到有running的process,则尝试等待10秒,重新检验一次,如果还存在则退出 + sleep(10) + if not self._is_running_process(rds_params=rpc_params): + raise CtlSwitchToSlaveFailedException( + message=_("After two detections, there are still non-sleep state threads in the instance") + ) + return True + + def _exec_disable_primary(self, cluster: Cluster, reduce_ctl_primary): + """ + 连接待下架的primary,执行执行TDBCTL DISABLE PRIMARY + """ + res = DRSApi.rpc( + { + "addresses": [reduce_ctl_primary], + "cmds": ["set tc_admin = 1", "TDBCTL DISABLE PRIMARY"], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + ) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("exec TDBCTL-DISABLE-PRIMARY failed: {}".format(res[0]["error_msg"])) + ) + self.log_info(f"[{reduce_ctl_primary}]exec TDBCTL-DISABLE-PRIMARY success") + return True + + def _stop_slave(self, cluster: Cluster, ctl_set): + # 再分发stop slave命令 + rpc_params = { + "addresses": [], + "cmds": ["set tc_admin=0", "stop slave"], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + for ctl in ctl_set: + self.log_info(f"exec stop slave in instance[{ctl.machine.ip}{IP_PORT_DIVIDER}{ctl.admin_port}") + rpc_params["addresses"] = [f"{ctl.machine.ip}{IP_PORT_DIVIDER}{ctl.admin_port}"] + res = DRSApi.rpc(rpc_params) + + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_(f"exec [{ctl.ip_port}] stop slave failed: {res[0]['error_msg']}") + ) + + return True + + def _new_master_enable_primary(self, cluster: Cluster, new_master, reduce_ctl_primary): + """ + 提升新节点作为主节点的逻辑 + """ + rpc_params = { + "addresses": [f"{new_master.machine.ip}{IP_PORT_DIVIDER}{new_master.admin_port}"], + "cmds": [], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + + # 查询reduce_ctl_primary对应的server_name + reduce_ip = reduce_ctl_primary.split(":")[0] + reduce_port = reduce_ctl_primary.split(":")[1] + server_name = "test_name" + select_sql = [ + "set tc_admin = 1", + f"select Server_name from mysql.servers where host = '{reduce_ip}' and port = {reduce_port}", + ] + rpc_params["cmds"] = select_sql + res = DRSApi.rpc(rpc_params) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("select mysql.servers failed: {}".format(res[0]["error_msg"])) + ) + if not res[0]["cmd_results"][1]["table_data"]: + self.log_warning(f"Node [{reduce_ctl_primary}] no longer has routing information") + else: + server_name = res[0]["cmd_results"][1]["table_data"][0]["Server_name"] + + # 提升新主节点 + exec_sql = ["set tc_admin=1", f"TDBCTL DROP NODE IF EXISTS {server_name}", "TDBCTL ENABLE PRIMARY"] + rpc_params["cmds"] = exec_sql + res = DRSApi.rpc(rpc_params) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException( + message=_("exec TDBCTL-DISABLE-PRIMARY failed: {}".format(res[0]["error_msg"])) + ) + return True + + def _sync_to_new_master(self, cluster: Cluster, new_primary, other_secondary): + """ + 其余的slave节点同步新的master + """ + # 获取同步账号 + data = DBConfigApi.query_conf_item( + { + "bk_biz_id": "0", + "level_name": LevelName.PLAT, + "level_value": "0", + "conf_file": "mysql#user", + "conf_type": ConfigTypeEnum.InitUser, + "namespace": NameSpaceEnum.TenDB.value, + "format": FormatType.MAP, + } + )["content"] + + # 远程授权 + MySQLPrivManagerApi.add_priv_without_account_rule( + { + "bk_cloud_id": cluster.bk_cloud_id, + "bk_biz_id": cluster.bk_biz_id, + "operator": "", + "user": data["repl_user"], + "psw": RSAHandler.encrypt_password( + MySQLPrivManagerApi.fetch_public_key(), data["repl_pwd"], salt=None + ), + "hosts": [slave.machine.ip for slave in other_secondary], + "dbname": "%", + "dml_ddl_priv": "", + "global_priv": "REPLICATION SLAVE, REPLICATION CLIENT", + "address": new_primary, + "role": PrivRole.TDBCTL.value, + } + ) + self.log_info(_("在[{}]创建添加同步账号成功").format(new_primary)) + + # 基于GTID建立同步 + for secondary in other_secondary: + repl_sql = ( + f"CHANGE MASTER TO" + f"MASTER_HOST ='{new_primary.split(':')[0]}'," + f"MASTER_PORT={new_primary.split(':')[1]}," + f"MASTER_USER ='{data['repl_user']}'," + f"MASTER_PASSWORD='{data['repl_pwd']}'," + "MASTER_AUTO_POSITION = 1;" + ) + + res = DRSApi.rpc( + { + "addresses": [f"{secondary.machine.ip}{IP_PORT_DIVIDER}{secondary.admin_port}"], + "cmds": ["set tc_admin = 0", repl_sql], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + ) + if res[0]["error_msg"]: + raise CtlSwitchToSlaveFailedException(message=_(f"exec change master failed: {res[0]['error_msg']}")) + return True + + def _execute(self, data, parent_data): + kwargs = data.get_one_of_inputs("kwargs") + + reduce_ctl_primary = kwargs["reduce_ctl_primary"] + new_ctl_primary = kwargs["new_ctl_primary"] + + # 获取cluster对象,包括中控实例、 spider端口等 + cluster = Cluster.objects.get(id=kwargs["cluster_id"]) + + # 查询所有的spider-ctl的其余从节点对象 + ctl_set = cluster.proxyinstance_set.filter( + tendbclusterspiderext__spider_role=TenDBClusterSpiderRole.SPIDER_MASTER + ).exclude(machine__ip=reduce_ctl_primary.split(":")[0]) + + # 阶段1 先检测是否当前可以提升主切换 + result = self._prepare_check(cluster=cluster, reduce_ctl_primary=reduce_ctl_primary) + + # 阶段2 尝试连接原来ctl_primary,执行TDBCTL DISABLE PRIMARY + if result: + self._exec_disable_primary(cluster, reduce_ctl_primary) + + # 阶段3 关闭所有从节点的主从同步 + self._stop_slave(cluster, ctl_set) + + # 阶段3 根据传入新的primary节点,计算出其余的从节点 + other_secondary = ctl_set.exclude(machine__ip=new_ctl_primary.split(":")[0]) + + # 阶段4 其余节点同步新的primary节点 + self._sync_to_new_master(cluster, new_ctl_primary, other_secondary) + + # 阶段5 连接新的primary节点,执行剔除原primary节点的命令, 并提升自己为primary TDBCTL ENABLE PRIMARY + self._new_master_enable_primary(cluster, new_ctl_primary, reduce_ctl_primary) + + +class CtlSwitchToSlaveComponent(Component): + name = __name__ + code = "ctl_switch_to_slave" + bound_service = CtlSwitchToSlaveService diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py b/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py new file mode 100644 index 0000000000..596a055959 --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py @@ -0,0 +1,139 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.utils.translation import ugettext_lazy as _ +from pipeline.component_framework.component import Component + +from backend.components import DBConfigApi, DRSApi +from backend.components.dbconfig.constants import FormatType, LevelName +from backend.constants import IP_PORT_DIVIDER +from backend.db_meta.models import Cluster, ProxyInstance +from backend.flow.consts import MYSQL_SYS_USER, ConfigTypeEnum, NameSpaceEnum +from backend.flow.engine.bamboo.scene.mysql.common.get_mysql_sys_user import get_mysql_sys_users +from backend.flow.engine.bamboo.scene.spider.common.exceptions import DropSpiderNodeFailedException +from backend.flow.plugins.components.collections.common.base_service import BaseService + + +class DropSpiderRoutingService(BaseService): + def _pre_check(self, cluster: Cluster, reduce_spider: ProxyInstance): + """ + 检测待下架的spider节点是否有存在访问 + """ + + # 获取内置账号名称 + data = DBConfigApi.query_conf_item( + { + "bk_biz_id": "0", + "level_name": LevelName.PLAT, + "level_value": "0", + "conf_file": "mysql#user", + "conf_type": ConfigTypeEnum.InitUser, + "namespace": NameSpaceEnum.TenDB.value, + "format": FormatType.MAP, + } + )["content"] + mysql_user_name_list = [data["admin_user"], data["backup_user"], data["monitor_user"], data["repl_user"]] + users = ",".join( + [ + "'" + str(x) + "'" + for x in MYSQL_SYS_USER + mysql_user_name_list + get_mysql_sys_users(cluster.bk_cloud_id) + ] + ) + + cmds = [f"select * from information_schema.processlist where command != 'Sleep' and User not in ({users})"] + res = DRSApi.rpc( + { + "addresses": [f"{reduce_spider.machine.ip}{IP_PORT_DIVIDER}{reduce_spider.port}"], + "cmds": cmds, + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + ) + + if res[0]["error_msg"]: + raise DropSpiderNodeFailedException(message=_("select processlist failed: {}".format(res[0]["error_msg"]))) + + if res[0]["cmd_results"][0]["table_data"]: + self.log_error(f"There are also {res[0]['cmd_results'][1]['rows_affected']} non-sleep state threads") + return False + + return True + + def _exec_drop_routing(self, cluster: Cluster, spider: ProxyInstance): + """ + 执行删除节点路由逻辑 + """ + ctl_primary = cluster.tendbcluster_ctl_primary_address() + + rpc_params = { + "addresses": [ctl_primary], + "cmds": [], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + + select_sqls = [ + "set tc_admin=1", + f"select Server_name from mysql.servers where host = '{spider.machine.ip}' and port = {spider.port}", + ] + + rpc_params["cmds"] = select_sqls + res = DRSApi.rpc(rpc_params) + + if res[0]["error_msg"]: + raise DropSpiderNodeFailedException( + message=_("select mysql.servers failed: {}".format(res[0]["error_msg"])) + ) + + if not res[0]["cmd_results"][1]["table_data"]: + self.log_warning(f"Node [{spider.ip_port}] no longer has routing information") + return True + + else: + server_name = res[0]["cmd_results"][1]["table_data"][0]["Server_name"] + + # 删除节点路由信息 + exec_sql = [ + "set tc_admin=1", + f"TDBCTL DROP NODE IF EXISTS {server_name}", + ] + rpc_params["cmds"] = exec_sql + res = DRSApi.rpc(rpc_params) + if res[0]["error_msg"]: + raise DropSpiderNodeFailedException( + message=_("exec TDBCTL-DROP-NODE failed: {}".format(res[0]["error_msg"])) + ) + return True + + def _execute(self, data, parent_data): + kwargs = data.get_one_of_inputs("kwargs") + + reduce_spiders = kwargs["reduce_spiders"] + is_safe = kwargs["is_safe"] + cluster = Cluster.objects.get(id=kwargs["cluster_id"]) + + for spider in reduce_spiders: + # spider机器是专属于一套集群,单机单实例 + s = cluster.proxyinstance_set.get(machine__ip=spider["ip"]) + + if is_safe: + if not self._pre_check(cluster, s): + # 检测不通过退出 + return False + + # 执行删除路由 + self.log_info(f"exec drop node [{s.ip_port}]") + self._exec_drop_routing(cluster, s) + return True + + +class DropSpiderRoutingComponent(Component): + name = __name__ + code = "drop_spider_routing" + bound_service = DropSpiderRoutingService diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index dfff56b0fa..2fbc67ad01 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -122,6 +122,7 @@ from backend.flow.views.spider_cluster_rename_database import TenDBClusterRenameDatabaseView from backend.flow.views.spider_cluster_truncate_database import TenDBClusterTruncateDatabaseView from backend.flow.views.spider_partition import SpiderPartitionSceneApiView +from backend.flow.views.spider_reduce_nodes import ReduceSpiderNodesSceneApiView from backend.flow.views.spider_semantic_check import SpiderSemanticCheckSceneApiView from backend.flow.views.spider_slave_apply import InstallSpiderSlaveClusterSceneApiView from backend.flow.views.spider_sql_import import SpiderSqlImportSceneApiView @@ -260,6 +261,8 @@ # spider 添加 url(r"^scene/add_spider_nodes$", AddSpiderNodesSceneApiView.as_view()), url(r"^scene/tendbcluster_full_backup$", TenDBClusterFullBackupView.as_view()), + # spider 减少 + url(r"^scene/reduce_spider_nodes$", ReduceSpiderNodesSceneApiView.as_view()), # riak url(r"^scene/riak_cluster_apply$", RiakApplySceneApiView.as_view()), ] diff --git a/dbm-ui/backend/flow/utils/mysql/mysql_act_dataclass.py b/dbm-ui/backend/flow/utils/mysql/mysql_act_dataclass.py index 51866b428c..1dc639517f 100644 --- a/dbm-ui/backend/flow/utils/mysql/mysql_act_dataclass.py +++ b/dbm-ui/backend/flow/utils/mysql/mysql_act_dataclass.py @@ -322,7 +322,7 @@ class DelServiceInstKwargs: 删除集群内服务实例的专属私有变量 """ - cluster_id: str # 对应的cluster_id + cluster_id: int # 对应的cluster_id del_instance_list: list # 删除对应的实例信息 diff --git a/dbm-ui/backend/flow/utils/spider/get_spider_incr.py b/dbm-ui/backend/flow/utils/spider/get_spider_incr.py index 56a3a13a8d..1ab7ddba49 100644 --- a/dbm-ui/backend/flow/utils/spider/get_spider_incr.py +++ b/dbm-ui/backend/flow/utils/spider/get_spider_incr.py @@ -13,7 +13,6 @@ from django.utils.translation import ugettext_lazy as _ from backend.components import DRSApi -from backend.constants import IP_PORT_DIVIDER from backend.db_meta.models import Cluster from backend.flow.consts import MAX_SPIDER_MASTER_COUNT from backend.flow.engine.bamboo.scene.spider.common.exceptions import FailedToAssignIncrException @@ -27,8 +26,7 @@ def get_spider_master_incr(cluster: Cluster, add_spiders: list) -> list: 每个spider节点每个分配到的值目前阶段必须小于等于37 """ new_add_spiders = copy.deepcopy(add_spiders) - spider_instance = cluster.proxyinstance_set.first() # 随便拿一个接入层 - ctl_address = "{}{}{}".format(spider_instance.machine.ip, IP_PORT_DIVIDER, spider_instance.admin_port) + ctl_address = cluster.tendbcluster_ctl_primary_address() # 随便拿一个spider-master接入层 logger.info("ctl address: {}".format(ctl_address)) res = DRSApi.rpc( @@ -45,11 +43,11 @@ def get_spider_master_incr(cluster: Cluster, add_spiders: list) -> list: message=_("select spider_auto_increment failed: {}".format(res[0]["error_msg"])) ) - if res[0]["cmd_results"][1]["table_data"]: + if not res[0]["cmd_results"][1]["table_data"]: raise FailedToAssignIncrException(message=_("select spider_auto_increment is null, check ")) # 生成对比list - tmp_list = [info["SPIDER_AUTO_INCREMENT_MODE_VALUE"] for info in res[0]["cmd_results"][1]["table_data"]] + tmp_list = [int(info["SPIDER_AUTO_INCREMENT_MODE_VALUE"]) for info in res[0]["cmd_results"][1]["table_data"]] # incr_number 从1开始寻找,如果已使用则跳过,直至到未使用则赋值给对应的待加入的spider-master节点,且跳出 start = 0 diff --git a/dbm-ui/backend/flow/utils/spider/spider_act_dataclass.py b/dbm-ui/backend/flow/utils/spider/spider_act_dataclass.py index b4685cb863..71df2981fc 100644 --- a/dbm-ui/backend/flow/utils/spider/spider_act_dataclass.py +++ b/dbm-ui/backend/flow/utils/spider/spider_act_dataclass.py @@ -35,3 +35,35 @@ class AddSpiderRoutingKwargs: add_spider_role: TenDBClusterSpiderRole user: str passwd: str + + +@dataclass +class CtlSwitchToSlaveKwargs: + """ + 定义ctl集群切换的私有变量结构体 + """ + + cluster_id: int + reduce_ctl_primary: str # 待回收的ctl,格式是ip:port + new_ctl_primary: str # 待提升主的ctl,格式是ip:port + + +@dataclass +class CtlDropRoutingKwargs: + """ + 定义ctl节点路由删除的私有变量结构体 + """ + + cluster_id: int + reduce_ctl: str # 待回收的ctl,格式是ip:port + + +@dataclass +class DropSpiderRoutingKwargs: + """ + 定义spider节点路由删除的私有变量结构体 + """ + + cluster_id: int + reduce_spiders: list # 待下架的spider列表,每个元素的格式是字典 + is_safe: bool # 是否做安全检测 diff --git a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py index 38d622771a..3a1bd82629 100644 --- a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py +++ b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py @@ -113,3 +113,13 @@ def add_spider_master_nodes_apply(self): todo 后续tdbctl新版本出现在补齐 """ return True + + def reduce_spider_nodes_apply(self): + """ + 对已有的TenDB cluster集群 (spider集群)缩容spider节点,这里不区分spider角色 + """ + TenDBClusterClusterHandler.reduce_spider( + cluster_id=self.global_data["cluster_id"], + spiders=self.global_data["reduce_spiders"], + ) + return True diff --git a/dbm-ui/backend/flow/views/spider_reduce_nodes.py b/dbm-ui/backend/flow/views/spider_reduce_nodes.py new file mode 100644 index 0000000000..ed513a276c --- /dev/null +++ b/dbm-ui/backend/flow/views/spider_reduce_nodes.py @@ -0,0 +1,32 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import logging +import uuid + +from rest_framework.response import Response + +from backend.flow.engine.controller.spider import SpiderController +from backend.flow.views.base import FlowTestView + +logger = logging.getLogger("root") + + +class ReduceSpiderNodesSceneApiView(FlowTestView): + """ + api: /apis/v1/flow/scene/reduce_spider_nodes + params: + """ + + def post(self, request): + root_id = uuid.uuid1().hex + test = SpiderController(root_id=root_id, ticket_data=request.data) + test.reduce_spider_nodes_scene() + return Response({"root_id": root_id}) From 83a068d11435d16e3918cbcd8ab968b38818105e Mon Sep 17 00:00:00 2001 From: seanlook Date: Fri, 30 Jun 2023 17:43:36 +0800 Subject: [PATCH 070/476] =?UTF-8?q?fix(backend):=20=E4=BF=AE=E5=A4=8Ddbcon?= =?UTF-8?q?fig=E5=9B=BD=E9=99=85=E5=8C=96=E9=97=AE=E9=A2=98=20close=20#364?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/db-config/assets/migrate.md | 3 +- .../migrations/000010_common_data.up.sql | 2 - .../assets/migrations/000011_es_data.up.sql | 4 +- .../assets/migrations/000012_hdfs_data.up.sql | 14 +-- .../migrations/000013_kafka_data.up.sql | 4 +- ...00014_PredixyTendisplusCluster_data.up.sql | 18 ++- .../migrations/000015_rediscomm_data.up.sql | 10 +- .../000016_RedisInstance_data.up.sql | 4 +- .../migrations/000017_RedisMS_data.up.sql | 6 +- .../migrations/000018_tendb_data.up.sql | 47 ++++---- .../000019_tendbcluster_data.up.sql | 58 +++++----- .../migrations/000020_tendbha_data.up.sql | 54 +++++---- .../migrations/000021_tendbsingle_data.up.sql | 52 +++++---- .../migrations/000022_TendisCache_data.up.sql | 8 +- .../000023_TendisplusInstance_data.up.sql | 4 +- .../migrations/000024_TendisSSD_data.up.sql | 4 +- .../migrations/000025_TendisX_data.up.sql | 4 +- .../000026_TwemproxyRedisInstance_data.up.sql | 14 +-- ...27_TwemproxyTendisplusInstance_data.up.sql | 10 +- ...028_TwemproxyTendisSSDInstance_data.up.sql | 6 +- .../migrations/000029_pulsar_data.up.sql | 4 +- .../migrations/000030_influxdb_data.up.sql | 4 +- .../migrations/000031_riak_data.down.sql | 2 + .../assets/migrations/000031_riak_data.up.sql | 109 ++++++++++++++++++ 24 files changed, 271 insertions(+), 174 deletions(-) create mode 100644 dbm-services/common/db-config/assets/migrations/000031_riak_data.down.sql create mode 100644 dbm-services/common/db-config/assets/migrations/000031_riak_data.up.sql diff --git a/dbm-services/common/db-config/assets/migrate.md b/dbm-services/common/db-config/assets/migrate.md index 72848ed50e..91f5d7edac 100644 --- a/dbm-services/common/db-config/assets/migrate.md +++ b/dbm-services/common/db-config/assets/migrate.md @@ -16,7 +16,7 @@ sed -i 's/CREATE TABLE /CREATE TABLE IF NOT EXISTS /g' 000002_create_table.up.sq dbuser=xx dbpass=xxx seqno=10 -namespaces="common es hdfs kafka PredixyTendisplusCluster rediscomm RedisInstance RedisMS tendb tendbcluster tendbha tendbsingle TendisCache TendisplusInstance TendisSSD TendisX TwemproxyRedisInstance TwemproxyTendisplusInstance TwemproxyTendisSSDInstance pulsar influxdb" +namespaces="common es hdfs kafka PredixyTendisplusCluster rediscomm RedisInstance RedisMS tendb tendbcluster tendbha tendbsingle TendisCache TendisplusInstance TendisSSD TendisX TwemproxyRedisInstance TwemproxyTendisplusInstance TwemproxyTendisSSDInstance pulsar influxdb riak" dbname=dbconfig_release exclude_sensitive="(flag_encrypt!=1 or value_default like '{{%')" @@ -33,6 +33,7 @@ DELETE FROM tb_config_name_def WHERE namespace='${namespace}' AND ${exclude_sens let seqno+=1 done +sed -i '/Dump completed on /d' 0000*.sql ``` migrates 文件名前缀一次保持递增 \ No newline at end of file diff --git a/dbm-services/common/db-config/assets/migrations/000010_common_data.up.sql b/dbm-services/common/db-config/assets/migrations/000010_common_data.up.sql index 1b432935ea..16576a1285 100644 --- a/dbm-services/common/db-config/assets/migrations/000010_common_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000010_common_data.up.sql @@ -37,7 +37,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -78,4 +77,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000011_es_data.up.sql b/dbm-services/common/db-config/assets/migrations/000011_es_data.up.sql index dc65b55d87..32b2f7ad09 100644 --- a/dbm-services/common/db-config/assets/migrations/000011_es_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000011_es_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='es' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (74,'es','dbconf','7.10.2','elasticsearch.yml配置','es配置文件','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'es配置文件','2022-09-05 17:00:13','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (74,'es','dbconf','7.10.2','elasticsearch.yml配置','ES-7.10','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'es配置文件','2022-09-05 17:00:13','2023-06-30 17:27:03',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -103,4 +102,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000012_hdfs_data.up.sql b/dbm-services/common/db-config/assets/migrations/000012_hdfs_data.up.sql index 0e568933c3..81a6f4c655 100644 --- a/dbm-services/common/db-config/assets/migrations/000012_hdfs_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000012_hdfs_data.up.sql @@ -24,12 +24,12 @@ -- -- WHERE: namespace='hdfs' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (78,'hdfs','core-site','2.6.0-cdh5.4.11-tendataV0.2','core-site配置','core-site配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'core-site配置','2022-09-18 17:08:55','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (101,'hdfs','dbconf','2.6.0-cdh5.4.11-tendataV0.2','hdfs集群配置','hdfs集群配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs集群配置','2022-10-18 16:00:03','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (77,'hdfs','hdfs-site','2.6.0-cdh5.4.11-tendataV0.2','hdfs-site配置','hdfs-site配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs-site配置','2022-09-18 17:08:55','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (76,'hdfs','hdfsconf','2.6.0-cdh5.4.11-tendataV0.2','hdfs配置','hdfs配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs配置','2022-09-18 16:53:04','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (83,'hdfs','install','2.6.0-cdh5.4.11-tendataV0.2','hdfs安装配置','hdfs安装配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs安装配置','2022-09-19 17:02:17','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (79,'hdfs','zoo.cfg','2.6.0-cdh5.4.11-tendataV0.2','zk配置','zk配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'zk配置','2022-09-18 17:08:55','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (78,'hdfs','core-site','2.6.0-cdh5.4.11-tendataV0.2','core-site配置','core-site.xml','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'core-site配置','2022-09-18 17:08:55','2023-06-30 17:26:25',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (101,'hdfs','dbconf','2.6.0-cdh5.4.11-tendataV0.2','hdfs集群配置','2.6.0-cdh5.4.11','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs集群配置','2022-10-18 16:00:03','2023-06-29 10:36:47',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (77,'hdfs','hdfs-site','2.6.0-cdh5.4.11-tendataV0.2','hdfs-site配置','hdfs-site.xml','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs-site配置','2022-09-18 17:08:55','2023-06-30 17:26:19',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (76,'hdfs','hdfsconf','2.6.0-cdh5.4.11-tendataV0.2','hdfs配置','hdfs config','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs配置','2022-09-18 16:53:04','2023-06-30 17:26:37',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (83,'hdfs','install','2.6.0-cdh5.4.11-tendataV0.2','hdfs安装配置','2.6.0-cdh5.4.11','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'hdfs安装配置','2022-09-19 17:02:17','2023-06-29 10:37:49',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (79,'hdfs','zoo.cfg','2.6.0-cdh5.4.11-tendataV0.2','zk配置','zoo.cfg','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'zk配置','2022-09-18 17:08:55','2023-06-30 17:26:47',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -41,7 +41,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -163,4 +162,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000013_kafka_data.up.sql b/dbm-services/common/db-config/assets/migrations/000013_kafka_data.up.sql index fbab25b4b4..d9ce6febff 100644 --- a/dbm-services/common/db-config/assets/migrations/000013_kafka_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000013_kafka_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='kafka' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (84,'kafka','dbconf','2.4.0','kafka配置','kafka配置文件','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'kafka配置文件','2022-09-20 15:17:36','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (84,'kafka','dbconf','2.4.0','kafka配置','kafka-2.4','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'kafka配置文件','2022-09-20 15:17:36','2023-06-30 17:27:00',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -83,4 +82,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000014_PredixyTendisplusCluster_data.up.sql b/dbm-services/common/db-config/assets/migrations/000014_PredixyTendisplusCluster_data.up.sql index 143c5b9563..d11a227b19 100644 --- a/dbm-services/common/db-config/assets/migrations/000014_PredixyTendisplusCluster_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000014_PredixyTendisplusCluster_data.up.sql @@ -24,14 +24,14 @@ -- -- WHERE: namespace='PredixyTendisplusCluster' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (99,'PredixyTendisplusCluster','config','backup','配置','备份相关的配置','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'备份相关的配置','2022-09-28 12:08:17','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (121,'PredixyTendisplusCluster','config','binlogbackup','配置','binlog备份相关的配置','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'binlog备份相关的配置','2022-11-23 19:54:59','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (120,'PredixyTendisplusCluster','config','fullbackup','配置','全备相关的配置','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'全备相关的配置','2022-11-23 19:54:59','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (122,'PredixyTendisplusCluster','config','heartbeat','配置','心跳相关的配置','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'心跳相关的配置','2022-11-23 19:54:59','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (100,'PredixyTendisplusCluster','config','monitor','配置','监控相关的配置','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'监控相关的配置','2022-09-28 12:08:17','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (97,'PredixyTendisplusCluster','dbconf','Tendisplus-2.5','redis配置','Tendisplus-2.5的配置文件','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'Tendisplus-2.5的配置文件','2022-09-28 12:08:17','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (202,'PredixyTendisplusCluster','dbconf','Tendisplus-2.6','redis配置','Tendisplus-2.6的配置文件','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-04-07 15:40:18',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (98,'PredixyTendisplusCluster','proxyconf','Predixy-latest','redis配置','predixy配置文件','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'predixy配置文件','2022-09-28 12:08:17','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (99,'PredixyTendisplusCluster','config','backup','备份相关的配置','backup','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'备份相关的配置','2022-09-28 12:08:17','2023-06-30 17:28:27',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (121,'PredixyTendisplusCluster','config','binlogbackup','binlog备份相关的配置','binlogbackup','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'binlog备份相关的配置','2022-11-23 19:54:59','2023-06-30 17:29:56',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (120,'PredixyTendisplusCluster','config','fullbackup','全备相关的配置','fullbackup','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'全备相关的配置','2022-11-23 19:54:59','2023-06-30 17:29:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (122,'PredixyTendisplusCluster','config','heartbeat','心跳相关的配置','heartbeat','pub,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'心跳相关的配置','2022-11-23 19:54:59','2023-06-30 17:29:29',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (100,'PredixyTendisplusCluster','config','monitor','监控相关的配置','monitor','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'监控相关的配置','2022-09-28 12:08:17','2023-06-30 17:28:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (97,'PredixyTendisplusCluster','dbconf','Tendisplus-2.5','redis配置','Tendisplus-2.5','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'Tendisplus-2.5的配置文件','2022-09-28 12:08:17','2023-06-29 10:33:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (202,'PredixyTendisplusCluster','dbconf','Tendisplus-2.6','redis配置','Tendisplus-2.6','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-29 10:35:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (98,'PredixyTendisplusCluster','proxyconf','Predixy-latest','redis配置','Predixy-latest','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'predixy配置文件','2022-09-28 12:08:17','2023-06-29 10:36:57',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -43,7 +43,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -184,4 +183,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000015_rediscomm_data.up.sql b/dbm-services/common/db-config/assets/migrations/000015_rediscomm_data.up.sql index 19bbcbb3ba..add40a3c17 100644 --- a/dbm-services/common/db-config/assets/migrations/000015_rediscomm_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000015_rediscomm_data.up.sql @@ -24,13 +24,13 @@ -- -- WHERE: namespace='rediscomm' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (124,'rediscomm','config','base','配置','运行时间','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'运行时间','2022-11-29 14:51:54','2023-04-06 11:59:44',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (126,'rediscomm','config','bigkey','配置','热key相关配置','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'热key相关配置','2022-11-29 14:51:54','2023-04-06 11:59:44',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (124,'rediscomm','config','base','运行时间','base','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'运行时间','2022-11-29 14:51:54','2023-06-30 17:29:26',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (126,'rediscomm','config','bigkey','热key相关配置','bigkey','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'热key相关配置','2022-11-29 14:51:54','2023-06-30 17:29:20',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (171,'rediscomm','config','binlogbackup','配置','binlog备份相关的配置','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'binlog备份相关的配置','2023-02-28 15:01:19','2023-04-06 11:59:44',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (170,'rediscomm','config','fullbackup','配置','全备相关的配置','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'全备相关的配置','2023-02-28 15:01:19','2023-04-06 11:59:44',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (172,'rediscomm','config','heartbeat','配置','心跳相关的配置','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'心跳相关的配置','2023-02-28 15:01:19','2023-04-06 11:59:44',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (125,'rediscomm','config','hotkey','配置','大key相关配置','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'大key相关配置','2022-11-29 14:51:54','2023-04-06 11:59:44',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (127,'rediscomm','config','keymod','配置','key模式相关配置','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'key模式相关配置','2022-11-29 14:51:54','2023-04-06 11:59:44',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (125,'rediscomm','config','hotkey','大key相关配置','hotkey','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'大key相关配置','2022-11-29 14:51:54','2023-06-30 17:29:23',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (127,'rediscomm','config','keymod','key模式相关配置','keymod','pub,plat,app,module,cluster','cluster',1,1,0,'rediscomm',5,365,0,'key模式相关配置','2022-11-29 14:51:54','2023-06-30 17:29:16',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (173,'rediscomm','config','monitor','配置','监控相关的配置','pub,plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'监控相关的配置','2023-02-28 15:01:19','2023-04-06 11:59:44',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; @@ -43,7 +43,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -106,4 +105,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000016_RedisInstance_data.up.sql b/dbm-services/common/db-config/assets/migrations/000016_RedisInstance_data.up.sql index 129816abb9..b7fe89519e 100644 --- a/dbm-services/common/db-config/assets/migrations/000016_RedisInstance_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000016_RedisInstance_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='RedisInstance' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (62,'RedisInstance','redisconf','Redis-6','Redis参数配置','redis-6版本_参数配置','plat,app,cluster','cluster',1,1,0,NULL,0,0,0,'redis-6版本_参数配置','2022-08-10 11:53:22','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (62,'RedisInstance','redisconf','Redis-6','Redis参数配置','Redis-6','plat,app,cluster','cluster',1,1,0,NULL,0,0,0,'redis-6版本_参数配置','2022-08-10 11:53:22','2023-06-29 10:33:57',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -131,4 +130,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000017_RedisMS_data.up.sql b/dbm-services/common/db-config/assets/migrations/000017_RedisMS_data.up.sql index d06bab156f..caec92d42a 100644 --- a/dbm-services/common/db-config/assets/migrations/000017_RedisMS_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000017_RedisMS_data.up.sql @@ -24,8 +24,8 @@ -- -- WHERE: namespace='RedisMS' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (52,'RedisMS','dbconf','RedisMS-2.8','DB参数配置','Redis主从版(2.8.17)','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'Redis主从版(2.8.17)','2022-08-02 14:29:01','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (53,'RedisMS','dbconf','RedisMS-3.2','DB参数配置','Redis主从版(3.2.12)','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'Redis主从版(3.2.12)','2022-08-02 14:29:01','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (52,'RedisMS','dbconf','RedisMS-2.8','DB参数配置','RedisMS-2.8','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'Redis主从版(2.8.17)','2022-08-02 14:29:01','2023-06-29 10:34:24',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (53,'RedisMS','dbconf','RedisMS-3.2','DB参数配置','RedisMS-3.2','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'Redis主从版(3.2.12)','2022-08-02 14:29:01','2023-06-29 10:34:19',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -37,7 +37,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -75,4 +74,3 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000018_tendb_data.up.sql b/dbm-services/common/db-config/assets/migrations/000018_tendb_data.up.sql index 66b4f15187..8d027d206a 100644 --- a/dbm-services/common/db-config/assets/migrations/000018_tendb_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000018_tendb_data.up.sql @@ -39,7 +39,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -75,26 +74,31 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (8864,'tendb','init_user','mysql#user','yw_user','STRING','yw','','STRING',1,0,1,0,0,NULL,'','',-1,NULL,'','2022-05-23 15:54:15','2022-09-19 13:16:16',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (8860,'tendb','init_user','proxy#user','proxy_admin_user','STRING','proxy','','STRING',1,0,1,0,0,NULL,'','',-1,NULL,'','2022-05-23 15:54:15','2023-03-24 17:30:13',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15825,'tendb','init_user','spider#user','tdbctl_user','STRING','tdbctl','','STRING',1,0,1,0,0,NULL,'','',-1,NULL,'','2023-03-09 17:36:33','2023-03-24 17:30:47',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16465,'tendb','mysql_monitor','items-config.yaml','character-consistency','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 14 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": [\n \"slave\"\n ]\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16471,'tendb','mysql_monitor','items-config.yaml','ctl-replicate','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16470,'tendb','mysql_monitor','items-config.yaml','engine','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 12 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16466,'tendb','mysql_monitor','items-config.yaml','ext3-check','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 16 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16458,'tendb','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 10s\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16454,'tendb','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 10m\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16459,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\n \"enable\": true,\n \"schedule\": \"0 40 23 * * *\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16457,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\n \"enable\": true,\n \"schedule\": \"0 30 23 * * *\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16467,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 12 * * *\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16451,'tendb','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16455,'tendb','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16460,'tendb','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16461,'tendb','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16462,'tendb','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 14 * * 1\",\n \"machine_type\": [\n \"proxy\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16450,'tendb','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 14 * * 1\",\n \"machine_type\": [\n \"proxy\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16453,'tendb','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\n \"enable\": true,\n \"schedule\": \"0 55 23 * * *\",\n \"machine_type\": [\n \"backend\",\n \"remote\",\n \"spider\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16469,'tendb','mysql_monitor','items-config.yaml','routine-definer','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 15 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16463,'tendb','mysql_monitor','items-config.yaml','slave-status','STRING','{\n \"enable\": true,\n \"schedule\": \"@every 1m\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": [\n \"repeater\",\n \"slave\"\n ]\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16456,'tendb','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 15 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16464,'tendb','mysql_monitor','items-config.yaml','view-definer','STRING','{\n \"enable\": true,\n \"schedule\": \"0 0 15 * * 1\",\n \"machine_type\": [\n \"backend\",\n \"remote\"\n ],\n \"role\": []\n}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-06-07 17:44:57',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16571,'tendb','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16594,'tendb','mysql_monitor','items-config.yaml','ctl-replicate','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16575,'tendb','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16576,'tendb','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true,\"schedule\":\"0 0 16 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16577,'tendb','mysql_monitor','items-config.yaml','ibd-statistic','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[\"slave\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16578,'tendb','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"master\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16579,'tendb','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16582,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true,\"schedule\":\"0 40 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16581,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true,\"schedule\":\"0 30 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16580,'tendb','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16584,'tendb','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16583,'tendb','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16589,'tendb','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16588,'tendb','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16590,'tendb','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16591,'tendb','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16592,'tendb','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true,\"schedule\":\"0 55 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16572,'tendb','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16593,'tendb','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"slave\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16587,'tendb','mysql_monitor','items-config.yaml','spider-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16585,'tendb','mysql_monitor','items-config.yaml','spider-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16586,'tendb','mysql_monitor','items-config.yaml','spider-err-warn','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16595,'tendb','mysql_monitor','items-config.yaml','spider-remote','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16574,'tendb','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16573,'tendb','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:19:36','2023-06-30 17:19:36',0); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -106,4 +110,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000019_tendbcluster_data.up.sql b/dbm-services/common/db-config/assets/migrations/000019_tendbcluster_data.up.sql index d10aec1b89..13a6d25c76 100644 --- a/dbm-services/common/db-config/assets/migrations/000019_tendbcluster_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000019_tendbcluster_data.up.sql @@ -29,11 +29,11 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (189,'tendbcluster','backup','dbbackup.options','备份控制选项','dbbackup.ini控制选项','plat,app,module,cluster','',1,1,0,'',0,0,0,'dbbackup.ini控制选项','2023-03-09 17:40:06','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (190,'tendbcluster','checksum','checksum.option','checksum控制选项','checksum.option','plat,app,module,cluster','',1,1,0,'',0,0,0,'checksum.option','2023-03-09 17:40:06','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (191,'tendbcluster','checksum','checksum.yaml','checksum配置','checksum.yaml','plat,app,module,cluster','',1,1,0,'',0,0,0,'checksum.yaml','2023-03-09 17:40:06','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (145,'tendbcluster','dbconf','MySQL-5.6','my.cnf配置','5.6_参数配置','plat,app,module,cluster','cluster',1,1,0,'',0,0,0,'5.6_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (144,'tendbcluster','dbconf','MySQL-5.7','my.cnf配置','5.7_参数配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7配置','2022-04-25 10:19:22','2023-03-28 21:40:30',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (143,'tendbcluster','dbconf','MySQL-8.0','','8.0_参数配置','plat,app,module,cluster','cluster',1,1,0,'',0,0,0,'MySQL8.0配置','2022-06-02 17:27:34','2023-03-28 21:40:19',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (147,'tendbcluster','dbconf','Spider-1','my.cnf配置','Spider 1.x 接入层','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'Spider 1.x 接入层','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (148,'tendbcluster','dbconf','Spider-3','my.cnf配置','Spider 3.x 接入层','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'Spider 3.x 接入层','2022-04-25 10:19:22','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (145,'tendbcluster','dbconf','MySQL-5.6','my.cnf配置','MySQL-5.7','plat,app,module,cluster','cluster',1,1,0,'',0,0,0,'5.6_参数配置','2022-04-25 10:19:22','2023-06-29 10:32:57',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (144,'tendbcluster','dbconf','MySQL-5.7','my.cnf配置','MySQL-5.7','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7配置','2022-04-25 10:19:22','2023-06-29 10:33:14',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (143,'tendbcluster','dbconf','MySQL-8.0','','MySQL-8.0','plat,app,module,cluster','cluster',1,1,0,'',0,0,0,'MySQL8.0配置','2022-06-02 17:27:34','2023-06-29 10:32:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (147,'tendbcluster','dbconf','Spider-1','my.cnf配置','Spider 1.x','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'Spider 1.x 接入层','2022-04-25 10:19:22','2023-06-29 10:33:02',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (148,'tendbcluster','dbconf','Spider-3','my.cnf配置','Spider 3.x','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'Spider 3.x 接入层','2022-04-25 10:19:22','2023-06-29 10:33:05',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (177,'tendbcluster','dbconf','Tdbctl','my.cnf配置','tdbctl中控配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'tdbctl中控配置','2022-04-25 10:19:22','2023-05-10 19:35:47',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (192,'tendbcluster','deploy','deploy_info','部署配置',NULL,'plat,app,module,cluster','',0,1,0,NULL,5,365,0,NULL,'2023-03-09 17:40:06','2023-03-20 21:40:05',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (194,'tendbcluster','sys','sysfile','系统配置',NULL,'plat','',1,1,0,NULL,5,365,0,NULL,'2023-03-09 17:40:06','2023-03-20 21:40:05',''); @@ -48,7 +48,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -87,7 +86,7 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14152,'tendbcluster','backup','binlog_rotate.yaml','public.max_disk_used_pct','INT','80','[1,99]','RANGE',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:46',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14153,'tendbcluster','backup','binlog_rotate.yaml','public.max_keep_duration','STRING','61d','','DURATION',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:47',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14154,'tendbcluster','backup','binlog_rotate.yaml','public.purge_interval','STRING','4h','','DURATION',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:48',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14155,'tendbcluster','backup','binlog_rotate.yaml','public.rotate_interval','STRING','10m','','STRING',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:49',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14155,'tendbcluster','backup','binlog_rotate.yaml','public.rotate_interval','STRING','30m','','STRING',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-06-29 18:43:46',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14156,'tendbcluster','backup','binlog_rotate.yaml','report.enable','BOOL','true','true | false','ENUM',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:50',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14157,'tendbcluster','backup','binlog_rotate.yaml','report.filepath','STRING','/home/mysql/dbareport/mysql/binlog','','STRING',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:51',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (14158,'tendbcluster','backup','binlog_rotate.yaml','report.log_maxage','INT','30','[1, 60]','ENUM',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'','2023-03-09 17:36:33','2023-03-22 12:27:52',0); @@ -1584,7 +1583,7 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15786,'tendbcluster','dbconf','Tdbctl','mysqld.table_open_cache','INT','5120','[1, 524288]','RANGE',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'The number of open tables for all threads. Increasing this value increases the number of file descriptors that mysqld requires.','2023-03-09 17:57:45','2023-05-10 19:35:56',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15787,'tendbcluster','dbconf','Tdbctl','mysqld.table_open_cache_instances','STRING','{MIN(DBInitMemory/1000,16)}','','',-1,0,0,0,1,NULL,NULL,NULL,-1,NULL,'The number of table cache instances','2023-03-09 17:57:45','2023-05-10 19:35:56',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16472,'tendbcluster','dbconf','Tdbctl','mysqld.tc_admin','INT','1','1 | 0','ENUM',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'When the value is ON, it means that the current node is the master node, allowing the execution of cluster-related DDL statements, management statements','2023-03-09 17:57:45','2023-06-12 10:37:08',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16473,'tendbcluster','dbconf','Tdbctl','mysqld.tc_skip_dump_db_list','STRING','performance_schema,information_schema,mysql,test,infodba_schema',NULL,'',2,0,0,0,1,'{{mysqld.server_id}}',NULL,NULL,-1,NULL,NULL,'2023-03-09 17:57:45','2023-05-10 19:35:56',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16473,'tendbcluster','dbconf','Tdbctl','mysqld.tc_skip_dump_db_list','STRING','performance_schema,information_schema,mysql,test,sys,infodba_schema',NULL,'',2,0,0,0,1,'{{mysqld.server_id}}',NULL,NULL,-1,NULL,NULL,'2023-03-09 17:57:45','2023-06-28 17:33:15',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15788,'tendbcluster','dbconf','Tdbctl','mysqld.thread_cache_size','INT','8','[4,64]','RANGE',1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'How many threads we should keep in a cache for reuse','2023-03-09 17:57:45','2023-05-10 19:35:56',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15789,'tendbcluster','dbconf','Tdbctl','mysqld.thread_handling','STRING','one-thread-per-connection','one-thread-per-connection| pool-of-threads ','ENUM',-1,0,0,0,1,NULL,NULL,NULL,-1,NULL,'The thread-handling model used by the server for connection threads.','2023-03-09 17:57:45','2023-05-10 19:35:56',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15790,'tendbcluster','dbconf','Tdbctl','mysqld.thread_pool_oversubscribe','INT','3','[3,32]','RANGE',-1,0,0,0,0,NULL,NULL,NULL,-1,NULL,'Number of additional threads per group of thread pool.','2023-03-09 17:57:45','2023-05-10 19:35:56',0); @@ -1605,23 +1604,31 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16289,'tendbcluster','deploy','deploy_info','spider_version','STRING','Spider-3','Spider-3 | Spider-1','ENUM',1,0,0,0,1,NULL,NULL,'容灾级别',-1,NULL,NULL,'2023-03-09 17:36:33','2023-05-22 17:04:31',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15066,'tendbcluster','deploy','deploy_info','storage_engine','STRING','InnoDB','InnoDB','',1,0,0,0,1,NULL,NULL,'存储引擎',-1,NULL,NULL,'2023-03-09 17:36:33','2023-03-09 17:36:33',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15067,'tendbcluster','deploy','deploy_info','tolerance_level','STRING','compus','idc|compus|city','ENUM',-1,0,0,0,1,NULL,NULL,'容灾级别',-1,NULL,NULL,'2023-03-09 17:36:33','2023-03-09 17:36:33',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15881,'tendbcluster','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true, \"schedule\":\"0 0 14 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15882,'tendbcluster','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15883,'tendbcluster','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true, \"schedule\":\"0 0 16 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15884,'tendbcluster','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true, \"schedule\":\"@every 10s\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15885,'tendbcluster','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true, \"schedule\":\"@every 10m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15886,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true, \"schedule\":\"0 40 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15887,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true, \"schedule\":\"0 30 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15888,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15889,'tendbcluster','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15890,'tendbcluster','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15891,'tendbcluster','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15892,'tendbcluster','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15893,'tendbcluster','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true, \"schedule\":\"0 55 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15894,'tendbcluster','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15895,'tendbcluster','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": [\"repeater\", \"slave\"]}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15896,'tendbcluster','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15897,'tendbcluster','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:54','2023-03-22 12:35:54',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16721,'tendbcluster','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16744,'tendbcluster','mysql_monitor','items-config.yaml','ctl-replicate','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16725,'tendbcluster','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16726,'tendbcluster','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true,\"schedule\":\"0 0 16 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16727,'tendbcluster','mysql_monitor','items-config.yaml','ibd-statistic','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[\"slave\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16728,'tendbcluster','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"master\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16729,'tendbcluster','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16732,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true,\"schedule\":\"0 40 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16731,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true,\"schedule\":\"0 30 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16730,'tendbcluster','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16734,'tendbcluster','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16733,'tendbcluster','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16739,'tendbcluster','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16738,'tendbcluster','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16740,'tendbcluster','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16741,'tendbcluster','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16742,'tendbcluster','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true,\"schedule\":\"0 55 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16722,'tendbcluster','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16743,'tendbcluster','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"slave\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16737,'tendbcluster','mysql_monitor','items-config.yaml','spider-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16735,'tendbcluster','mysql_monitor','items-config.yaml','spider-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16736,'tendbcluster','mysql_monitor','items-config.yaml','spider-err-warn','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16745,'tendbcluster','mysql_monitor','items-config.yaml','spider-remote','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16724,'tendbcluster','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16723,'tendbcluster','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -1633,4 +1640,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:02 diff --git a/dbm-services/common/db-config/assets/migrations/000020_tendbha_data.up.sql b/dbm-services/common/db-config/assets/migrations/000020_tendbha_data.up.sql index 47089a9731..824a2a6a23 100644 --- a/dbm-services/common/db-config/assets/migrations/000020_tendbha_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000020_tendbha_data.up.sql @@ -29,13 +29,13 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (129,'tendbha','backup','dbbackup.options','备份控制选项','dbbackup.ini控制选项','plat,app,module,cluster','',1,1,0,'',0,0,0,'dbbackup.ini控制选项','2022-04-25 10:19:22','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (137,'tendbha','checksum','checksum.option','checksum控制选项','checksum.option','plat,app,module,cluster','',1,1,0,'',0,0,0,'checksum.option','2022-04-25 10:19:22','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (136,'tendbha','checksum','checksum.yaml','checksum配置','checksum.yaml','plat,app,module,cluster','',1,1,0,'',0,0,0,'checksum.yaml','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (9,'tendbha','dbconf','MySQL-5.6','my.cnf配置','5.6_参数配置','plat,app,module,cluster','cluster',0,0,0,'',0,0,0,'5.6_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (10,'tendbha','dbconf','MySQL-5.7','my.cnf配置','5.7_参数配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (40,'tendbha','dbconf','MySQL-8.0','','8.0_参数配置','plat,app,module,cluster','cluster',0,0,0,'',0,0,0,'MySQL8.0配置','2022-06-02 17:27:34','2023-03-28 21:40:07',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (9,'tendbha','dbconf','MySQL-5.6','my.cnf配置','MySQL-5.6','plat,app,module,cluster','cluster',0,0,0,'',0,0,0,'5.6_参数配置','2022-04-25 10:19:22','2023-06-29 10:34:52',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (10,'tendbha','dbconf','MySQL-5.7','my.cnf配置','MySQL-5.7','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7_参数配置','2022-04-25 10:19:22','2023-06-29 10:34:49',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (40,'tendbha','dbconf','MySQL-8.0','','MySQL-8.0','plat,app,module,cluster','cluster',0,0,0,'',0,0,0,'MySQL8.0配置','2022-06-02 17:27:34','2023-06-29 10:34:46',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (6,'tendbha','dbha','dbha','DBHA切换配置',NULL,'plat,app,city,module,cluster','',1,1,0,NULL,5,365,0,NULL,'2022-04-25 10:19:22','2023-03-20 21:40:05',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (4,'tendbha','deploy','deploy_info','部署配置',NULL,'plat,app,module,cluster','',0,1,0,NULL,5,365,0,NULL,'2022-04-25 10:19:22','2023-03-20 21:40:05',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (201,'tendbha','mysql_monitor','items-config.yaml','监控配置',NULL,'plat,app,module,cluster','',1,1,1,NULL,5,365,0,NULL,'2023-03-09 17:40:06','2023-03-20 21:40:05',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (39,'tendbha','proxyconf','default','','mysql-proxy配置','plat','',0,1,0,'',0,0,0,'mysql-proxy配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (39,'tendbha','proxyconf','default','','mysql-proxy','plat','',0,1,0,'',0,0,0,'mysql-proxy配置','2022-04-25 10:19:22','2023-06-30 17:24:45',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (7,'tendbha','sys','sysfile','系统配置',NULL,'plat','',1,1,0,NULL,5,365,0,NULL,'2022-04-25 10:19:22','2023-03-20 21:40:05',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (1,'tendbha','user','tb_app_info','用户配置',NULL,'plat,app,module,cluster','',1,1,0,NULL,NULL,NULL,0,NULL,'2022-04-25 10:19:22','2023-03-20 21:40:05',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; @@ -49,7 +49,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -997,25 +996,31 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (467,'tendbha','deploy','deploy_info','db_version','STRING','MySQL-5.7','MySQL-5.5 | MySQL-5.6 | MySQL-5.7 | MySQL-8.0','ENUM',1,0,0,0,1,NULL,NULL,'DB版本',-1,NULL,NULL,'2022-04-25 10:00:47','2022-09-13 17:28:25',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (468,'tendbha','deploy','deploy_info','storage_engine','STRING','InnoDB','InnoDB','',1,0,0,0,1,NULL,NULL,'存储引擎',-1,NULL,NULL,'2022-04-25 10:00:47','2022-09-13 15:03:55',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (470,'tendbha','deploy','deploy_info','tolerance_level','STRING','compus','idc|compus|city','ENUM',-1,0,0,0,1,NULL,NULL,'容灾级别',-1,NULL,NULL,'2022-04-25 10:00:47','2022-10-20 12:26:09',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15831,'tendbha','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true, \"schedule\":\"0 0 14 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:26',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15835,'tendbha','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:30',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15836,'tendbha','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true, \"schedule\":\"0 0 16 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:32',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15847,'tendbha','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true, \"schedule\":\"@every 10s\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:33:13',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15846,'tendbha','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true, \"schedule\":\"@every 10m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:45',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15845,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true, \"schedule\":\"0 40 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15844,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true, \"schedule\":\"0 30 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:43',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15843,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:41',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15839,'tendbha','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:36',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15838,'tendbha','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:34',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15841,'tendbha','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:38',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15840,'tendbha','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:37',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15913,'tendbha','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\"enable\":true, \"schedule\":\"0 0 14 * * 1\", \"machine_type\":\"proxy\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:33:13',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15912,'tendbha','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\"enable\":true, \"schedule\":\"0 0 14 * * 1\", \"machine_type\":\"proxy\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:33:13',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15842,'tendbha','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true, \"schedule\":\"0 55 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:40',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15832,'tendbha','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:27',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15837,'tendbha','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": [\"repeater\", \"slave\"]}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:33',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15834,'tendbha','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:29',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15833,'tendbha','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2022-05-27 13:09:08','2023-03-20 17:11:28',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16671,'tendbha','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16694,'tendbha','mysql_monitor','items-config.yaml','ctl-replicate','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16675,'tendbha','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16676,'tendbha','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true,\"schedule\":\"0 0 16 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16677,'tendbha','mysql_monitor','items-config.yaml','ibd-statistic','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[\"slave\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16678,'tendbha','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"master\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16679,'tendbha','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16682,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true,\"schedule\":\"0 40 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16681,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true,\"schedule\":\"0 30 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16680,'tendbha','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16684,'tendbha','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16683,'tendbha','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16689,'tendbha','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16688,'tendbha','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16690,'tendbha','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16691,'tendbha','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16692,'tendbha','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true,\"schedule\":\"0 55 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16672,'tendbha','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16693,'tendbha','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"slave\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16687,'tendbha','mysql_monitor','items-config.yaml','spider-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16685,'tendbha','mysql_monitor','items-config.yaml','spider-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16686,'tendbha','mysql_monitor','items-config.yaml','spider-err-warn','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16695,'tendbha','mysql_monitor','items-config.yaml','spider-remote','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16674,'tendbha','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16673,'tendbha','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (715,'tendbha','proxyconf','default','conn_log','STRING','true','true|false','ENUM',1,0,1,0,0,NULL,'','',-1,NULL,'','2022-05-23 15:51:24','2022-05-23 15:55:10',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (716,'tendbha','proxyconf','default','daemon','STRING','true','true|false','ENUM',1,0,1,0,0,NULL,'','',-1,NULL,'','2022-05-23 15:51:24','2022-05-23 15:55:10',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (719,'tendbha','proxyconf','default','event-threads','INT','7','[1,10]','RANGE',1,0,1,0,0,NULL,'','',-1,NULL,'','2022-05-23 15:51:24','2022-05-23 15:55:10',0); @@ -1045,4 +1050,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000021_tendbsingle_data.up.sql b/dbm-services/common/db-config/assets/migrations/000021_tendbsingle_data.up.sql index d21f9832f4..b08ffbae8c 100644 --- a/dbm-services/common/db-config/assets/migrations/000021_tendbsingle_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000021_tendbsingle_data.up.sql @@ -27,10 +27,10 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (178,'tendbsingle','backup','binlog_rotate.yaml','binlog滚动与备份选项','binlog_rotate.yaml','plat,app,module,cluster','',1,1,1,'',0,0,0,'binlog_rotate.yaml','2023-03-09 17:34:12','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (131,'tendbsingle','backup','dbbackup.ini','备份配置','dbbackup.conf配置项','plat,app,module,cluster','',1,1,0,'',0,0,0,'dbbackup.conf配置项','2022-04-25 10:19:22','2023-03-22 12:08:50',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (132,'tendbsingle','backup','dbbackup.options','备份控制选项','dbbackup.ini控制选项','plat,app,module,cluster','',1,1,0,'',0,0,0,'dbbackup.ini控制选项','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (47,'tendbsingle','dbconf','MySQL-5.6','my.cnf配置','5.6_参数配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.6_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (42,'tendbsingle','dbconf','MySQL-5.7','my.cnf配置','5.7_参数配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (48,'tendbsingle','dbconf','MySQL-8.0','my.cnf配置','8.0_参数配置','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'8.0_参数配置','2022-04-25 10:19:22','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (105,'tendbsingle','deploy','deploy_info','部署配置',NULL,'plat,app,module,cluster','',0,1,0,NULL,5,365,0,NULL,'2022-04-25 10:19:22','2023-03-20 21:40:05',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (47,'tendbsingle','dbconf','MySQL-5.6','my.cnf配置','MySQL-5.6','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.6_参数配置','2022-04-25 10:19:22','2023-06-29 10:34:35',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (42,'tendbsingle','dbconf','MySQL-5.7','my.cnf配置','MySQL-5.7','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'5.7_参数配置','2022-04-25 10:19:22','2023-06-29 10:34:41',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (48,'tendbsingle','dbconf','MySQL-8.0','my.cnf配置','MySQL-8.0','plat,app,module,cluster','cluster',1,1,0,NULL,5,365,0,'8.0_参数配置','2022-04-25 10:19:22','2023-06-29 10:34:32',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (105,'tendbsingle','deploy','deploy_info','部署配置','deploy_info','plat,app,module,cluster','',0,1,0,NULL,5,365,0,NULL,'2022-04-25 10:19:22','2023-06-30 17:29:49',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -42,7 +42,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -968,23 +967,31 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (12418,'tendbsingle','deploy','deploy_info','db_version','STRING','MySQL-5.7','MySQL-5.5 | MySQL-5.6 | MySQL-5.7 | MySQL-8.0','ENUM',1,0,0,0,1,NULL,NULL,'DB版本',-1,NULL,NULL,'2022-10-27 11:03:11','2022-10-27 11:03:11',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (12419,'tendbsingle','deploy','deploy_info','storage_engine','STRING','InnoDB','InnoDB','',1,0,0,0,1,NULL,NULL,'存储引擎',-1,NULL,NULL,'2022-10-27 11:03:11','2022-10-27 11:03:11',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (12420,'tendbsingle','deploy','deploy_info','tolerance_level','STRING','compus','idc|compus|city','ENUM',-1,0,0,0,1,NULL,NULL,'容灾级别',-1,NULL,NULL,'2022-10-27 11:03:11','2022-10-27 11:03:11',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15850,'tendbsingle','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true, \"schedule\":\"0 0 14 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15851,'tendbsingle','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15852,'tendbsingle','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true, \"schedule\":\"0 0 16 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15853,'tendbsingle','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true, \"schedule\":\"@every 10s\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15854,'tendbsingle','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true, \"schedule\":\"@every 10m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15855,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true, \"schedule\":\"0 40 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15856,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true, \"schedule\":\"0 30 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15857,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true, \"schedule\":\"0 0 12 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15858,'tendbsingle','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15859,'tendbsingle','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15860,'tendbsingle','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15861,'tendbsingle','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15862,'tendbsingle','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true, \"schedule\":\"0 55 23 * * *\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15863,'tendbsingle','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15864,'tendbsingle','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true, \"schedule\":\"@every 1m\", \"machine_type\":\"backend\", \"role\": [\"repeater\", \"slave\"]}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15865,'tendbsingle','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); -INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (15866,'tendbsingle','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true, \"schedule\":\"0 0 15 * * 1\", \"machine_type\":\"backend\", \"role\": []}','','MAP',1,0,0,0,0,NULL,'','',-1,NULL,'','2023-03-22 12:35:44','2023-03-22 12:35:44',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16696,'tendbsingle','mysql_monitor','items-config.yaml','character-consistency','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16719,'tendbsingle','mysql_monitor','items-config.yaml','ctl-replicate','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16700,'tendbsingle','mysql_monitor','items-config.yaml','engine','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16701,'tendbsingle','mysql_monitor','items-config.yaml','ext3-check','STRING','{\"enable\":true,\"schedule\":\"0 0 16 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16702,'tendbsingle','mysql_monitor','items-config.yaml','ibd-statistic','STRING','{\"enable\":true,\"schedule\":\"0 0 14 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[\"slave\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16703,'tendbsingle','mysql_monitor','items-config.yaml','master-slave-heartbeat','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"master\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16704,'tendbsingle','mysql_monitor','items-config.yaml','mysql-config-diff','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16707,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-report','STRING','{\"enable\":true,\"schedule\":\"0 40 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16706,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-rotate','STRING','{\"enable\":true,\"schedule\":\"0 30 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16705,'tendbsingle','mysql_monitor','items-config.yaml','mysql-connlog-size','STRING','{\"enable\":true,\"schedule\":\"0 0 12 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16709,'tendbsingle','mysql_monitor','items-config.yaml','mysql-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16708,'tendbsingle','mysql_monitor','items-config.yaml','mysql-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16714,'tendbsingle','mysql_monitor','items-config.yaml','mysql-inject','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16713,'tendbsingle','mysql_monitor','items-config.yaml','mysql-lock','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16715,'tendbsingle','mysql_monitor','items-config.yaml','proxy-backend','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16716,'tendbsingle','mysql_monitor','items-config.yaml','proxy-user-list','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"proxy\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16717,'tendbsingle','mysql_monitor','items-config.yaml','rotate-slowlog','STRING','{\"enable\":true,\"schedule\":\"0 55 23 * * *\",\"machine_type\":[\"single\",\"backend\",\"remote\",\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16697,'tendbsingle','mysql_monitor','items-config.yaml','routine-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16718,'tendbsingle','mysql_monitor','items-config.yaml','slave-status','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"backend\",\"remote\"],\"role\":[\"slave\",\"repeater\"]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16712,'tendbsingle','mysql_monitor','items-config.yaml','spider-err-critical','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16710,'tendbsingle','mysql_monitor','items-config.yaml','spider-err-notice','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16711,'tendbsingle','mysql_monitor','items-config.yaml','spider-err-warn','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16720,'tendbsingle','mysql_monitor','items-config.yaml','spider-remote','STRING','{\"enable\":true,\"schedule\":\"@every 1m\",\"machine_type\":[\"spider\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:13','2023-06-30 17:21:13',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16699,'tendbsingle','mysql_monitor','items-config.yaml','trigger-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16698,'tendbsingle','mysql_monitor','items-config.yaml','view-definer','STRING','{\"enable\":true,\"schedule\":\"0 0 15 * * 1\",\"machine_type\":[\"single\",\"backend\",\"remote\"],\"role\":[]}','','MAP',1,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2023-06-30 17:21:12','2023-06-30 17:21:12',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (11726,'tendbsingle','proxyconf','default','conn_log','STRING','true','true|false','ENUM',1,0,1,0,0,NULL,NULL,NULL,-1,NULL,NULL,'2022-09-27 11:52:55','2022-09-27 11:52:55',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (11727,'tendbsingle','proxyconf','default','daemon','STRING','true','true|false','ENUM',1,0,1,0,0,NULL,NULL,NULL,-1,NULL,NULL,'2022-09-27 11:52:55','2022-09-27 11:52:55',0); INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (11728,'tendbsingle','proxyconf','default','event-threads','INT','7','[1,10]','RANGE',1,0,1,0,0,NULL,NULL,NULL,-1,NULL,NULL,'2022-09-27 11:52:55','2022-09-27 11:52:55',0); @@ -1014,4 +1021,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000022_TendisCache_data.up.sql b/dbm-services/common/db-config/assets/migrations/000022_TendisCache_data.up.sql index 53b6440071..7d89f4e055 100644 --- a/dbm-services/common/db-config/assets/migrations/000022_TendisCache_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000022_TendisCache_data.up.sql @@ -24,9 +24,9 @@ -- -- WHERE: namespace='TendisCache' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (60,'TendisCache','dbconf','TendisCache-2.8','DB参数配置','5.8_参数配置','','',0,0,0,'',0,0,0,'5.8_参数配置','2022-08-04 15:28:35','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (49,'TendisCache','dbconf','TendisCache-3.2','DB参数配置','TendisCache-3.2配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'5.8_参数配置','2022-08-02 14:27:14','2023-03-28 21:40:02',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (51,'TendisCache','dbconf','TendisCache-4.0','DB参数配置','TendisCache-4.0配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisCache-4.0配置','2022-08-02 14:27:14','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (60,'TendisCache','dbconf','TendisCache-2.8','DB参数配置','TendisCache-2.8','','',0,0,0,'',0,0,0,'5.8_参数配置','2022-08-04 15:28:35','2023-06-29 10:34:03',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (49,'TendisCache','dbconf','TendisCache-3.2','DB参数配置','TendisCache-3.2','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'5.8_参数配置','2022-08-02 14:27:14','2023-06-29 10:31:00',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (51,'TendisCache','dbconf','TendisCache-4.0','DB参数配置','TendisCache-4.0','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisCache-4.0配置','2022-08-02 14:27:14','2023-06-29 10:31:09',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -38,7 +38,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -96,4 +95,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000023_TendisplusInstance_data.up.sql b/dbm-services/common/db-config/assets/migrations/000023_TendisplusInstance_data.up.sql index d626f83e22..faf668a90e 100644 --- a/dbm-services/common/db-config/assets/migrations/000023_TendisplusInstance_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000023_TendisplusInstance_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='TendisplusInstance' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (63,'TendisplusInstance','redisconf','tendisplus-2.5','Tendisplus参数配置','tendisplus-2.5版本_参数配置','plat,app,cluster','cluster',1,1,0,NULL,0,0,0,'tendisplus-2.5版本_参数配置','2022-08-11 20:22:50','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (63,'TendisplusInstance','redisconf','tendisplus-2.5','Tendisplus参数配置','tendisplus-2.5','plat,app,cluster','cluster',1,1,0,NULL,0,0,0,'tendisplus-2.5版本_参数配置','2022-08-11 20:22:50','2023-06-29 10:33:49',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -116,4 +115,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000024_TendisSSD_data.up.sql b/dbm-services/common/db-config/assets/migrations/000024_TendisSSD_data.up.sql index 9e3daa6dd9..a2bd6ecc42 100644 --- a/dbm-services/common/db-config/assets/migrations/000024_TendisSSD_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000024_TendisSSD_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='TendisSSD' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (50,'TendisSSD','dbconf','TendisSSD-2.8','DB参数配置','TendisSSD-2.8配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisSSD-2.8配置','2022-08-02 14:29:01','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (50,'TendisSSD','dbconf','TendisSSD-2.8','DB参数配置','TendisSSD-2.8','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisSSD-2.8配置','2022-08-02 14:29:01','2023-06-29 10:31:03',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -74,4 +73,3 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000025_TendisX_data.up.sql b/dbm-services/common/db-config/assets/migrations/000025_TendisX_data.up.sql index 569d3b691f..c4116c0d26 100644 --- a/dbm-services/common/db-config/assets/migrations/000025_TendisX_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000025_TendisX_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='TendisX' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (54,'TendisX','dbconf','TendisX-4.0','DB参数配置','TendisX集群(4.0.10)','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisX集群(4.0.10)','2022-08-02 14:29:01','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (54,'TendisX','dbconf','TendisX-4.0','DB参数配置','TendisX-4.0','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'TendisX集群(4.0.10)','2022-08-02 14:29:01','2023-06-29 10:34:12',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -74,4 +73,3 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000026_TwemproxyRedisInstance_data.up.sql b/dbm-services/common/db-config/assets/migrations/000026_TwemproxyRedisInstance_data.up.sql index 0c028d659d..f800ac50ab 100644 --- a/dbm-services/common/db-config/assets/migrations/000026_TwemproxyRedisInstance_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000026_TwemproxyRedisInstance_data.up.sql @@ -24,12 +24,12 @@ -- -- WHERE: namespace='TwemproxyRedisInstance' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (117,'TwemproxyRedisInstance','config','binlogbackup','配置','binlog备份相关的配置','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'binlog备份相关的配置','2022-11-22 08:55:34','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (71,'TwemproxyRedisInstance','config','fullbackup','配置','备份相关的配置','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'备份相关的配置','2022-09-01 17:00:08','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (118,'TwemproxyRedisInstance','config','heartbeat','配置','心跳相关的配置','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'心跳相关的配置','2022-11-22 08:55:34','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (72,'TwemproxyRedisInstance','config','monitor','配置','监控相关的配置','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'监控相关的配置','2022-09-01 17:00:08','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (69,'TwemproxyRedisInstance','dbconf','Redis-6','redis配置','redis6.0的配置文件','plat,app,cluster,host,instance','cluster',1,1,0,'tendisCache',5,365,0,'redis6.0的配置文件','2022-09-01 16:58:02','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (70,'TwemproxyRedisInstance','proxyconf','Twemproxy-latest','redis配置','twemproxy配置文件','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'twemproxy配置文件','2022-09-01 16:59:02','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (117,'TwemproxyRedisInstance','config','binlogbackup','binlog备份相关的配置','binlogbackup','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'binlog备份相关的配置','2022-11-22 08:55:34','2023-06-30 17:29:39',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (71,'TwemproxyRedisInstance','config','fullbackup','全备配置','fullbackup','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'备份相关的配置','2022-09-01 17:00:08','2023-06-30 17:30:00',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (118,'TwemproxyRedisInstance','config','heartbeat','心跳相关的配置','heartbeat','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'心跳相关的配置','2022-11-22 08:55:34','2023-06-30 17:29:36',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (72,'TwemproxyRedisInstance','config','monitor','监控配置','monitor','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'监控相关的配置','2022-09-01 17:00:08','2023-06-30 17:30:03',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (69,'TwemproxyRedisInstance','dbconf','Redis-6','redis配置','Redis-6','plat,app,cluster,host,instance','cluster',1,1,0,'tendisCache',5,365,0,'redis6.0的配置文件','2022-09-01 16:58:02','2023-06-30 17:24:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (70,'TwemproxyRedisInstance','proxyconf','Twemproxy-latest','redis配置','Twemproxy-latest','plat,app,cluster','cluster',1,1,0,'tendisCache',5,365,0,'twemproxy配置文件','2022-09-01 16:59:02','2023-06-30 17:24:36',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -41,7 +41,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -164,4 +163,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000027_TwemproxyTendisplusInstance_data.up.sql b/dbm-services/common/db-config/assets/migrations/000027_TwemproxyTendisplusInstance_data.up.sql index 8b1173a7bd..10d2e38064 100644 --- a/dbm-services/common/db-config/assets/migrations/000027_TwemproxyTendisplusInstance_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000027_TwemproxyTendisplusInstance_data.up.sql @@ -24,10 +24,10 @@ -- -- WHERE: namespace='TwemproxyTendisplusInstance' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (87,'TwemproxyTendisplusInstance','config','backup','配置','备份相关的配置','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'备份相关的配置','2022-09-27 17:48:51','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (88,'TwemproxyTendisplusInstance','config','monitor','配置','监控相关的配置','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'监控相关的配置','2022-09-27 17:49:02','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (85,'TwemproxyTendisplusInstance','dbconf','Tendisplus-2.5','redis配置','Tendisplus-2.5的配置文件','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'Tendisplus-2.5的配置文件','2022-09-27 17:48:42','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (86,'TwemproxyTendisplusInstance','proxyconf','Twemproxy-latest','redis配置','twemproxy配置文件','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'twemproxy配置文件','2022-09-27 17:48:46','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (87,'TwemproxyTendisplusInstance','config','backup','备份相关的配置','backup','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'备份相关的配置','2022-09-27 17:48:51','2023-06-30 17:27:33',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (88,'TwemproxyTendisplusInstance','config','monitor','监控相关的配置','monitor','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'监控相关的配置','2022-09-27 17:49:02','2023-06-30 17:27:28',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (85,'TwemproxyTendisplusInstance','dbconf','Tendisplus-2.5','redis配置','Tendisplus-2.5','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'Tendisplus-2.5的配置文件','2022-09-27 17:48:42','2023-06-29 10:33:39',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (86,'TwemproxyTendisplusInstance','proxyconf','Twemproxy-latest','redis配置','Twemproxy-latest','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'twemproxy配置文件','2022-09-27 17:48:46','2023-06-29 10:37:01',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -39,7 +39,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -133,4 +132,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000028_TwemproxyTendisSSDInstance_data.up.sql b/dbm-services/common/db-config/assets/migrations/000028_TwemproxyTendisSSDInstance_data.up.sql index 3f7e09cae9..86a1e4986b 100644 --- a/dbm-services/common/db-config/assets/migrations/000028_TwemproxyTendisSSDInstance_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000028_TwemproxyTendisSSDInstance_data.up.sql @@ -24,8 +24,8 @@ -- -- WHERE: namespace='TwemproxyTendisSSDInstance' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (174,'TwemproxyTendisSSDInstance','dbconf','TendisSSD-1.2','redis配置','TendisSSD的配置文件','plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'TendisSSD的配置文件','2023-03-01 10:27:53','2023-03-22 12:08:50',''); -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (175,'TwemproxyTendisSSDInstance','dbconf','TendisSSD-1.3','redis配置','TendisSSD的配置文件','plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'TendisSSD的配置文件','2023-03-01 10:27:53','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (174,'TwemproxyTendisSSDInstance','dbconf','TendisSSD-1.2','redis配置','TendisSSD-1.2','plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'TendisSSD的配置文件','2023-03-01 10:27:53','2023-06-29 10:35:22',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (175,'TwemproxyTendisSSDInstance','dbconf','TendisSSD-1.3','redis配置','TendisSSD-1.3','plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'TendisSSD的配置文件','2023-03-01 10:27:53','2023-06-29 10:35:27',''); INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (176,'TwemproxyTendisSSDInstance','proxyconf','Twemproxy-latest','redis配置','twemproxy配置文件','plat,app,module,cluster','cluster',1,1,0,'Tendisplus',5,365,0,'twemproxy配置文件','2023-03-01 10:27:53','2023-03-22 12:08:50',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; @@ -38,7 +38,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -222,4 +221,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000029_pulsar_data.up.sql b/dbm-services/common/db-config/assets/migrations/000029_pulsar_data.up.sql index 6d78f6bcf2..a933b5ad22 100644 --- a/dbm-services/common/db-config/assets/migrations/000029_pulsar_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000029_pulsar_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='pulsar' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (142,'pulsar','dbconf','2.10.1','pulsar集群配置','pulsar集群配置','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'pulsar集群配置','2023-01-13 10:37:29','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (142,'pulsar','dbconf','2.10.1','pulsar集群配置','pulsar-2.10','plat,app,cluster','cluster',1,1,0,NULL,5,365,0,'pulsar集群配置','2023-01-13 10:37:29','2023-06-29 10:36:17',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -547,4 +546,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000030_influxdb_data.up.sql b/dbm-services/common/db-config/assets/migrations/000030_influxdb_data.up.sql index 163b343a46..41a76d8792 100644 --- a/dbm-services/common/db-config/assets/migrations/000030_influxdb_data.up.sql +++ b/dbm-services/common/db-config/assets/migrations/000030_influxdb_data.up.sql @@ -24,7 +24,7 @@ -- -- WHERE: namespace='influxdb' -INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (149,'influxdb','dbconf','1.8.4','influxdb配置','influxdb配置文件','plat,app,instance','instance',1,1,0,'NULL',5,365,0,'influxdb配置文件','2022-09-20 15:17:36','2023-03-22 12:08:50',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (149,'influxdb','dbconf','1.8.4','influxdb配置','influxdb-1.8','plat,app,instance','instance',1,1,0,'NULL',5,365,0,'influxdb配置文件','2022-09-20 15:17:36','2023-06-29 10:36:04',''); /*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; /*!50112 PREPARE s FROM @disable_bulk_load */; /*!50112 EXECUTE s */; @@ -36,7 +36,6 @@ INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 -- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) -- -- Host: localhost Database: bk_dbconfig @@ -75,4 +74,3 @@ INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, ` /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2023-06-26 14:30:03 diff --git a/dbm-services/common/db-config/assets/migrations/000031_riak_data.down.sql b/dbm-services/common/db-config/assets/migrations/000031_riak_data.down.sql new file mode 100644 index 0000000000..91f36bce00 --- /dev/null +++ b/dbm-services/common/db-config/assets/migrations/000031_riak_data.down.sql @@ -0,0 +1,2 @@ +DELETE FROM tb_config_file_def WHERE namespace='riak'; +DELETE FROM tb_config_name_def WHERE namespace='riak' AND (flag_encrypt!=1 or value_default like '{{%'); diff --git a/dbm-services/common/db-config/assets/migrations/000031_riak_data.up.sql b/dbm-services/common/db-config/assets/migrations/000031_riak_data.up.sql new file mode 100644 index 0000000000..27dd8e932c --- /dev/null +++ b/dbm-services/common/db-config/assets/migrations/000031_riak_data.up.sql @@ -0,0 +1,109 @@ +-- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) +-- +-- Host: localhost Database: bk_dbconfig +-- ------------------------------------------------------ +-- Server version 5.7.20-tmysql-3.3-log +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/*!50717 SELECT COUNT(*) INTO @rocksdb_has_p_s_session_variables FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'performance_schema' AND TABLE_NAME = 'session_variables' */; +/*!50717 SET @rocksdb_get_is_supported = IF (@rocksdb_has_p_s_session_variables, 'SELECT COUNT(*) INTO @rocksdb_is_supported FROM performance_schema.session_variables WHERE VARIABLE_NAME=\'rocksdb_bulk_load\'', 'SELECT 0') */; +/*!50717 PREPARE s FROM @rocksdb_get_is_supported */; +/*!50717 EXECUTE s */; +/*!50717 DEALLOCATE PREPARE s */; +/*!50717 SET @rocksdb_enable_bulk_load = IF (@rocksdb_is_supported, 'SET SESSION rocksdb_bulk_load = 1', 'SET @rocksdb_dummy_bulk_load = 0') */; +/*!50717 PREPARE s FROM @rocksdb_enable_bulk_load */; +/*!50717 EXECUTE s */; +/*!50717 DEALLOCATE PREPARE s */; + +-- +-- Dumping data for table `tb_config_file_def` +-- +-- WHERE: namespace='riak' + +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (206,'riak','dbconf','riak-2.2-legs','riak-2.2','riak-2.2-legs','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-30 16:01:57',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (203,'riak','dbconf','riak-2.2-mhs','riak-2.2','riak-2.2-mhs','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-30 16:02:24',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (209,'riak','dbconf','riak-2.2-mixed','riak-2.2','riak-2.2-mixedt','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-30 16:03:19',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (207,'riak','dbconf','riak-2.2-pp','riak-2.2','riak-2.2-pp','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-30 16:02:01',''); +INSERT INTO `tb_config_file_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_type_lc`, `conf_file_lc`, `level_names`, `level_versioned`, `conf_name_validate`, `conf_value_validate`, `value_type_strict`, `namespace_info`, `version_keep_limit`, `version_keep_days`, `conf_name_order`, `description`, `created_at`, `updated_at`, `updated_by`) VALUES (208,'riak','dbconf','riak-2.2-test','riak-2.2','riak-2.2-test','plat,app,cluster','cluster',1,1,0,'Tendisplus',5,365,0,NULL,'2023-03-30 19:17:40','2023-06-30 16:02:04',''); +/*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; +/*!50112 PREPARE s FROM @disable_bulk_load */; +/*!50112 EXECUTE s */; +/*!50112 DEALLOCATE PREPARE s */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) +-- +-- Host: localhost Database: bk_dbconfig +-- ------------------------------------------------------ +-- Server version 5.7.20-tmysql-3.3-log +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/*!50717 SELECT COUNT(*) INTO @rocksdb_has_p_s_session_variables FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'performance_schema' AND TABLE_NAME = 'session_variables' */; +/*!50717 SET @rocksdb_get_is_supported = IF (@rocksdb_has_p_s_session_variables, 'SELECT COUNT(*) INTO @rocksdb_is_supported FROM performance_schema.session_variables WHERE VARIABLE_NAME=\'rocksdb_bulk_load\'', 'SELECT 0') */; +/*!50717 PREPARE s FROM @rocksdb_get_is_supported */; +/*!50717 EXECUTE s */; +/*!50717 DEALLOCATE PREPARE s */; +/*!50717 SET @rocksdb_enable_bulk_load = IF (@rocksdb_is_supported, 'SET SESSION rocksdb_bulk_load = 1', 'SET @rocksdb_dummy_bulk_load = 0') */; +/*!50717 PREPARE s FROM @rocksdb_enable_bulk_load */; +/*!50717 EXECUTE s */; +/*!50717 DEALLOCATE PREPARE s */; + +-- +-- Dumping data for table `tb_config_name_def` +-- +-- WHERE: namespace='riak' AND (flag_encrypt!=1 or value_default like '{{%') + +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16498,'riak','dbconf','riak-2.2-legs','bucket_types','STRING','','','STRING',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:59:34',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16499,'riak','dbconf','riak-2.2-legs','distributed_cookie','STRING','legsriak','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:53',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16494,'riak','dbconf','riak-2.2-legs','leveldb_expiration','STRING','on','off | on','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:59:54',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16495,'riak','dbconf','riak-2.2-legs','leveldb_expiration_mode','STRING','whole_file','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:58',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16496,'riak','dbconf','riak-2.2-legs','leveldb_expiration_retention_time','STRING','365d','unlimited | 365d','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:00:03',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16497,'riak','dbconf','riak-2.2-legs','ring_size','INT','256','[256,256]','RANGE',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:47:01',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16491,'riak','dbconf','riak-2.2-mhs','bucket_types','STRING','','','STRING',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:59:18',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16492,'riak','dbconf','riak-2.2-mhs','distributed_cookie','STRING','mhsriak','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:53',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16487,'riak','dbconf','riak-2.2-mhs','leveldb_expiration','STRING','off','off | on','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:50',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16488,'riak','dbconf','riak-2.2-mhs','leveldb_expiration_mode','STRING','whole_file','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:58',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16489,'riak','dbconf','riak-2.2-mhs','leveldb_expiration_retention_time','STRING','unlimited','unlimited | 365d','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:37',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16490,'riak','dbconf','riak-2.2-mhs','ring_size','INT','256','[256,256]','RANGE',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:47:01',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16516,'riak','dbconf','riak-2.2-mixied','bucket_types','STRING','player_preferences','','STRING',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:35',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16517,'riak','dbconf','riak-2.2-mixied','distributed_cookie','STRING','mixedriak','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:43',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16512,'riak','dbconf','riak-2.2-mixied','leveldb_expiration','STRING','off','off | on','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:29',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16513,'riak','dbconf','riak-2.2-mixied','leveldb_expiration_mode','STRING','whole_file','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:31',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16514,'riak','dbconf','riak-2.2-mixied','leveldb_expiration_retention_time','STRING','unlimited','unlimited | 365d','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:32',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16515,'riak','dbconf','riak-2.2-mixied','ring_size','INT','256','[256,256]','RANGE',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 16:03:34',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16504,'riak','dbconf','riak-2.2-pp','bucket_types','STRING','player_preferences','','STRING',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:49:55',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16505,'riak','dbconf','riak-2.2-pp','distributed_cookie','STRING','ppriak','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:53',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16500,'riak','dbconf','riak-2.2-pp','leveldb_expiration','STRING','off','off | on','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:50',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16501,'riak','dbconf','riak-2.2-pp','leveldb_expiration_mode','STRING','whole_file','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:58',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16502,'riak','dbconf','riak-2.2-pp','leveldb_expiration_retention_time','STRING','unlimited','unlimited | 365d','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:37',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16503,'riak','dbconf','riak-2.2-pp','ring_size','INT','256','[256,256]','RANGE',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:47:01',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16510,'riak','dbconf','riak-2.2-test','bucket_types','STRING','player_preferences','','STRING',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:49:55',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16511,'riak','dbconf','riak-2.2-test','distributed_cookie','STRING','testriak','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:53',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16506,'riak','dbconf','riak-2.2-test','leveldb_expiration','STRING','off','off | on','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:50',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16507,'riak','dbconf','riak-2.2-test','leveldb_expiration_mode','STRING','whole_file','','',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:58',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16508,'riak','dbconf','riak-2.2-test','leveldb_expiration_retention_time','STRING','unlimited','unlimited | 365d','ENUM',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:46:37',0); +INSERT INTO `tb_config_name_def` (`id`, `namespace`, `conf_type`, `conf_file`, `conf_name`, `value_type`, `value_default`, `value_allowed`, `value_type_sub`, `flag_status`, `flag_disable`, `flag_locked`, `flag_encrypt`, `need_restart`, `value_formula`, `extra_info`, `conf_name_lc`, `order_index`, `since_version`, `description`, `created_at`, `updated_at`, `stage`) VALUES (16509,'riak','dbconf','riak-2.2-test','ring_size','INT','256','[256,256]','RANGE',2,0,0,0,1,NULL,NULL,NULL,-1,NULL,NULL,'2022-04-25 10:00:47','2023-06-30 15:47:01',0); +/*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */; +/*!50112 PREPARE s FROM @disable_bulk_load */; +/*!50112 EXECUTE s */; +/*!50112 DEALLOCATE PREPARE s */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + From 21081042d58e1502aae086ae1626ee0b0cd2fc3c Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Fri, 30 Jun 2023 20:08:15 +0800 Subject: [PATCH 071/476] =?UTF-8?q?feat(fronent):=20=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=89=A9=E7=BC=A9=E5=AE=B9=E6=8E=A5=E5=85=A5=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=B1=A0=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/.gitignore | 1 + .../components/ResourcePoolSelector.vue | 6 +- .../cluster-common/es-host-replace/Index.vue | 19 +- .../components/ResourcePoolSelector.vue | 11 +- .../cluster-common/host-expansion/Index.vue | 4 +- .../components/ResourcePoolSelector.vue | 6 +- .../cluster-common/host-replace/Index.vue | 22 +- .../host-replace/components/HostSelector.vue | 4 +- .../components/ResourcePoolSelector.vue | 47 ++- .../cluster-common/host-shrink/Index.vue | 4 +- dbm-ui/frontend/src/services/dbResource.ts | 7 +- .../model/influxdb/influxdbInstance.ts | 16 +- .../views/es-manage/common/replace/Index.vue | 5 +- .../hdfs-manage/common/replace/Index.vue | 7 +- .../components/replace/Index.vue | 241 ++++++++----- .../replace/components/RenderNodeHostList.vue | 330 ------------------ .../kafka-manage/common/replace/Index.vue | 4 +- 17 files changed, 264 insertions(+), 470 deletions(-) delete mode 100644 dbm-ui/frontend/src/views/influxdb-manage/components/replace/components/RenderNodeHostList.vue diff --git a/dbm-ui/frontend/.gitignore b/dbm-ui/frontend/.gitignore index 8d0bd1959d..05e0b3dec8 100644 --- a/dbm-ui/frontend/.gitignore +++ b/dbm-ui/frontend/.gitignore @@ -28,5 +28,6 @@ build.yml public/.DS_Store *.bak +*.bak.* .codecc .vscode \ No newline at end of file diff --git a/dbm-ui/frontend/src/components/cluster-common/es-host-expansion/components/ResourcePoolSelector.vue b/dbm-ui/frontend/src/components/cluster-common/es-host-expansion/components/ResourcePoolSelector.vue index dd71da9023..6b8003dc59 100644 --- a/dbm-ui/frontend/src/components/cluster-common/es-host-expansion/components/ResourcePoolSelector.vue +++ b/dbm-ui/frontend/src/components/cluster-common/es-host-expansion/components/ResourcePoolSelector.vue @@ -125,9 +125,9 @@ role: props.data.role, }, ], - onSuccess(recommendSpecData) { - if (recommendSpecData) { - specId.value = recommendSpecData.spec_id; + onSuccess(recommendSpecList) { + if (recommendSpecList.length > 0) { + specId.value = recommendSpecList[0].spec_id; } }, }); diff --git a/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue b/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue index fc60a9956a..76ea734ef2 100644 --- a/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue +++ b/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue @@ -12,7 +12,7 @@ --> diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue new file mode 100644 index 0000000000..c95125843e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue @@ -0,0 +1,334 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/list/components/BatchEdit.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/BatchEdit.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/BatchEdit.vue rename to dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/BatchEdit.vue diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue new file mode 100644 index 0000000000..bedd7e7651 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue @@ -0,0 +1,481 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Index.vue new file mode 100644 index 0000000000..8577d530a6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Index.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentCapacity.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentCapacity.vue new file mode 100644 index 0000000000..2c9b3f75d3 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentCapacity.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentSpec.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentSpec.vue new file mode 100644 index 0000000000..b40019f8b8 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderCurrentSpec.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderSpecifyVersion.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderSpecifyVersion.vue new file mode 100644 index 0000000000..e4dc24e45e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderSpecifyVersion.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue new file mode 100644 index 0000000000..c415007df3 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue new file mode 100644 index 0000000000..b01469565b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue new file mode 100644 index 0000000000..b738e74ddd --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue @@ -0,0 +1,207 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue new file mode 100644 index 0000000000..d2567ba05e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/Index.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/Index.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/Index.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/Index.vue diff --git a/dbm-ui/frontend/src/views/redis/details/BaseInfo.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/details/BaseInfo.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/details/BaseInfo.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/details/BaseInfo.vue diff --git a/dbm-ui/frontend/src/views/redis/details/DetailsRedis.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/details/DetailsRedis.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/details/DetailsRedis.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/details/DetailsRedis.vue diff --git a/dbm-ui/frontend/src/views/redis/hooks/useRedisData.ts b/dbm-ui/frontend/src/views/redis/cluster-manage/hooks/useRedisData.ts similarity index 96% rename from dbm-ui/frontend/src/views/redis/hooks/useRedisData.ts rename to dbm-ui/frontend/src/views/redis/cluster-manage/hooks/useRedisData.ts index 89130e5a14..8cef8f1e86 100644 --- a/dbm-ui/frontend/src/views/redis/hooks/useRedisData.ts +++ b/dbm-ui/frontend/src/views/redis/cluster-manage/hooks/useRedisData.ts @@ -20,7 +20,7 @@ import { DBTypes } from '@common/const'; import { getSearchSelectorParams } from '@utils'; -import type { RedisState } from '../common/types'; +import type { RedisState } from '../../common/types'; /** * 处理 redis 列表数据 @@ -44,6 +44,7 @@ export const useRedisData = (state: RedisState) => { state.isLoading = isLoading; return getResources(DBTypes.REDIS, params) .then((res) => { + console.log('getResources>>', res); state.pagination.count = res.count; state.data = res.results; state.isAnomalies = false; diff --git a/dbm-ui/frontend/src/views/redis/list/List.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/List.vue similarity index 99% rename from dbm-ui/frontend/src/views/redis/list/List.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/List.vue index dce53665fd..5be1f57963 100644 --- a/dbm-ui/frontend/src/views/redis/list/List.vue +++ b/dbm-ui/frontend/src/views/redis/cluster-manage/list/List.vue @@ -140,11 +140,12 @@ import DbStatus from '@components/db-status/index.vue'; import RenderInstances from '@components/render-instances/RenderInstances.vue'; + import type { RedisState } from '@views/redis/common/types'; + import { isRecentDays, messageWarn, random } from '@utils'; import { useTimeoutPoll } from '@vueuse/core'; - import type { RedisState } from '../common/types'; import { useRedisData } from '../hooks/useRedisData'; import RedisBackup from './components/Backup.vue'; diff --git a/dbm-ui/frontend/src/views/redis/list/components/Backup.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/Backup.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/Backup.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/Backup.vue diff --git a/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/BatchEdit.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/BatchEdit.vue new file mode 100644 index 0000000000..df3dba4dea --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/BatchEdit.vue @@ -0,0 +1,175 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/list/components/BatchEditKeys.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/BatchEditKeys.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/BatchEditKeys.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/BatchEditKeys.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/ClusterPassword.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/ClusterPassword.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/ClusterPassword.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/ClusterPassword.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/DeleteKeys.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/DeleteKeys.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/DeleteKeys.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/DeleteKeys.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/ExtractKeys.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/ExtractKeys.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/ExtractKeys.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/ExtractKeys.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/OperationStatusTips.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/OperationStatusTips.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/OperationStatusTips.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/OperationStatusTips.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/Purge.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/Purge.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/Purge.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/Purge.vue diff --git a/dbm-ui/frontend/src/views/redis/list/components/RenderOperationTag.vue b/dbm-ui/frontend/src/views/redis/cluster-manage/list/components/RenderOperationTag.vue similarity index 100% rename from dbm-ui/frontend/src/views/redis/list/components/RenderOperationTag.vue rename to dbm-ui/frontend/src/views/redis/cluster-manage/list/components/RenderOperationTag.vue diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue new file mode 100644 index 0000000000..81910dd103 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue @@ -0,0 +1,595 @@ + + + + + + + +@/services/model/redis/redis diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/CollapseMini.vue b/dbm-ui/frontend/src/views/redis/common/cluster-selector/CollapseMini.vue new file mode 100644 index 0000000000..eae56c4625 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/CollapseMini.vue @@ -0,0 +1,98 @@ + + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/types.ts b/dbm-ui/frontend/src/views/redis/common/cluster-selector/types.ts new file mode 100644 index 0000000000..05eb3a95c9 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/types.ts @@ -0,0 +1,30 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import type { IPagination } from '@hooks'; + +import RedisModel from '@/services/model/redis/redis'; + +export type ClusterSelectorResult = Record> + +export type ClusterSelectorState = { + curSelectdDataTab: string, + activeTab: string, + isLoading: boolean, + search: string, + pagination: IPagination, + tableData: RedisModel[], + selected: ClusterSelectorResult, + isSelectedAll: boolean + isAnomalies: boolean +}; diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts b/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts new file mode 100644 index 0000000000..e48b487330 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts @@ -0,0 +1,71 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +// import { getResources } from '@services/clusters'; +import { getModules } from '@services/common'; +import { listClusterList } from '@services/redis/toolbox'; + +// import type { ResourceItem } from '@services/types/clusters'; +import { useGlobalBizs } from '@stores'; + +// import { DBTypes } from '@common/const'; +// import { getSearchSelectorParams } from '@utils'; +import type { ClusterSelectorState } from './types'; + +/** + * 处理集群列表数据 + */ +export function useClusterData(state: ClusterSelectorState) { + /** + * 获取列表 + */ + const fetchResources = () => { + state.isLoading = true; + return listClusterList() + .then((res) => { + state.pagination.count = res.length; + state.tableData = res; + state.isAnomalies = false; + }) + .catch(() => { + state.tableData = []; + state.pagination.count = 0; + state.isAnomalies = true; + }) + .finally(() => { + state.isLoading = false; + }); + }; + + /** + * change page + */ + const handleChangePage = (value: number) => { + state.pagination.current = value; + return fetchResources(); + }; + + /** + * change limit + */ + const handeChangeLimit = (value: number) => { + state.pagination.limit = value; + return handleChangePage(1); + }; + + return { + fetchResources, + handleChangePage, + handeChangeLimit, + }; +} diff --git a/dbm-ui/frontend/src/views/redis/common/edit-field/ClusterWithRelateCluster.vue b/dbm-ui/frontend/src/views/redis/common/edit-field/ClusterWithRelateCluster.vue new file mode 100644 index 0000000000..4f10afb2b2 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit-field/ClusterWithRelateCluster.vue @@ -0,0 +1,452 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit-field/DbName.vue b/dbm-ui/frontend/src/views/redis/common/edit-field/DbName.vue new file mode 100644 index 0000000000..8f12f69731 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit-field/DbName.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit-field/TableName.vue b/dbm-ui/frontend/src/views/redis/common/edit-field/TableName.vue new file mode 100644 index 0000000000..06be0006ef --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit-field/TableName.vue @@ -0,0 +1,154 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit/DateTime.vue b/dbm-ui/frontend/src/views/redis/common/edit/DateTime.vue new file mode 100644 index 0000000000..de9088ff3f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit/DateTime.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit/Input.vue b/dbm-ui/frontend/src/views/redis/common/edit/Input.vue new file mode 100644 index 0000000000..de7c9e5828 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit/Input.vue @@ -0,0 +1,340 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit/Select.vue b/dbm-ui/frontend/src/views/redis/common/edit/Select.vue new file mode 100644 index 0000000000..a2b53bfa67 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit/Select.vue @@ -0,0 +1,411 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit/Tag.vue b/dbm-ui/frontend/src/views/redis/common/edit/Tag.vue new file mode 100644 index 0000000000..15ea6c78d5 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit/Tag.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/edit/hooks/useValidtor.ts b/dbm-ui/frontend/src/views/redis/common/edit/hooks/useValidtor.ts new file mode 100644 index 0000000000..009fabe999 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/edit/hooks/useValidtor.ts @@ -0,0 +1,90 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { + reactive, + toRefs, +} from 'vue'; + +export type Rules = Array<{ + validator: (value: any) => boolean | Promise, + message: string | (() => string) +}> + +const getRuleMessage = (rule: Rules[0]) => { + if (typeof rule.message === 'function') { + return rule.message(); + } + return rule.message; +}; + +export default function (rules: Rules|undefined) { + const state = reactive({ + loading: false, + error: false, + message: '', + }); + + const validator = (targetValue: any) => { + state.error = false, + state.message = ''; + if (!rules) { + return Promise.resolve(true); + } + const run = (() => { + let stepIndex = -1; + return (): Promise => { + stepIndex = stepIndex + 1; + if (stepIndex >= rules.length) { + return Promise.resolve(true); + } + const rule = rules[stepIndex]; + return Promise.resolve() + .then(() => { + const result = rule.validator(targetValue); + // 异步验证 + if (typeof result !== 'boolean' + && typeof result.then === 'function') { + return result.then((data: boolean) => { + // 异步验证结果为 false + if (data === false) { + return Promise.reject(getRuleMessage(rule)); + } + }).then(() => run(), () => { + state.error = true; + const message = getRuleMessage(rule); + state.message = message; + return Promise.reject(message); + }); + } + // 验证失败 + if (!result) { + state.error = true; + const message = getRuleMessage(rule); + state.message = message; + return Promise.reject(message); + } + // 下一步 + return run(); + }); + }; + })(); + + return run(); + }; + + return { + ...toRefs(state), + validator, + }; +} diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue new file mode 100644 index 0000000000..ee4c638f35 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue @@ -0,0 +1,165 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/common/tableSettings.ts b/dbm-ui/frontend/src/views/redis/common/instance-selector/common/tableSettings.ts new file mode 100644 index 0000000000..766de81814 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/common/tableSettings.ts @@ -0,0 +1,69 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { t } from '@locales/index'; + +import type { TableProps } from '@/types/bkui-vue'; + +const getSettings = (role?: string) => ({ + fields: [ + { + label: role ? role.charAt(0).toUpperCase() + role.slice(1) : t('实例'), + field: 'instance_address', + disabled: true, + }, + { + label: t('角色'), + field: 'role', + }, + { + label: t('实例状态'), + field: 'status', + }, + { + label: t('云区域'), + field: 'cloud_area', + }, + { + label: t('Agent状态'), + field: 'alive', + }, + { + label: t('主机名称'), + field: 'host_name', + }, + { + label: t('OS名称'), + field: 'os_name', + }, + { + label: t('所属云厂商'), + field: 'cloud_vendor', + }, + { + label: t('OS类型'), + field: 'os_type', + }, + { + label: t('主机ID'), + field: 'host_id', + }, + { + label: 'Agent ID', + field: 'agent_id', + }, + ], + checked: ['instance_address', 'role', 'cloud_area', 'alive', 'host_name'], +} as TableProps['settings']); + +export default getSettings; diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/common/utils.ts b/dbm-ui/frontend/src/views/redis/common/instance-selector/common/utils.ts new file mode 100644 index 0000000000..73d583ce2b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/common/utils.ts @@ -0,0 +1,19 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { t } from '@locales/index'; + +export const textMap = { + idleHosts: t('Redis_业务空闲机'), + manualInput: t('手动输入'), +}; diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/CollapseMini.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/CollapseMini.vue new file mode 100644 index 0000000000..600cb847c2 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/CollapseMini.vue @@ -0,0 +1,94 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PanelTab.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PanelTab.vue new file mode 100644 index 0000000000..a7fb966f5e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PanelTab.vue @@ -0,0 +1,81 @@ + + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue new file mode 100644 index 0000000000..a507d246f6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue @@ -0,0 +1,211 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue new file mode 100644 index 0000000000..63f547ea45 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue @@ -0,0 +1,259 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue new file mode 100644 index 0000000000..1701beae54 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue @@ -0,0 +1,299 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue new file mode 100644 index 0000000000..9fb3298a58 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue @@ -0,0 +1,247 @@ + + + + + +@/services/model/redis/redis diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue new file mode 100644 index 0000000000..8db68465ac --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue @@ -0,0 +1,378 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/render-table/HeadColumn.vue b/dbm-ui/frontend/src/views/redis/common/render-table/HeadColumn.vue new file mode 100644 index 0000000000..67c850aff8 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/render-table/HeadColumn.vue @@ -0,0 +1,78 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/render-table/Index.vue b/dbm-ui/frontend/src/views/redis/common/render-table/Index.vue new file mode 100644 index 0000000000..9843b8f089 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/render-table/Index.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/render-table/hooks/useColumnResize.ts b/dbm-ui/frontend/src/views/redis/common/render-table/hooks/useColumnResize.ts new file mode 100644 index 0000000000..189ce05a4e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/render-table/hooks/useColumnResize.ts @@ -0,0 +1,150 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import _ from 'lodash'; +import { + onBeforeUnmount, + onMounted, + type Ref, + ref, +} from 'vue'; + +export default function (tableRef: Ref, tableColumnResizeRef: Ref) { + let dragable = false; + + const dragging = ref(false); + const dragState = ref({} as any); + + const initColumnWidth = () => { + setTimeout(() => { + const tableEl = tableRef.value; + tableEl.querySelectorAll('th').forEach((columnEl) => { + const { + width, + } = columnEl.getBoundingClientRect(); + const renderWidth = Math.max(parseInt(columnEl.getAttribute('data-minwidth') || '', 10), width); + // eslint-disable-next-line no-param-reassign + columnEl.style.width = `${renderWidth}px`; + }); + }); + }; + + const handleMouseDown = ( + event: MouseEvent, + payload: { + columnKey: string, + minWidth: number + }, + ) => { + if (!dragable) { + return; + } + const { + columnKey, + minWidth = 100, + } = payload; + dragging.value = true; + + const tableEl = tableRef.value; + const tableLeft = tableEl.getBoundingClientRect().left; + const columnEl = tableEl.querySelector(`th.column-${columnKey}`) as HTMLElement; + const columnRect = columnEl.getBoundingClientRect(); + const minLeft = columnRect.left - tableLeft + 30; + + dragState.value = { + startMouseLeft: event.clientX, + startLeft: columnRect.right - tableLeft, + startColumnLeft: columnRect.left - tableLeft, + tableLeft, + }; + const resizeProxy = tableColumnResizeRef.value; + resizeProxy.style.display = 'block'; + resizeProxy.style.left = `${dragState.value.startLeft}px`; + + document.onselectstart = function () { + return false; + }; + document.ondragstart = function () { + return false; + }; + + const handleMouseMove = (event: MouseEvent) => { + const deltaLeft = event.clientX - (dragState.value).startMouseLeft; + const proxyLeft = (dragState.value).startLeft + deltaLeft; + resizeProxy.style.display = 'block'; + resizeProxy.style.left = `${Math.max(minLeft, proxyLeft)}px`; + }; + + const handleMouseUp = () => { + if (dragging.value) { + const { startColumnLeft } = dragState.value; + const finalLeft = Number.parseInt(resizeProxy.style.left, 10); + const columnWidth = Math.max(finalLeft - startColumnLeft, minWidth); + + columnEl.style.width = `${columnWidth}px`; + resizeProxy.style.display = 'none'; + document.body.style.cursor = ''; + dragging.value = false; + dragState.value = {}; + } + dragable = false; + + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + document.onselectstart = null; + document.ondragstart = null; + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + }; + + const handleMouseMove = (event: MouseEvent) => { + const target = (event.target as Element).closest('th') as Element; + + const rect = target.getBoundingClientRect(); + + const bodyStyle = document.body.style; + if (rect.width > 12 && rect.right - event.pageX < 8) { + bodyStyle.cursor = 'col-resize'; + dragable = true; + } else if (!dragging.value) { + bodyStyle.cursor = ''; + dragable = false; + } + }; + + const handleOuterMousemove = _.throttle((event) => { + let i = event.composedPath().length - 1; + while (i >= 0) { + if (event.composedPath()[i].id === 'mysqlToolRenderTable') { + return; + } + i = i - 1; + } + document.body.style.cursor = ''; + }, 500); + + onMounted(() => { + document.addEventListener('mousemove', handleOuterMousemove); + }); + + onBeforeUnmount(() => { + document.removeEventListener('mousemove', handleOuterMousemove); + }); + return { + initColumnWidth, + handleMouseDown, + handleMouseMove, + }; +} diff --git a/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue b/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue new file mode 100644 index 0000000000..2e04d16e3b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/utils/index.ts b/dbm-ui/frontend/src/views/redis/common/utils/index.ts new file mode 100644 index 0000000000..e891c2fc90 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/utils/index.ts @@ -0,0 +1,46 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { queryClustersInfo } from '@services/redis/toolbox'; +import { getVersions } from '@services/versionFiles'; + +import { ClusterTypes } from '@common/const'; + +// 根据关键字查询集群信息 +export const getClusterInfo = async (domain: string | string[]) => await queryClustersInfo({ + keywords: Array.isArray(domain) ? domain : [domain], + role: 'proxy', +}).catch((e) => { + console.error('queryClustersInfo error: ', e); + return null; +}); + +// 获取 redis 版本信息 +export const getRedisVersions = async () => { + const arr = await getVersions({ query_key: ClusterTypes.TWEMPROXY_REDIS_INSTANCE }) + .catch((e) => { + console.error('query redis version failed: ', e); + return null; + }); + if (arr) { + return arr.map(item => ({ + id: item, + name: item, + })); + } + return null; +}; + + +// 首字母大写 +export const firstLetterToUpper = (str: string) => str.charAt(0).toUpperCase() + str.slice(1); diff --git a/dbm-ui/frontend/src/views/redis/db-replace/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue new file mode 100644 index 0000000000..ac63bc635f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue @@ -0,0 +1,401 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue new file mode 100644 index 0000000000..1550fa9e8c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderCluster.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderCluster.vue new file mode 100644 index 0000000000..d52ca4aa29 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderCluster.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderHost.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderHost.vue new file mode 100644 index 0000000000..fbc9cfdd47 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderHost.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderRole.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderRole.vue new file mode 100644 index 0000000000..9084f51063 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderRole.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue new file mode 100644 index 0000000000..9e98728f7d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue new file mode 100644 index 0000000000..a0344c03c2 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue @@ -0,0 +1,167 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page2/Index.vue new file mode 100644 index 0000000000..a920775a33 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue new file mode 100644 index 0000000000..8929184721 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue @@ -0,0 +1,299 @@ + + + + + + + +@/services/model/redis/redis diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Index.vue new file mode 100644 index 0000000000..932cd25bb8 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Index.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderNodeType.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderNodeType.vue new file mode 100644 index 0000000000..040ca89f2c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderNodeType.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue new file mode 100644 index 0000000000..c18b2320fd --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSwitchMode.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSwitchMode.vue new file mode 100644 index 0000000000..3b34b3590f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSwitchMode.vue @@ -0,0 +1,93 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetCluster.vue new file mode 100644 index 0000000000..efe74dec5d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetCluster.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetNumber.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetNumber.vue new file mode 100644 index 0000000000..b2fb1d3fc1 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderTargetNumber.vue @@ -0,0 +1,76 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue new file mode 100644 index 0000000000..167686606b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue @@ -0,0 +1,172 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page2/Index.vue new file mode 100644 index 0000000000..2da54e344e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue new file mode 100644 index 0000000000..3e4f893178 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue @@ -0,0 +1,298 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Index.vue new file mode 100644 index 0000000000..8217b5649c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Index.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderNodeType.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderNodeType.vue new file mode 100644 index 0000000000..c04132b64f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderNodeType.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderSpec.vue new file mode 100644 index 0000000000..673bfe29b0 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderSpec.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetCluster.vue new file mode 100644 index 0000000000..633f107a3d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetCluster.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue new file mode 100644 index 0000000000..5edcbe034b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue @@ -0,0 +1,62 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue new file mode 100644 index 0000000000..e03b94c4ba --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue @@ -0,0 +1,157 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue new file mode 100644 index 0000000000..a09e5514da --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecSelect.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecSelect.vue new file mode 100644 index 0000000000..bd47c670e6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecSelect.vue @@ -0,0 +1,425 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page2/Index.vue new file mode 100644 index 0000000000..1bb70d7c20 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/routes.ts b/dbm-ui/frontend/src/views/redis/routes.ts index a3f54c4d1f..24d569fe72 100644 --- a/dbm-ui/frontend/src/views/redis/routes.ts +++ b/dbm-ui/frontend/src/views/redis/routes.ts @@ -17,6 +17,60 @@ import { MainViewRouteNames } from '@views/main-views/common/const'; import { t } from '@locales/index'; +/** + * 工具箱 routes + */ +export const toolboxRoutes: RouteRecordRaw[] = [ + { + name: 'RedisCapacityChange', + path: '/database/:bizId(\\d+)/redis-toolbox/capacity-change/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: '集群容量变更', // TODO: I18n + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/capacity-change/Index.vue'), + }, + { + name: 'RedisProxyScaleUp', + path: '/database/:bizId(\\d+)/redis-toolbox/proxy-scale-up/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: '扩容接入层', // TODO: I18n + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/proxy-scale-up/Index.vue'), + }, + { + name: 'RedisProxyScaleDown', + path: '/database/:bizId(\\d+)/redis-toolbox/proxy-scale-down/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: '缩容接入层', // TODO: I18n + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/proxy-scale-down/Index.vue'), + }, + { + name: 'RedisDBReplace', + path: '/database/:bizId(\\d+)/redis-toolbox/db-replace/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: '整机替换', // TODO: I18n + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/db-replace/Index.vue'), + }, +]; + const routes: RouteRecordRaw[] = [ { name: 'SelfServiceApplyRedis', @@ -30,13 +84,27 @@ const routes: RouteRecordRaw[] = [ }, { name: 'DatabaseRedis', - path: 'redis', + path: 'redis-manage', meta: { routeParentName: MainViewRouteNames.Database, navName: t('Redis_集群管理'), isMenu: true, }, - component: () => import('@views/redis/Index.vue'), + component: () => import('@views/redis/cluster-manage/Index.vue'), + }, + { + name: 'RedisToolbox', + path: 'redis-toolbox', + redirect: { + name: 'RedisDBReplace', + }, + meta: { + routeParentName: MainViewRouteNames.Database, + navName: t('工具箱'), + isMenu: true, + }, + component: () => import('@views/redis/toolbox/Index.vue'), + children: toolboxRoutes, }, ]; diff --git a/dbm-ui/frontend/src/views/redis/toolbox/Index.vue b/dbm-ui/frontend/src/views/redis/toolbox/Index.vue new file mode 100644 index 0000000000..4266581757 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/toolbox/Index.vue @@ -0,0 +1,69 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts new file mode 100644 index 0000000000..b5ce908cd9 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts @@ -0,0 +1,49 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { t } from '@locales/index'; +export interface MenuChild { + name: string, + id: string, + parentId: string +} + +export default [ + { + name: t('集群维护'), + id: 'redis', + icon: 'db-icon-cluster', + children: [ + { + name: t('集群容量变更'), + id: 'RedisCapacityChange', + parentId: 'redis', + }, + { + name: t('扩容接入层'), + id: 'RedisProxyScaleUp', + parentId: 'redis', + }, + { + name: t('缩容接入层'), + id: 'RedisProxyScaleDown', + parentId: 'redis', + }, + { + name: t('整机替换'), + id: 'RedisDBReplace', + parentId: 'redis', + }, + ], + }, +]; diff --git a/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue b/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue new file mode 100644 index 0000000000..09d1b20905 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue @@ -0,0 +1,141 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxContent.vue b/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxContent.vue new file mode 100644 index 0000000000..3911c75935 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxContent.vue @@ -0,0 +1,53 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxSide.vue b/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxSide.vue new file mode 100644 index 0000000000..3cf74dd1ab --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/toolbox/components/ToolboxSide.vue @@ -0,0 +1,457 @@ + + + + + + + From b7625dbf966dfc788c127cdccd7f129b10448fce Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Wed, 5 Jul 2023 15:03:21 +0800 Subject: [PATCH 088/476] =?UTF-8?q?feat(fronent):=20=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=89=A9=E7=BC=A9=E5=AE=B9=E6=8E=A5=E5=85=A5=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=B1=A0=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 8e8363f404..c2b6aca55f 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1455,8 +1455,6 @@ "请选择操作时间": "请选择操作时间", "请选择匹配规格": "请选择匹配规格", "复制全部 IP": "复制全部 IP", - "复制异常 IP": "复制异常 IP", - "导入设置": "导入设置", "请选择切换模式": "请选择切换模式", "目标台数不能为空": "目标台数不能为空", "确认整机替换n台主机?": "确认整机替换{n}台主机?", @@ -1510,5 +1508,7 @@ "集群容量(G)": "集群容量(G)", "集群QPS(每秒)": "集群QPS(每秒)", "选择集群后自动生成": "选择集群后自动生成", + "复制异常 IP": "复制异常 IP", + "导入设置": "导入设置", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file From 7aecffa9c1f89766978d6f4236a73ebbb6fe93f7 Mon Sep 17 00:00:00 2001 From: austinqli <1344583166@qq.com> Date: Wed, 5 Jul 2023 14:45:15 +0800 Subject: [PATCH 089/476] =?UTF-8?q?feat(frontend):=20redis=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=20#396?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index c2b6aca55f..cb519c3995 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1510,5 +1510,58 @@ "选择集群后自动生成": "选择集群后自动生成", "复制异常 IP": "复制异常 IP", "导入设置": "导入设置", + "请选择切换模式": "请选择切换模式", + "目标台数不能为空": "目标台数不能为空", + "确认整机替换n台主机?": "确认整机替换{n}台主机?", + "确认接入层缩容n个集群?": "确认接入层缩容{n}个集群?", + "确认扩容接入层n个集群?": "确认扩容接入层{n}个集群?", + "确认缩容存储层n个集群?": "确认缩容存储层{n}个集群?", + "确认扩容存储层n个集群?": "确认扩容存储层{n}个集群?", + "请谨慎操作!": "请谨慎操作!", + "n核": "{n} 核", + "批量添加": "批量添加", + "缩容节点类型": "缩容节点类型", + "扩容节点类型": "扩容节点类型", + "当前规格": "当前规格", + "缩容至(台)": "缩容至(台)", + "扩容至(台)": "扩容至(台)", + "切换模式": "切换模式", + "输入集群后自动生成": "输入集群后自动生成", + "输入主机后自动生成": "输入主机后自动生成", + "(n)台": "{n}台", + "((n))台": "({n})台", + "需人工确认": "需人工确认", + "无需确认": "无需确认", + "请输入或选择集群": "请输入或选择集群", + "台数只能为正整数": "台数只能为正整数", + "不能大于最大台数": "不能大于最大台数", + "缩容接入层提交成功": "缩容接入层提交成功", + "请先输入集群": "请先输入集群", + "请输入字段名搜索": "请输入字段名搜索", + "数据为空": "数据为空", + "扩容接入层提交成功": "扩容接入层提交成功", + "缩容存储层提交成功": "缩容存储层提交成功", + "扩容存储层提交成功": "扩容存储层提交成功", + "当前方案": "当前方案", + "扩容方案": "扩容方案", + "扩容后预估容量": "扩容后预估容量", + "指定Redis版本": "指定Redis版本", + "选择扩容方案后自动生成": "选择扩容方案后自动生成", + "请选择扩容方案": "请选择扩容方案", + "请选择Redis版本": "请选择Redis版本", + "集群容量变更": "集群容量变更", + "扩容接入层": "扩容接入层", + "缩容接入层": "缩容接入层", + "整机替换": "整机替换", + "当前资源规格": "当前资源规格", + "部署机器组数": "部署机器组数", + "资源规格": "资源规格", + "Redis_工具箱": "Redis_工具箱", + "选择集群目标方案": "选择集群目标方案", + "需机器组数": "需机器组数", + "集群分片": "集群分片", + "集群容量(G)": "集群容量(G)", + "集群QPS(每秒)": "集群QPS(每秒)", + "选择集群后自动生成": "选择集群后自动生成", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file From ff7f9faa6f2529f893f92dee607f2f9e2880cfd9 Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Wed, 5 Jul 2023 15:03:21 +0800 Subject: [PATCH 090/476] =?UTF-8?q?feat(fronent):=20=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=89=A9=E7=BC=A9=E5=AE=B9=E6=8E=A5=E5=85=A5=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=B1=A0=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 53 -------------------------- 1 file changed, 53 deletions(-) diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index cb519c3995..c2b6aca55f 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1510,58 +1510,5 @@ "选择集群后自动生成": "选择集群后自动生成", "复制异常 IP": "复制异常 IP", "导入设置": "导入设置", - "请选择切换模式": "请选择切换模式", - "目标台数不能为空": "目标台数不能为空", - "确认整机替换n台主机?": "确认整机替换{n}台主机?", - "确认接入层缩容n个集群?": "确认接入层缩容{n}个集群?", - "确认扩容接入层n个集群?": "确认扩容接入层{n}个集群?", - "确认缩容存储层n个集群?": "确认缩容存储层{n}个集群?", - "确认扩容存储层n个集群?": "确认扩容存储层{n}个集群?", - "请谨慎操作!": "请谨慎操作!", - "n核": "{n} 核", - "批量添加": "批量添加", - "缩容节点类型": "缩容节点类型", - "扩容节点类型": "扩容节点类型", - "当前规格": "当前规格", - "缩容至(台)": "缩容至(台)", - "扩容至(台)": "扩容至(台)", - "切换模式": "切换模式", - "输入集群后自动生成": "输入集群后自动生成", - "输入主机后自动生成": "输入主机后自动生成", - "(n)台": "{n}台", - "((n))台": "({n})台", - "需人工确认": "需人工确认", - "无需确认": "无需确认", - "请输入或选择集群": "请输入或选择集群", - "台数只能为正整数": "台数只能为正整数", - "不能大于最大台数": "不能大于最大台数", - "缩容接入层提交成功": "缩容接入层提交成功", - "请先输入集群": "请先输入集群", - "请输入字段名搜索": "请输入字段名搜索", - "数据为空": "数据为空", - "扩容接入层提交成功": "扩容接入层提交成功", - "缩容存储层提交成功": "缩容存储层提交成功", - "扩容存储层提交成功": "扩容存储层提交成功", - "当前方案": "当前方案", - "扩容方案": "扩容方案", - "扩容后预估容量": "扩容后预估容量", - "指定Redis版本": "指定Redis版本", - "选择扩容方案后自动生成": "选择扩容方案后自动生成", - "请选择扩容方案": "请选择扩容方案", - "请选择Redis版本": "请选择Redis版本", - "集群容量变更": "集群容量变更", - "扩容接入层": "扩容接入层", - "缩容接入层": "缩容接入层", - "整机替换": "整机替换", - "当前资源规格": "当前资源规格", - "部署机器组数": "部署机器组数", - "资源规格": "资源规格", - "Redis_工具箱": "Redis_工具箱", - "选择集群目标方案": "选择集群目标方案", - "需机器组数": "需机器组数", - "集群分片": "集群分片", - "集群容量(G)": "集群容量(G)", - "集群QPS(每秒)": "集群QPS(每秒)", - "选择集群后自动生成": "选择集群后自动生成", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file From b2931d271a760c9843416a6ceeb2fd7f7d9ef629 Mon Sep 17 00:00:00 2001 From: austinqli <1344583166@qq.com> Date: Wed, 5 Jul 2023 14:45:15 +0800 Subject: [PATCH 091/476] =?UTF-8?q?feat(frontend):=20redis=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=20#396?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index c2b6aca55f..cb519c3995 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1510,5 +1510,58 @@ "选择集群后自动生成": "选择集群后自动生成", "复制异常 IP": "复制异常 IP", "导入设置": "导入设置", + "请选择切换模式": "请选择切换模式", + "目标台数不能为空": "目标台数不能为空", + "确认整机替换n台主机?": "确认整机替换{n}台主机?", + "确认接入层缩容n个集群?": "确认接入层缩容{n}个集群?", + "确认扩容接入层n个集群?": "确认扩容接入层{n}个集群?", + "确认缩容存储层n个集群?": "确认缩容存储层{n}个集群?", + "确认扩容存储层n个集群?": "确认扩容存储层{n}个集群?", + "请谨慎操作!": "请谨慎操作!", + "n核": "{n} 核", + "批量添加": "批量添加", + "缩容节点类型": "缩容节点类型", + "扩容节点类型": "扩容节点类型", + "当前规格": "当前规格", + "缩容至(台)": "缩容至(台)", + "扩容至(台)": "扩容至(台)", + "切换模式": "切换模式", + "输入集群后自动生成": "输入集群后自动生成", + "输入主机后自动生成": "输入主机后自动生成", + "(n)台": "{n}台", + "((n))台": "({n})台", + "需人工确认": "需人工确认", + "无需确认": "无需确认", + "请输入或选择集群": "请输入或选择集群", + "台数只能为正整数": "台数只能为正整数", + "不能大于最大台数": "不能大于最大台数", + "缩容接入层提交成功": "缩容接入层提交成功", + "请先输入集群": "请先输入集群", + "请输入字段名搜索": "请输入字段名搜索", + "数据为空": "数据为空", + "扩容接入层提交成功": "扩容接入层提交成功", + "缩容存储层提交成功": "缩容存储层提交成功", + "扩容存储层提交成功": "扩容存储层提交成功", + "当前方案": "当前方案", + "扩容方案": "扩容方案", + "扩容后预估容量": "扩容后预估容量", + "指定Redis版本": "指定Redis版本", + "选择扩容方案后自动生成": "选择扩容方案后自动生成", + "请选择扩容方案": "请选择扩容方案", + "请选择Redis版本": "请选择Redis版本", + "集群容量变更": "集群容量变更", + "扩容接入层": "扩容接入层", + "缩容接入层": "缩容接入层", + "整机替换": "整机替换", + "当前资源规格": "当前资源规格", + "部署机器组数": "部署机器组数", + "资源规格": "资源规格", + "Redis_工具箱": "Redis_工具箱", + "选择集群目标方案": "选择集群目标方案", + "需机器组数": "需机器组数", + "集群分片": "集群分片", + "集群容量(G)": "集群容量(G)", + "集群QPS(每秒)": "集群QPS(每秒)", + "选择集群后自动生成": "选择集群后自动生成", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file From f87ec11f63a3ed28f06c290313cdf1ddf731b6ba Mon Sep 17 00:00:00 2001 From: austinqli <1344583166@qq.com> Date: Wed, 5 Jul 2023 16:39:50 +0800 Subject: [PATCH 092/476] =?UTF-8?q?feat(frontend):=20redis=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=20#396?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 53 -------------------------- 1 file changed, 53 deletions(-) diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index cb519c3995..c2b6aca55f 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1510,58 +1510,5 @@ "选择集群后自动生成": "选择集群后自动生成", "复制异常 IP": "复制异常 IP", "导入设置": "导入设置", - "请选择切换模式": "请选择切换模式", - "目标台数不能为空": "目标台数不能为空", - "确认整机替换n台主机?": "确认整机替换{n}台主机?", - "确认接入层缩容n个集群?": "确认接入层缩容{n}个集群?", - "确认扩容接入层n个集群?": "确认扩容接入层{n}个集群?", - "确认缩容存储层n个集群?": "确认缩容存储层{n}个集群?", - "确认扩容存储层n个集群?": "确认扩容存储层{n}个集群?", - "请谨慎操作!": "请谨慎操作!", - "n核": "{n} 核", - "批量添加": "批量添加", - "缩容节点类型": "缩容节点类型", - "扩容节点类型": "扩容节点类型", - "当前规格": "当前规格", - "缩容至(台)": "缩容至(台)", - "扩容至(台)": "扩容至(台)", - "切换模式": "切换模式", - "输入集群后自动生成": "输入集群后自动生成", - "输入主机后自动生成": "输入主机后自动生成", - "(n)台": "{n}台", - "((n))台": "({n})台", - "需人工确认": "需人工确认", - "无需确认": "无需确认", - "请输入或选择集群": "请输入或选择集群", - "台数只能为正整数": "台数只能为正整数", - "不能大于最大台数": "不能大于最大台数", - "缩容接入层提交成功": "缩容接入层提交成功", - "请先输入集群": "请先输入集群", - "请输入字段名搜索": "请输入字段名搜索", - "数据为空": "数据为空", - "扩容接入层提交成功": "扩容接入层提交成功", - "缩容存储层提交成功": "缩容存储层提交成功", - "扩容存储层提交成功": "扩容存储层提交成功", - "当前方案": "当前方案", - "扩容方案": "扩容方案", - "扩容后预估容量": "扩容后预估容量", - "指定Redis版本": "指定Redis版本", - "选择扩容方案后自动生成": "选择扩容方案后自动生成", - "请选择扩容方案": "请选择扩容方案", - "请选择Redis版本": "请选择Redis版本", - "集群容量变更": "集群容量变更", - "扩容接入层": "扩容接入层", - "缩容接入层": "缩容接入层", - "整机替换": "整机替换", - "当前资源规格": "当前资源规格", - "部署机器组数": "部署机器组数", - "资源规格": "资源规格", - "Redis_工具箱": "Redis_工具箱", - "选择集群目标方案": "选择集群目标方案", - "需机器组数": "需机器组数", - "集群分片": "集群分片", - "集群容量(G)": "集群容量(G)", - "集群QPS(每秒)": "集群QPS(每秒)", - "选择集群后自动生成": "选择集群后自动生成", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file From 8ec9a640bbb6699861336792f7dca31b60a15923 Mon Sep 17 00:00:00 2001 From: secloud <47274844+iSecloud@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:14:04 +0800 Subject: [PATCH 093/476] =?UTF-8?q?refactor(backend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=E5=88=A0=E9=99=A4=E9=83=A8=E7=BD=B2=E6=96=B9=E6=A1=88?= =?UTF-8?q?&=E4=BF=AE=E5=A4=8D=E4=BD=93=E9=AA=8C=E9=97=AE=E9=A2=98=20#381?= =?UTF-8?q?=20(#382)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/cluster/mongocluster/create.py | 4 - .../db_meta/api/cluster/mongorepset/create.py | 4 - .../api/cluster/nosqlcomm/create_cluster.py | 4 - .../cluster/tendbcluster/create_cluster.py | 2 - .../api/cluster/tendbcluster/handler.py | 2 - .../api/cluster/tendiscache/handler.py | 2 - .../api/cluster/tendispluscluster/create.py | 2 - .../api/cluster/tendispluscluster/handler.py | 2 - .../db_meta/api/cluster/tendisssd/handler.py | 2 - dbm-ui/backend/db_meta/exceptions.py | 6 -- .../migrations/0007_auto_20230510_1955.py | 27 ----- .../0012_alter_clusterdeployplan_capacity.py | 18 ---- .../0013_alter_machine_spec_config.py | 2 +- .../migrations/0014_auto_20230627_1716.py | 2 +- .../migrations/0015_auto_20230703_2002.py | 22 +++++ dbm-ui/backend/db_meta/models/__init__.py | 2 +- dbm-ui/backend/db_meta/models/cluster.py | 14 +-- dbm-ui/backend/db_meta/models/spec.py | 54 ++++------ dbm-ui/backend/db_proxy/models.py | 29 +++++- .../db_services/bigdata/influxdb/query.py | 6 +- .../db_services/dbresource/exceptions.py | 6 -- .../backend/db_services/dbresource/filters.py | 22 +---- dbm-ui/backend/db_services/dbresource/mock.py | 19 ++++ .../db_services/dbresource/serializers.py | 44 ++------- dbm-ui/backend/db_services/dbresource/urls.py | 2 - .../dbresource/views/deploy_plan.py | 99 ------------------- .../db_services/dbresource/views/resource.py | 36 +++++-- .../db_services/dbresource/views/sepc.py | 30 +++++- .../db_services/redis/toolbox/serializers.py | 3 - dbm-ui/backend/flow/signal/handlers.py | 5 +- dbm-ui/backend/flow/utils/cc_manage.py | 5 + .../backend/flow/utils/redis/redis_db_meta.py | 3 - .../flow/utils/spider/spider_db_meta.py | 1 - dbm-ui/backend/ticket/builders/es/es_apply.py | 3 +- .../backend/ticket/builders/es/es_scale_up.py | 2 +- .../builders/mysql/mysql_single_apply.py | 3 +- .../builders/redis/redis_cluster_apply.py | 15 ++- .../ticket/builders/spider/tendb_apply.py | 37 +------ dbm-ui/backend/ticket/constants.py | 1 + dbm-ui/backend/ticket/flow_manager/base.py | 4 +- dbm-ui/backend/ticket/flow_manager/inner.py | 3 +- .../backend/ticket/flow_manager/resource.py | 83 +++++++--------- dbm-ui/backend/ticket/models/ticket.py | 2 +- 43 files changed, 230 insertions(+), 404 deletions(-) delete mode 100644 dbm-ui/backend/db_meta/migrations/0012_alter_clusterdeployplan_capacity.py create mode 100644 dbm-ui/backend/db_meta/migrations/0015_auto_20230703_2002.py delete mode 100644 dbm-ui/backend/db_services/dbresource/views/deploy_plan.py diff --git a/dbm-ui/backend/db_meta/api/cluster/mongocluster/create.py b/dbm-ui/backend/db_meta/api/cluster/mongocluster/create.py index 3ee7fd23a2..ade54dc1f5 100644 --- a/dbm-ui/backend/db_meta/api/cluster/mongocluster/create.py +++ b/dbm-ui/backend/db_meta/api/cluster/mongocluster/create.py @@ -55,7 +55,6 @@ def create_mongo_cluster( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, cluster_type=ClusterType.MongoShardedCluster.value, ): """创建副本集 MongoSet 实例 @@ -96,7 +95,6 @@ def create_mongo_cluster( updater=creator, cluster_type=cluster_type, bk_cloud_id=bk_cloud_id, - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID region=region, ) cluster.proxyinstance_set.add(*mongos_objs) @@ -152,7 +150,6 @@ def pkg_create_mongo_cluster( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, machine_specs: Optional[Dict] = None, cluster_type=ClusterType.MongoShardedCluster.value, ): @@ -219,5 +216,4 @@ def pkg_create_mongo_cluster( bk_cloud_id=bk_cloud_id, region=region, cluster_type=cluster_type, - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID ) diff --git a/dbm-ui/backend/db_meta/api/cluster/mongorepset/create.py b/dbm-ui/backend/db_meta/api/cluster/mongorepset/create.py index ba5866c561..d305190e84 100644 --- a/dbm-ui/backend/db_meta/api/cluster/mongorepset/create.py +++ b/dbm-ui/backend/db_meta/api/cluster/mongorepset/create.py @@ -53,7 +53,6 @@ def pkg_create_mongoset( region: str = "", spec_id: int = 0, spec_config: str = "", - deploy_plan_id: int = 0, cluster_type=ClusterType.MongoReplicaSet.value, ): """ @@ -90,7 +89,6 @@ def pkg_create_mongoset( bk_cloud_id=bk_cloud_id, region=region, cluster_type=cluster_type, - deploy_plan_id=deploy_plan_id, ) @@ -106,7 +104,6 @@ def create_mongoset( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, cluster_type=ClusterType.MongoReplicaSet.value, ): """创建副本集 MongoSet 实例 @@ -149,7 +146,6 @@ def create_mongoset( updater=creator, cluster_type=cluster_type, bk_cloud_id=bk_cloud_id, - deploy_plan_id=deploy_plan_id, region=region, ) cluster.storageinstance_set.add(*storage_objs) diff --git a/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/create_cluster.py b/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/create_cluster.py index 8227669be2..2d5a251ebe 100644 --- a/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/create_cluster.py +++ b/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/create_cluster.py @@ -58,7 +58,6 @@ def create_twemproxy_cluster( bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", cluster_type: str = ClusterType.TendisTwemproxyRedisInstance.value, - deploy_plan_id: int = 0, ): """ 兼容 TendisCache/TendisSSD 集群 @@ -93,7 +92,6 @@ def create_twemproxy_cluster( status=ClusterStatus.NORMAL.value, updater=creator, bk_cloud_id=bk_cloud_id, - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID region=region, ) cluster.proxyinstance_set.add(*proxy_objs) @@ -161,7 +159,6 @@ def pkg_create_twemproxy_cluster( bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", cluster_type=ClusterType.TendisTwemproxyRedisInstance.value, - deploy_plan_id: int = 0, machine_specs: Optional[Dict] = None, ): """ @@ -224,7 +221,6 @@ def pkg_create_twemproxy_cluster( storages=seg_instances, creator=creator, bk_cloud_id=bk_cloud_id, - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID region=region, cluster_type=cluster_type, ) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_cluster.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_cluster.py index bda1d666eb..1ebbf19406 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_cluster.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_cluster.py @@ -84,7 +84,6 @@ def create( time_zone: str, spiders: Optional[List], storages: Optional[List], - deploy_plan_id: int, creator: str = "", region: str = "", ): @@ -120,7 +119,6 @@ def create( bk_cloud_id=bk_cloud_id, time_zone=time_zone, major_version=major_version, # 这里存储集群的主版本信息,主要是为展示,存储mysql版本 - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID region=region, # 这里保存申请资源的地域信息 ) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py index 8b6eac9806..9b932d3933 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py @@ -48,7 +48,6 @@ def create( time_zone: str, bk_cloud_id: int, shard_infos: Optional[List[ShardInfo]], - deploy_plan_id: int, resource_spec: dict, region: str, ): @@ -133,7 +132,6 @@ def create( time_zone=time_zone, spiders=spiders, storages=storages, - deploy_plan_id=deploy_plan_id, creator=creator, region=region, ) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendiscache/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendiscache/handler.py index d6262a3162..3492241995 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendiscache/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendiscache/handler.py @@ -42,7 +42,6 @@ def create( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, ): """「必须」创建集群""" create_twemproxy_cluster( @@ -58,7 +57,6 @@ def create( bk_cloud_id=bk_cloud_id, region=region, cluster_type=ClusterType.TendisTwemproxyRedisInstance.value, - deploy_plan_id=deploy_plan_id, ) @transaction.atomic diff --git a/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/create.py b/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/create.py index db4f8fe006..940e18df21 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/create.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/create.py @@ -40,7 +40,6 @@ def create( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, ): """ 注册 TendisplusCluster 集群 @@ -73,7 +72,6 @@ def create( immute_domain=immute_domain, creator=creator, bk_cloud_id=bk_cloud_id, - deploy_plan_id=deploy_plan_id, # 这里存储当时选择的部署方案ID region=region, ) cluster.proxyinstance_set.add(*proxy_objs) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/handler.py index 4c6ec18112..60278ebca1 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendispluscluster/handler.py @@ -47,7 +47,6 @@ def create( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, ): """「必须」创建集群""" create( @@ -62,7 +61,6 @@ def create( creator=creator, bk_cloud_id=bk_cloud_id, region=region, - deploy_plan_id=deploy_plan_id, ) @transaction.atomic diff --git a/dbm-ui/backend/db_meta/api/cluster/tendisssd/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendisssd/handler.py index 32b123a9f6..4662bb88c7 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendisssd/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendisssd/handler.py @@ -42,7 +42,6 @@ def create( creator: str = "", bk_cloud_id: int = DEFAULT_BK_CLOUD_ID, region: str = "", - deploy_plan_id: int = 0, ): """「必须」创建集群""" create_twemproxy_cluster( @@ -58,7 +57,6 @@ def create( bk_cloud_id=bk_cloud_id, region=region, cluster_type=ClusterType.TwemproxyTendisSSDInstance.value, - deploy_plan_id=deploy_plan_id, ) @transaction.atomic diff --git a/dbm-ui/backend/db_meta/exceptions.py b/dbm-ui/backend/db_meta/exceptions.py index 52d7529cb5..f237833b12 100644 --- a/dbm-ui/backend/db_meta/exceptions.py +++ b/dbm-ui/backend/db_meta/exceptions.py @@ -144,12 +144,6 @@ class ClusterProxyExtraNotDefine(DBMetaBaseException): MESSAGE_TPL = _("集群类型:{cluster_type} proxy 无附加信息") -class ClusterDeployPlanNotMatchException(DBMetaBaseException): - ERROR_CODE = "022" - MESSAGE = _("部署方案不匹配") - MESSAGE_TPL = _("集群类型:{cluster_type} 和部署方案:{deploy_plan_class} 不匹配") - - class ClusterDeployHasRefException(DBMetaBaseException): ERROR_CODE = "023" MESSAGE = _("部署方案使用中") diff --git a/dbm-ui/backend/db_meta/migrations/0007_auto_20230510_1955.py b/dbm-ui/backend/db_meta/migrations/0007_auto_20230510_1955.py index 4a565674ab..76569423d2 100644 --- a/dbm-ui/backend/db_meta/migrations/0007_auto_20230510_1955.py +++ b/dbm-ui/backend/db_meta/migrations/0007_auto_20230510_1955.py @@ -13,33 +13,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.CreateModel( - name="ClusterDeployPlan", - fields=[ - ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), - ("creator", models.CharField(max_length=64, verbose_name="创建人")), - ("create_at", models.DateTimeField(auto_now_add=True, verbose_name="创建时间")), - ("updater", models.CharField(max_length=64, verbose_name="修改人")), - ("update_at", models.DateTimeField(auto_now=True, verbose_name="更新时间")), - ("name", models.CharField(default="", max_length=128)), - ("shard_cnt", models.PositiveIntegerField(default=0, help_text="集群分片总数")), - ("capacity", models.PositiveIntegerField(default=0, help_text="集群存储预估总容量/G")), - ("machine_pair_cnt", models.PositiveIntegerField(default=0, help_text="机器组数: (每组两台)")), - ( - "cluster_type", - models.CharField( - choices=ClusterType.get_choices(), - help_text="集群类型", - max_length=128, - ), - ), - ("desc", models.TextField(blank=True, default="", help_text="方案描述", null=True)), - ("spec", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to="db_meta.spec")), - ], - options={ - "abstract": False, - }, - ), migrations.AlterField( model_name="clusterentry", name="role", diff --git a/dbm-ui/backend/db_meta/migrations/0012_alter_clusterdeployplan_capacity.py b/dbm-ui/backend/db_meta/migrations/0012_alter_clusterdeployplan_capacity.py deleted file mode 100644 index a3eb5eb107..0000000000 --- a/dbm-ui/backend/db_meta/migrations/0012_alter_clusterdeployplan_capacity.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-08 07:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("db_meta", "0011_alter_cluster_name"), - ] - - operations = [ - migrations.AlterField( - model_name="clusterdeployplan", - name="capacity", - field=models.CharField(default="", help_text="集群存储预估总容量/G", max_length=128), - ), - ] diff --git a/dbm-ui/backend/db_meta/migrations/0013_alter_machine_spec_config.py b/dbm-ui/backend/db_meta/migrations/0013_alter_machine_spec_config.py index f2778c5cd5..68d84b2703 100644 --- a/dbm-ui/backend/db_meta/migrations/0013_alter_machine_spec_config.py +++ b/dbm-ui/backend/db_meta/migrations/0013_alter_machine_spec_config.py @@ -6,7 +6,7 @@ class Migration(migrations.Migration): dependencies = [ - ("db_meta", "0012_alter_clusterdeployplan_capacity"), + ("db_meta", "0011_alter_cluster_name"), ] operations = [ diff --git a/dbm-ui/backend/db_meta/migrations/0014_auto_20230627_1716.py b/dbm-ui/backend/db_meta/migrations/0014_auto_20230627_1716.py index 89e619ff75..df92034b52 100644 --- a/dbm-ui/backend/db_meta/migrations/0014_auto_20230627_1716.py +++ b/dbm-ui/backend/db_meta/migrations/0014_auto_20230627_1716.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name="spec", name="instance_num", - field=models.IntegerField(default=1, help_text="实例数(es专属)"), + field=models.IntegerField(default=0, help_text="实例数(es专属)"), ), migrations.AlterUniqueTogether( name="spec", diff --git a/dbm-ui/backend/db_meta/migrations/0015_auto_20230703_2002.py b/dbm-ui/backend/db_meta/migrations/0015_auto_20230703_2002.py new file mode 100644 index 0000000000..837c4dfd83 --- /dev/null +++ b/dbm-ui/backend/db_meta/migrations/0015_auto_20230703_2002.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.19 on 2023-07-03 12:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("db_meta", "0014_auto_20230627_1716"), + ] + + operations = [ + migrations.RemoveField( + model_name="cluster", + name="deploy_plan_id", + ), + migrations.AddField( + model_name="spec", + name="qps", + field=models.JSONField(default=dict, help_text="qps规格描述:{'min': 1, 'max': 100}"), + ), + ] diff --git a/dbm-ui/backend/db_meta/models/__init__.py b/dbm-ui/backend/db_meta/models/__init__.py index bffd0bfc2f..010c1e4fb8 100644 --- a/dbm-ui/backend/db_meta/models/__init__.py +++ b/dbm-ui/backend/db_meta/models/__init__.py @@ -18,7 +18,7 @@ from .instance import ProxyInstance, StorageInstance from .machine import Machine from .proxy_instance_ext import TenDBClusterSpiderExt -from .spec import ClusterDeployPlan, SnapshotSpec, Spec +from .spec import SnapshotSpec, Spec from .storage_instance_tuple import StorageInstanceTuple from .storage_set_dtl import NosqlStorageSetDtl, TenDBClusterStorageSet from .tag import Tag diff --git a/dbm-ui/backend/db_meta/models/cluster.py b/dbm-ui/backend/db_meta/models/cluster.py index 3b03f2bac1..bc7b6d226e 100644 --- a/dbm-ui/backend/db_meta/models/cluster.py +++ b/dbm-ui/backend/db_meta/models/cluster.py @@ -30,7 +30,6 @@ TenDBClusterSpiderRole, ) from backend.db_meta.exceptions import ClusterExclusiveOperateException, DBMetaException -from backend.db_meta.models.spec import ClusterDeployPlan from backend.db_services.version.constants import LATEST, PredixyVersion, TwemproxyVersion from backend.ticket.constants import TicketType from backend.ticket.models import ClusterOperateRecord @@ -51,7 +50,6 @@ class Cluster(AuditedModel): bk_cloud_id = models.IntegerField(default=DEFAULT_BK_CLOUD_ID, help_text=_("云区域 ID")) region = models.CharField(max_length=128, default="", help_text=_("地域")) time_zone = models.CharField(max_length=16, default=DEFAULT_TIME_ZONE, help_text=_("集群所在的时区")) - deploy_plan_id = models.BigIntegerField(default=0, help_text=_("部署方法ID")) # tag = models.ManyToManyField(Tag, blank=True) @@ -66,9 +64,7 @@ def to_dict(self): @property def simple_desc(self): - return model_to_dict( - self, ["id", "name", "bk_cloud_id", "region", "cluster_type", "immute_domain", "deploy_plan_id"] - ) + return model_to_dict(self, ["id", "name", "bk_cloud_id", "region", "cluster_type", "immute_domain"]) @property def extra_desc(self): @@ -85,10 +81,6 @@ def extra_desc(self): ): simple_desc["{}_count".format(storage["instance_role"])] = storage["cnt"] - # 填充部署方案详情 - simple_desc["deploy_plan"] = getattr( - ClusterDeployPlan.objects.filter(id=self.deploy_plan_id).last(), "simple_desc", {} - ) return simple_desc @classmethod @@ -210,10 +202,6 @@ def get_partition_port(self): elif self.cluster_type == ClusterType.TenDBHA: return self.proxyinstance_set.first().port - @classmethod - def get_refer_deploy_plan_ids(cls, deploy_plan_ids): - return cls.objects.filter(deploy_plan_id__in=deploy_plan_ids).values_list("deploy_plan_id", flat=True) - def tendbcluster_ctl_primary_address(self) -> str: """ 查询并返回 tendbcluster 的中控 primary diff --git a/dbm-ui/backend/db_meta/models/spec.py b/dbm-ui/backend/db_meta/models/spec.py index 779e39bb55..f0930c1e48 100644 --- a/dbm-ui/backend/db_meta/models/spec.py +++ b/dbm-ui/backend/db_meta/models/spec.py @@ -35,7 +35,9 @@ class Spec(AuditedModel): storage_spec = models.JSONField(null=True, help_text=_("存储磁盘需求配置:{'mount_point':'/data','size':500,'type':'ssd'}")) desc = models.TextField(help_text=_("资源规格描述"), default="") # es专属 - instance_num = models.IntegerField(default=1, help_text=_("实例数(es专属)")) + instance_num = models.IntegerField(default=0, help_text=_("实例数(es专属)")) + # spider,redis集群专属 + qps = models.JSONField(default=dict, help_text=_("qps规格描述:{'min': 1, 'max': 100}")) class Meta: index_together = [("spec_cluster_type", "spec_machine_type", "spec_name")] @@ -45,14 +47,28 @@ def get_apply_params_detail(self, group_mark, count, bk_cloud_id, affinity=None, return { "group_mark": group_mark, "bk_cloud_id": bk_cloud_id, - # "device_class": self.device_class, + "device_class": self.device_class, "spec": {"cpu": self.cpu, "ram": self.mem}, - # "storage_spec": self.storage_spec, + "storage_spec": self.storage_spec, "count": count, "affinity": affinity # TODO: 暂时忽略location_spec(位置信息) } + def get_backend_group_apply_params_detail(self, bk_cloud_id, backend_group): + # 专属于后端:如果一组master/slave有特殊要求,则采用backend_group申请 + backend_group_params = [ + self.get_apply_params_detail( + group_mark=f"backend_group_{group}", + count=2, + bk_cloud_id=bk_cloud_id, + affinity=backend_group.get("affinity", None), + location_spec=backend_group.get("location_spec", None), + ) + for group in range(backend_group["count"]) + ] + return backend_group_params + def get_spec_info(self): # 获取规格的基本信息 return { @@ -65,38 +81,6 @@ def get_spec_info(self): } -class ClusterDeployPlan(AuditedModel): - """ - Spider、TendisCache、TendisPlus、TendisSSD 部署方案 - """ - - name = models.CharField(max_length=128, default="") - shard_cnt = models.PositiveIntegerField(default=0, help_text=_("集群分片总数")) - capacity = models.CharField(max_length=128, default="", help_text=_("集群存储预估总容量/G")) - machine_pair_cnt = models.PositiveIntegerField(default=0, help_text=_("机器组数: (每组两台)")) - spec = models.ForeignKey(Spec, on_delete=models.PROTECT) - cluster_type = models.CharField(help_text=_("集群类型"), choices=ClusterType.get_choices(), max_length=128) - desc = models.TextField(default="", help_text=_("方案描述"), blank=True, null=True) - - def get_apply_params_details(self, bk_cloud_id, affinity=None, location_spec=None): - # 获取资源申请的参数,暂时忽略亲和性和位置参数过滤 - backend_group_params = [ - self.spec.get_apply_params_detail( - group_mark=f"backend_group_{group}", - count=2, - bk_cloud_id=bk_cloud_id, - affinity=affinity, - location_spec=location_spec, - ) - for group in range(self.machine_pair_cnt) - ] - return backend_group_params - - @property - def simple_desc(self): - return model_to_dict(self, ["id", "name", "shard_cnt", "capacity", "machine_pair_cnt", "cluster_type"]) - - class SnapshotSpec(AuditedModel): """ 资源规格快照 diff --git a/dbm-ui/backend/db_proxy/models.py b/dbm-ui/backend/db_proxy/models.py index 580eda7726..d3f2d03ded 100644 --- a/dbm-ui/backend/db_proxy/models.py +++ b/dbm-ui/backend/db_proxy/models.py @@ -13,12 +13,14 @@ from typing import Dict, Union from django.db import models +from django.db.models.manager import Manager from django.utils.translation import gettext_lazy as _ from backend.bk_web.constants import LEN_LONG, LEN_NORMAL, LEN_SHORT from backend.bk_web.models import AuditedModel from backend.configuration.constants import DBType from backend.db_proxy.constants import CLUSTER__SERVICE_MAP, ClusterServiceType, ExtensionServiceStatus, ExtensionType +from backend.db_proxy.exceptions import ProxyPassBaseException from backend.flow.consts import CloudDBHATypeEnum @@ -116,6 +118,28 @@ def update_details(self, **kwargs): self.save() +class ClusterExtensionManager(Manager): + def create(self, **kwargs): + try: + # 因为ClusterExtension是软删除,所以创建的时候要判断是否有同种配置记录 + # TODO: 后续需要支持定时删除带有软删除标记的nginx文件 + ext = ClusterExtension.objects.filter( + bk_biz_id=kwargs["bk_biz_id"], + db_type=kwargs["db_type"], + cluster_name=kwargs["cluster_name"], + service_type=kwargs["service_type"], + is_deleted=False, + ) + if ext.count(): + raise ProxyPassBaseException( + _("在业务{}下已经存在同种配置的服务组件记录,请检查是否在同一业务下部署了同名的集群").format(kwargs["bk_biz_id"]) + ) + except ClusterExtension.DoesNotExist: + pass + + super().create(**kwargs) + + class ClusterExtension(AuditedModel): """集群部署所带的额外服务组件记录,如es的kibana""" @@ -131,11 +155,12 @@ class ClusterExtension(AuditedModel): # 当定时任务执行的时候,需要拉去is_flush为False的进行操作,并刷新为True is_flush = models.BooleanField(verbose_name=_("是否刷新(该条记录是否执行)"), default=False) is_deleted = models.BooleanField(verbose_name=_("是否删除"), default=False) - access_url = models.TextField(verbose_name=_("服务访问地址"), default="") + objects = ClusterExtensionManager() + class Meta: - unique_together = ["bk_biz_id", "db_type", "cluster_name", "service_type"] + index_together = [("bk_biz_id", "db_type", "cluster_name", "service_type")] @classmethod def get_extension_by_flush(cls, is_flush: bool = False, is_deleted: bool = False): diff --git a/dbm-ui/backend/db_services/bigdata/influxdb/query.py b/dbm-ui/backend/db_services/bigdata/influxdb/query.py index a56c1a66af..17aad18fd2 100644 --- a/dbm-ui/backend/db_services/bigdata/influxdb/query.py +++ b/dbm-ui/backend/db_services/bigdata/influxdb/query.py @@ -137,9 +137,9 @@ def _to_instance( "instance_address": f"{instance['machine__ip']}{IP_PORT_DIVIDER}{instance['port']}", "instance_name": instance["name"], "bk_host_id": instance["machine__bk_host_id"], - "bk_mem": host_info.get("bk_mem", ""), - "bk_cpu": host_info.get("bk_cpu", ""), - "bk_disk": host_info.get("bk_disk", ""), + "mem": host_info.get("bk_mem", ""), + "cpu": host_info.get("bk_cpu", ""), + "disk": host_info.get("bk_disk", ""), "bk_cloud_id": instance["machine__bk_cloud_id"], "bk_cloud_name": cloud_info[str(instance["machine__bk_cloud_id"])]["bk_cloud_name"], "role": instance["role"], diff --git a/dbm-ui/backend/db_services/dbresource/exceptions.py b/dbm-ui/backend/db_services/dbresource/exceptions.py index c433e0595c..e9d9537e16 100644 --- a/dbm-ui/backend/db_services/dbresource/exceptions.py +++ b/dbm-ui/backend/db_services/dbresource/exceptions.py @@ -28,9 +28,3 @@ class SpecOperateException(ResourcePoolBaseException): ERROR_CODE = "002" MESSAGE = _("规格操作失败") MESSAGE_TPL = _("规格操作失败") - - -class DeployPlanOperateException(ResourcePoolBaseException): - ERROR_CODE = "003" - MESSAGE = _("部署方案操作失败") - MESSAGE_TPL = _("部署方案操作失败") diff --git a/dbm-ui/backend/db_services/dbresource/filters.py b/dbm-ui/backend/db_services/dbresource/filters.py index 1b37c3bab2..884c0bcc51 100644 --- a/dbm-ui/backend/db_services/dbresource/filters.py +++ b/dbm-ui/backend/db_services/dbresource/filters.py @@ -12,7 +12,7 @@ from django.utils.translation import ugettext_lazy as _ from django_filters import rest_framework as filters -from backend.db_meta.models.spec import ClusterDeployPlan, Spec +from backend.db_meta.models.spec import Spec class SpecListFilter(filters.FilterSet): @@ -20,26 +20,12 @@ class SpecListFilter(filters.FilterSet): desc = filters.CharFilter(field_name="desc", lookup_expr="icontains", label=_("描述")) spec_cluster_type = filters.CharFilter(field_name="spec_cluster_type", lookup_expr="exact", label=_("规格集群类型")) spec_machine_type = filters.CharFilter(field_name="spec_machine_type", lookup_expr="exact", label=_("规格机器类型")) - time_asc = filters.BooleanFilter(field_name="time_asc", method="filter_time_asc", label=_("根据时间正序/逆序")) + update_at = filters.BooleanFilter(field_name="update_at", method="filter_update_at", label=_("根据时间正序/逆序")) - def filter_time_asc(self, queryset, name, value): + def filter_update_at(self, queryset, name, value): time_field = "update_at" if value else "-update_at" return queryset.order_by(time_field) class Meta: model = Spec - fields = ["spec_name", "spec_cluster_type", "spec_machine_type", "desc", "time_asc"] - - -class ClusterDeployPlanFilter(filters.FilterSet): - name = filters.CharFilter(field_name="name", lookup_expr="icontains", label=_("Redis部署方案名称")) - cluster_type = filters.CharFilter(field_name="cluster_type", lookup_expr="exact", label=_("Redis集群类型")) - time_asc = filters.BooleanFilter(field_name="time_asc", method="filter_time_asc", label=_("根据时间正序/逆序")) - - def filter_time_asc(self, queryset, name, value): - time_field = "update_at" if value else "-update_at" - return queryset.order_by(time_field) - - class Meta: - model = ClusterDeployPlan - fields = ["name", "cluster_type"] + fields = ["spec_name", "spec_cluster_type", "spec_machine_type", "desc", "update_at"] diff --git a/dbm-ui/backend/db_services/dbresource/mock.py b/dbm-ui/backend/db_services/dbresource/mock.py index ecf9dd05de..9e9137c3a1 100644 --- a/dbm-ui/backend/db_services/dbresource/mock.py +++ b/dbm-ui/backend/db_services/dbresource/mock.py @@ -59,3 +59,22 @@ "for_bizs": [{"bk_biz_id": 2005000100, "bk_biz_name": "xxxx"}], }, ] + +RECOMMEND_SPEC_DATA = [ + { + "spec_id": 1, + "creator": "admin", + "create_at": "2023-06-26 16:30:22", + "updater": "admin", + "update_at": "2023-06-26 16:30:22", + "spec_name": "mysql", + "spec_cluster_type": "tendbsingle", + "spec_machine_type": "backend", + "cpu": {"max": 10000, "min": 1}, + "mem": {"max": 10000, "min": 1}, + "device_class": [], + "storage_spec": [{"type": "", "max_size": 100000000, "min_size": 1, "mount_point": ""}], + "desc": "mysql", + "instance_num": 1, + } +] diff --git a/dbm-ui/backend/db_services/dbresource/serializers.py b/dbm-ui/backend/db_services/dbresource/serializers.py index c35b07b89c..ee1a42a847 100644 --- a/dbm-ui/backend/db_services/dbresource/serializers.py +++ b/dbm-ui/backend/db_services/dbresource/serializers.py @@ -16,9 +16,9 @@ from backend import env from backend.configuration.constants import DBType from backend.db_meta.enums import InstanceRole -from backend.db_meta.models import ClusterDeployPlan, Spec +from backend.db_meta.models import Spec from backend.db_services.dbresource.constants import ResourceOperation -from backend.db_services.dbresource.mock import RESOURCE_LIST_DATA, SPEC_DATA +from backend.db_services.dbresource.mock import RECOMMEND_SPEC_DATA, RESOURCE_LIST_DATA, SPEC_DATA from backend.db_services.ipchooser.serializers.base import QueryHostsBaseSer from backend.ticket.constants import TicketStatus @@ -200,6 +200,7 @@ def validate(self, attrs): & Q(mem=attrs["mem"]) & Q(device_class=attrs["device_class"]) & Q(storage_spec=attrs["storage_spec"]) + & Q(instance_num=attrs.get("instance_num", 1)) ) specs = Spec.objects.filter(unique_filter) if specs.count() and getattr(self.instance, "spec_id", 0) != specs.first().spec_id: @@ -215,41 +216,16 @@ class Meta: swagger_schema_fields = {"example": {"spec_ids": [1, 2, 3]}} -class DeleteDeployPlanSerializer(serializers.Serializer): - deploy_plan_ids = serializers.ListField(help_text=_("部署方案id列表"), child=serializers.IntegerField()) - - class Meta: - swagger_schema_fields = {"example": {"deploy_plan_ids": [1, 2, 3]}} - - class ListSubzonesSerializer(serializers.Serializer): citys = serializers.ListField(help_text=_("逻辑城市"), child=serializers.CharField()) -class ClusterDeployPlanSerializer(serializers.ModelSerializer): - class Meta: - model = ClusterDeployPlan - fields = "__all__" - read_only_fields = ("id",) + model.AUDITED_FIELDS - swagger_schema_fields = {"example": {}} - - def validate(self, attrs): - unique_filter = Q(cluster_type=attrs["cluster_type"]) & Q(name=attrs["name"]) - if ClusterDeployPlan.objects.filter(unique_filter).count(): - raise serializers.ValidationError(_("已存在同名部署方案,请保证集群类型-部署方案名称必须唯一")) - - unique_filter = ( - Q(cluster_type=attrs["cluster_type"]) - & Q(shard_cnt=attrs["shard_cnt"]) - & Q(machine_pair_cnt=attrs["machine_pair_cnt"]) - & Q(spec=attrs["spec"]) - ) - if ClusterDeployPlan.objects.filter(unique_filter).count(): - raise serializers.ValidationError(_("已存在同种部署方案配置,请不要在相同部署方案类型下重复录入")) - - return attrs +class RecommendSpecSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID"), required=False) + instance_id = serializers.IntegerField(help_text=_("实例ID"), required=False) + role = serializers.ChoiceField(help_text=_("实例类型"), choices=InstanceRole.get_choices()) -class RecommendSpecSerializer(serializers.Serializer): - cluster_id = serializers.IntegerField(help_text=_("集群ID")) - role = serializers.ChoiceField(help_text=_("实例类型"), choices=InstanceRole.get_choices(), required=False) +class RecommendResponseSpecSerializer(serializers.Serializer): + class Meta: + swagger_schema_fields = {"example": RECOMMEND_SPEC_DATA} diff --git a/dbm-ui/backend/db_services/dbresource/urls.py b/dbm-ui/backend/db_services/dbresource/urls.py index f7f22c2c72..a779c7feb5 100644 --- a/dbm-ui/backend/db_services/dbresource/urls.py +++ b/dbm-ui/backend/db_services/dbresource/urls.py @@ -10,7 +10,6 @@ """ from rest_framework.routers import DefaultRouter -from backend.db_services.dbresource.views.deploy_plan import ClusterDeployPlanViewSet from backend.db_services.dbresource.views.resource import DBResourceViewSet from backend.db_services.dbresource.views.sepc import DBSpecViewSet @@ -18,6 +17,5 @@ routers.register("resource", DBResourceViewSet, basename="resource") routers.register("spec", DBSpecViewSet, basename="spec") -routers.register("deploy_plan", ClusterDeployPlanViewSet, basename="deploy_plan") urlpatterns = routers.urls diff --git a/dbm-ui/backend/db_services/dbresource/views/deploy_plan.py b/dbm-ui/backend/db_services/dbresource/views/deploy_plan.py deleted file mode 100644 index 36b7865368..0000000000 --- a/dbm-ui/backend/db_services/dbresource/views/deploy_plan.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -""" -TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. -Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. -You may obtain a copy of the License at https://opensource.org/licenses/MIT -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on -an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -""" - -from django.utils.translation import ugettext_lazy as _ -from rest_framework.decorators import action -from rest_framework.response import Response - -from backend.bk_web import viewsets -from backend.bk_web.pagination import AuditedLimitOffsetPagination -from backend.bk_web.swagger import common_swagger_auto_schema -from backend.db_meta.models import Cluster -from backend.db_meta.models.spec import ClusterDeployPlan -from backend.db_services.dbresource.constants import SWAGGER_TAG -from backend.db_services.dbresource.exceptions import DeployPlanOperateException -from backend.db_services.dbresource.filters import ClusterDeployPlanFilter -from backend.db_services.dbresource.serializers import ClusterDeployPlanSerializer, DeleteDeployPlanSerializer -from backend.iam_app.handlers.drf_perm import GlobalManageIAMPermission - - -class DeployPlanViewSet(viewsets.AuditedModelViewSet): - - pagination_class = AuditedLimitOffsetPagination - view_name = "" - - def _get_custom_permissions(self): - return [GlobalManageIAMPermission()] - - @common_swagger_auto_schema( - operation_summary=_("新建{}部署方案").format(view_name), - tags=[SWAGGER_TAG], - ) - def create(self, request, *args, **kwargs): - return super().create(request, *args, **kwargs) - - @common_swagger_auto_schema( - operation_summary=_("更新{}部署方案").format(view_name), - tags=[SWAGGER_TAG], - ) - def update(self, request, *args, **kwargs): - deploy_plan_id = int(kwargs["pk"]) - if Cluster.get_refer_deploy_plan_ids([deploy_plan_id]): - raise DeployPlanOperateException(_("部署方案: {} 正在被引用,无法修改相关参数").format(deploy_plan_id)) - return super().update(request, *args, **kwargs) - - @common_swagger_auto_schema( - operation_summary=_("查询{}部署方案列表").format(view_name), - tags=[SWAGGER_TAG], - ) - def list(self, request, *args, **kwargs): - queryset = self.filter_queryset(self.get_queryset()) - page_queryset = self.paginate_queryset(queryset) - page_data = self.get_serializer(page_queryset, many=True).data - - # 填充is_refer(是否被集群引用)参数 - deploy_plan_ids = [data["id"] for data in page_data] - refer_plans = Cluster.get_refer_deploy_plan_ids(deploy_plan_ids) - for data in page_data: - data.update(is_refer=(data["id"] in refer_plans)) - - return self.get_paginated_response(page_data) - - @common_swagger_auto_schema( - operation_summary=_("删除{}部署方案").format(view_name), - tags=[SWAGGER_TAG], - ) - def destroy(self, request, *args, **kwargs): - deploy_plan_id = int(kwargs["pk"]) - if Cluster.get_refer_deploy_plan_ids([deploy_plan_id]): - raise DeployPlanOperateException(_("部署方案: {} 正在被引用,无法删除").format(deploy_plan_id)) - super().destroy(request, *args, **kwargs) - return Response() - - @common_swagger_auto_schema( - operation_summary=_("批量删除{}部署方案").format(view_name), - request_body=DeleteDeployPlanSerializer(), - tags=[SWAGGER_TAG], - ) - @action(methods=["DELETE"], detail=False, serializer_class=DeleteDeployPlanSerializer) - def batch_delete(self, request, *args, **kwargs): - plan_ids = self.params_validate(self.get_serializer_class())["deploy_plan_ids"] - if Cluster.get_refer_deploy_plan_ids(plan_ids): - raise DeployPlanOperateException(_("部署方案: {} 存在被引用,无法删除").format(plan_ids)) - return Response(self.deploy_plan_model.objects.filter(id__in=plan_ids).delete()) - - -class ClusterDeployPlanViewSet(DeployPlanViewSet): - - queryset = ClusterDeployPlan.objects.all() - serializer_class = ClusterDeployPlanSerializer - deploy_plan_model = ClusterDeployPlan - filter_class = ClusterDeployPlanFilter diff --git a/dbm-ui/backend/db_services/dbresource/views/resource.py b/dbm-ui/backend/db_services/dbresource/views/resource.py index d7e4d53abb..5695e20653 100644 --- a/dbm-ui/backend/db_services/dbresource/views/resource.py +++ b/dbm-ui/backend/db_services/dbresource/views/resource.py @@ -13,7 +13,7 @@ import itertools import time import uuid -from typing import Any, Dict, List +from typing import Dict, List from django.utils.translation import ugettext_lazy as _ from rest_framework import status @@ -23,7 +23,10 @@ from backend import env from backend.bk_web import viewsets from backend.bk_web.swagger import common_swagger_auto_schema +from backend.components import CCApi from backend.components.dbresource.client import DBResourceApi +from backend.configuration.constants import RESOURCE_TOPO +from backend.configuration.models import SystemSettings from backend.db_meta.models import AppCache from backend.db_services.dbresource.constants import ( GSE_AGENT_RUNNING_CODE, @@ -54,10 +57,10 @@ from backend.flow.engine.controller.base import BaseController from backend.flow.models import FlowTree from backend.iam_app.handlers.drf_perm import GlobalManageIAMPermission -from backend.ticket.constants import TicketType +from backend.ticket.constants import BAMBOO_STATE__TICKET_STATE_MAP, TicketStatus, TicketType from backend.ticket.models import Ticket from backend.utils.redis import RedisConn -from backend.utils.time import datetime2str, remove_timezone +from backend.utils.time import remove_timezone class DBResourceViewSet(viewsets.SystemViewSet): @@ -86,7 +89,7 @@ def _format_resource_fields(data, _cloud_info, _for_biz_infos): {"bk_biz_id": int(bk_biz_id), "bk_biz_name": _for_biz_infos[int(bk_biz_id)]} for bk_biz_id in data.pop("for_bizs") ], - "agent_status": (data.pop("gse_agent_status_code") == GSE_AGENT_RUNNING_CODE), + "agent_status": int((data.pop("gse_agent_status_code") == GSE_AGENT_RUNNING_CODE)), } ) return data @@ -281,7 +284,19 @@ def resource_confirm(self, request): @action(detail=False, methods=["POST"], url_path="delete", serializer_class=ResourceDeleteSerializer) def resource_delete(self, request): validated_data = self.params_validate(self.get_serializer_class()) - return Response(DBResourceApi.resource_delete(params=validated_data)) + # 从资源池删除机器 + resp = DBResourceApi.resource_delete(params=validated_data) + # 将在资源池模块的机器移到空闲机,若机器处于其他模块,则忽略 + move_idle_hosts: List[int] = [] + resource_topo = SystemSettings.get_setting_value(key=RESOURCE_TOPO) + for topo in CCApi.find_host_biz_relations({"bk_host_id": validated_data["bk_host_ids"]}): + if topo["bk_set_id"] == resource_topo["set_id"] and topo["bk_module_id"] == resource_topo["module_id"]: + move_idle_hosts.append(topo["bk_host_id"]) + + if move_idle_hosts: + CCApi.transfer_host_to_idlemodule({"bk_biz_id": env.DBA_APP_BK_BIZ_ID, "bk_host_id": move_idle_hosts}) + + return Response(resp) @common_swagger_auto_schema( operation_summary=_("资源更新"), @@ -322,9 +337,9 @@ def query_operation_list(self, request): operation_list = DBResourceApi.operation_list(query_params) operation_list["results"] = operation_list.pop("details") or [] - ticket_ids: List[int] = [op["bill_id"] for op in operation_list["results"] if op["bill_id"]] - ticket_id__ticket_map: Dict[int, Ticket] = { - ticket.id: ticket for ticket in Ticket.objects.filter(id__in=ticket_ids) + task_ids: List[int] = [op["task_id"] for op in operation_list["results"]] + task_id__task: Dict[int, Ticket] = { + task.root_id: task for task in FlowTree.objects.filter(root_id__in=task_ids) } for op in operation_list["results"]: # 格式化操作记录参数 @@ -332,8 +347,9 @@ def query_operation_list(self, request): op["update_time"] = remove_timezone(op["update_time"]) op["ticket_id"] = int(op.pop("bill_id") or 0) - op["bk_biz_id"] = getattr(ticket_id__ticket_map.get(op["ticket_id"]), "bk_biz_id", env.DBA_APP_BK_BIZ_ID) - op["status"] = getattr(ticket_id__ticket_map.get(op["ticket_id"]), "status", "") + op["bk_biz_id"] = getattr(task_id__task.get(op["task_id"]), "bk_biz_id", env.DBA_APP_BK_BIZ_ID) + task_status = getattr(task_id__task.get(op["task_id"]), "status", "") + op["status"] = BAMBOO_STATE__TICKET_STATE_MAP.get(task_status, TicketStatus.RUNNING) # 过滤单据状态的操作记录 operation_list["results"] = [ diff --git a/dbm-ui/backend/db_services/dbresource/views/sepc.py b/dbm-ui/backend/db_services/dbresource/views/sepc.py index f579045686..5dbc07681a 100644 --- a/dbm-ui/backend/db_services/dbresource/views/sepc.py +++ b/dbm-ui/backend/db_services/dbresource/views/sepc.py @@ -11,6 +11,7 @@ from django.db.models import F, Q from django.utils.translation import ugettext_lazy as _ +from rest_framework import status from rest_framework.decorators import action from rest_framework.response import Response @@ -18,12 +19,18 @@ from backend.bk_web.models import AuditedModel from backend.bk_web.pagination import AuditedLimitOffsetPagination from backend.bk_web.swagger import common_swagger_auto_schema +from backend.db_meta.enums import InstanceRole, MachineType from backend.db_meta.models import Cluster, Machine, ProxyInstance, StorageInstance from backend.db_meta.models.spec import Spec from backend.db_services.dbresource.constants import SWAGGER_TAG from backend.db_services.dbresource.exceptions import SpecOperateException from backend.db_services.dbresource.filters import SpecListFilter -from backend.db_services.dbresource.serializers import DeleteSpecSerializer, RecommendSpecSerializer, SpecSerializer +from backend.db_services.dbresource.serializers import ( + DeleteSpecSerializer, + RecommendResponseSpecSerializer, + RecommendSpecSerializer, + SpecSerializer, +) from backend.iam_app.handlers.drf_perm import GlobalManageIAMPermission @@ -109,6 +116,7 @@ def batch_delete(self, request, *args, **kwargs): @common_swagger_auto_schema( operation_summary=_("获取推荐规格"), query_serializer=RecommendSpecSerializer(), + responses={status.HTTP_200_OK: RecommendResponseSpecSerializer()}, tags=[SWAGGER_TAG], ) @action( @@ -120,8 +128,12 @@ def batch_delete(self, request, *args, **kwargs): ) def recommend_spec(self, request): data = self.params_validate(self.get_serializer_class()) - cluster = Cluster.objects.get(id=data["cluster_id"]) - filter_params = Q(cluster=cluster) & Q(role=data["role"]) + if data["role"] == InstanceRole.INFLUXDB: + # 如果是influxdb,则直接通过id查询即可 + filter_params = Q(role=data["role"]) & Q(id=data["instance_id"]) + else: + cluster = Cluster.objects.get(id=data["cluster_id"]) + filter_params = Q(cluster=cluster) & Q(role=data["role"]) spec_ids = list( StorageInstance.objects.annotate(role=F("instance_role")) @@ -132,3 +144,15 @@ def recommend_spec(self, request): spec_data = SpecSerializer(Spec.objects.filter(spec_id__in=spec_ids), many=True).data return Response(spec_data) + + def _remove_spec_fields(self, machine_type, data): + """移除无需的字段""" + remove_fields = [] + if machine_type != MachineType.ES_DATANODE: + remove_fields.append("instance_num") + + # TODO: 后续可增加其他特定字段排除 + + for d in data: + for field in remove_fields: + d.pop(field) diff --git a/dbm-ui/backend/db_services/redis/toolbox/serializers.py b/dbm-ui/backend/db_services/redis/toolbox/serializers.py index 305d62c3a8..a772b981eb 100644 --- a/dbm-ui/backend/db_services/redis/toolbox/serializers.py +++ b/dbm-ui/backend/db_services/redis/toolbox/serializers.py @@ -42,7 +42,6 @@ class Meta: "redis_master_count": 1, "redis_slave_count": 1, "region": "", - "deploy_plan_id": 0, "deploy_plan": { "id": 1, "name": "abc", @@ -100,7 +99,6 @@ class Meta: "redis_master_count": 1, "redis_slave_count": 1, "region": "", - "deploy_plan_id": 0, "deploy_plan": { "id": 1, "name": "abc", @@ -133,7 +131,6 @@ class Meta: "cluster_type": "TwemproxyRedisInstance", "bk_cloud_id": 0, "region": "", - "deploy_plan_id": 0, }, "master_ip": "127.0.0.1", "slave_ip": "127.0.0.2", diff --git a/dbm-ui/backend/flow/signal/handlers.py b/dbm-ui/backend/flow/signal/handlers.py index 9c7a162f66..07dd54fedb 100644 --- a/dbm-ui/backend/flow/signal/handlers.py +++ b/dbm-ui/backend/flow/signal/handlers.py @@ -18,10 +18,10 @@ from backend.flow.consts import StateType from backend.flow.engine.bamboo.engine import BambooEngine from backend.flow.models import FlowNode, FlowTree -from backend.ticket.constants import FlowCallbackType, FlowType, TicketFlowStatus +from backend.ticket.constants import BAMBOO_STATE__TICKET_STATE_MAP, FlowCallbackType, FlowType, TicketFlowStatus from backend.ticket.flow_manager.inner import InnerFlow from backend.ticket.flow_manager.manager import TicketFlowManager -from backend.ticket.models import Ticket +from backend.ticket.models import Flow, Ticket logger = logging.getLogger("flow") @@ -60,6 +60,7 @@ def post_set_state_signal_handler(sender, node_id, to_state, version, root_id, * target_tree_status = to_state if origin_tree_status != target_tree_status: + # 更新flow tree和inner flow的状态 tree.updated_at = now tree.status = target_tree_status tree.save() diff --git a/dbm-ui/backend/flow/utils/cc_manage.py b/dbm-ui/backend/flow/utils/cc_manage.py index d69e306288..1c0983594d 100644 --- a/dbm-ui/backend/flow/utils/cc_manage.py +++ b/dbm-ui/backend/flow/utils/cc_manage.py @@ -106,7 +106,12 @@ def transfer_host_module(cls, bk_host_ids: list, target_module_ids: list): 循环判断处理,逻辑保证幂等操作 """ + if not bk_host_ids: + # 有些角色允许为空,所以要忽略 + return + # 查询当前bk_hosts_ids的业务对应关系 + logger.info(f"bk_host_ids:{bk_host_ids}") hosts = CCApi.find_host_biz_relations({"bk_host_id": bk_host_ids}) biz_internal_module = CCApi.get_biz_internal_module({"bk_biz_id": env.DBA_APP_BK_BIZ_ID}, use_admin=True) diff --git a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py index b90a100151..87d23e6d78 100644 --- a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py +++ b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py @@ -262,7 +262,6 @@ def redis_make_cluster(self) -> bool: "storages": storages, "creator": self.ticket_data["created_by"], "region": self.ticket_data.get("city_code"), - "deploy_plan_id": self.ticket_data.get("deploy_plan_id"), } ) elif self.ticket_data["cluster_type"] == ClusterType.TwemproxyTendisSSDInstance.value: @@ -279,7 +278,6 @@ def redis_make_cluster(self) -> bool: "storages": storages, "creator": self.ticket_data["created_by"], "region": self.ticket_data.get("city_code"), - "deploy_plan_id": self.ticket_data.get("deploy_plan_id"), } ) @@ -314,7 +312,6 @@ def tendisplus_make_cluster(self) -> bool: "storages": storages, "creator": self.ticket_data["created_by"], "region": self.ticket_data.get("city_code"), - "deploy_plan_id": self.ticket_data.get("deploy_plan_id"), } ) return True diff --git a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py index a5e91048fd..208307994f 100644 --- a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py +++ b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py @@ -58,7 +58,6 @@ def tendb_cluster_apply(self): "creator": self.global_data["created_by"], "time_zone": self.cluster["time_zone_info"]["time_zone"], "bk_cloud_id": int(self.global_data["bk_cloud_id"]), - "deploy_plan_id": int(self.global_data["deploy_plan_id"]), "resource_spec": self.global_data["resource_spec"], "shard_infos": shard_infos, "region": self.global_data["city"], diff --git a/dbm-ui/backend/ticket/builders/es/es_apply.py b/dbm-ui/backend/ticket/builders/es/es_apply.py index a3d06aab34..afa0d8ab80 100644 --- a/dbm-ui/backend/ticket/builders/es/es_apply.py +++ b/dbm-ui/backend/ticket/builders/es/es_apply.py @@ -15,6 +15,7 @@ from rest_framework import serializers from backend.db_services.dbbase.constants import ES_DEFAULT_PORT, IpSource +from backend.flow.consts import ES_DEFAULT_INSTANCE_NUM from backend.flow.engine.controller.es import EsController from backend.ticket import builders from backend.ticket.builders.common import constants @@ -122,7 +123,7 @@ def fill_instance_num(cls, next_flow_data, ticket_data, nodes_key): continue for node in next_flow_data["nodes"][role]: - node["instance_num"] = ticket_data["resource_spec"][role]["instance_num"] + node["instance_num"] = ticket_data["resource_spec"][role].get("instance_num", ES_DEFAULT_INSTANCE_NUM) def post_callback(self): next_flow = self.ticket.next_flow() diff --git a/dbm-ui/backend/ticket/builders/es/es_scale_up.py b/dbm-ui/backend/ticket/builders/es/es_scale_up.py index fcd899f55c..de35e92d6c 100644 --- a/dbm-ui/backend/ticket/builders/es/es_scale_up.py +++ b/dbm-ui/backend/ticket/builders/es/es_scale_up.py @@ -31,7 +31,7 @@ class EsScaleUpDetailSerializer(BigDataScaleDetailSerializer): def validate(self, attrs): attrs = super().validate(attrs) - if attrs["ip_resource"] == IpSource.RESOURCE_POOL: + if attrs["ip_source"] == IpSource.RESOURCE_POOL: return attrs role_nodes_list = list(attrs["nodes"].values()) diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py b/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py index a09e024f0b..3c3a0d15b4 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py @@ -138,7 +138,8 @@ def format_cluster_domains(self) -> List[Dict[str, str]]: @classmethod def insert_ip_into_apply_infos(cls, ticket_data, apply_infos: List[Dict]): - backend_nodes = ticket_data["nodes"]["backend"] + # 适配手动输入和资源池导入的角色类型 + backend_nodes = ticket_data["nodes"]["backend"] or ticket_data["nodes"]["single"] for index, apply_info in enumerate(apply_infos): apply_info["new_ip"] = backend_nodes[index] diff --git a/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py b/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py index e8e55c49b7..4b77722e33 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py @@ -15,7 +15,6 @@ from backend.db_meta.enums import ClusterType from backend.db_meta.models import Machine -from backend.db_meta.models.spec import ClusterDeployPlan from backend.db_services.dbbase.constants import IpSource from backend.flow.engine.controller.redis import RedisController from backend.ticket import builders @@ -45,7 +44,7 @@ class RedisClusterApplyDetailSerializer(serializers.Serializer): nodes = serializers.JSONField(help_text=_("部署节点"), required=False) resource_spec = serializers.JSONField(help_text=_("proxy部署方案"), required=False) - resource_plan = serializers.JSONField(help_text=_("后台部署方案"), required=False) + cluster_shard_num = serializers.IntegerField(help_text=_("集群分片数"), required=False) def get_city_name(self, obj): city_code = obj["city_code"] @@ -242,13 +241,13 @@ def format_ticket_data(self): class RedisApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): def post_callback(self): next_flow = self.ticket.next_flow() - deploy_plan = ClusterDeployPlan.objects.get(id=self.ticket_data["resource_plan"]["resource_plan_id"]) + group_num = self.ticket_data["resource_spec"]["backend_group"]["count"] + shard_num = self.ticket_data["cluster_shard_num"] min_mem = min([host["master"]["bk_mem"] for host in self.ticket_data["nodes"]["backend_group"]]) - cluster_maxmemory = min_mem * deploy_plan.machine_pair_cnt // deploy_plan.shard_cnt - + cluster_maxmemory = min_mem * group_num // shard_num min_disk = min([host["master"]["bk_disk"] for host in self.ticket_data["nodes"]["backend_group"]]) - cluster_max_disk = min_disk * deploy_plan.machine_pair_cnt // deploy_plan.shard_cnt + cluster_max_disk = min_disk * group_num // shard_num next_flow.details["ticket_data"].update( # 分片大小, MB -> byte @@ -256,9 +255,9 @@ def post_callback(self): # 磁盘大小,单位是GB max_disk=int(cluster_max_disk), # 机器组数 - group_num=deploy_plan.machine_pair_cnt, + group_num=group_num, # 分片数 - shard_num=deploy_plan.shard_cnt, + shard_num=shard_num, ) next_flow.save(update_fields=["details"]) diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_apply.py b/dbm-ui/backend/ticket/builders/spider/tendb_apply.py index 920aa3ca00..31fa688bf4 100644 --- a/dbm-ui/backend/ticket/builders/spider/tendb_apply.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_apply.py @@ -16,7 +16,6 @@ from backend.components import DBConfigApi from backend.components.dbconfig import constants as dbconf_const from backend.db_meta.enums import ClusterType -from backend.db_meta.models import ClusterDeployPlan, Spec from backend.db_services.dbbase.constants import IpSource from backend.db_services.ipchooser.query.resource import ResourceQueryHelper from backend.flow.engine.controller.spider import SpiderController @@ -36,8 +35,10 @@ class TenDBClusterApplyDetailSerializer(serializers.Serializer): help_text=_("主机来源"), choices=IpSource.get_choices(), default=IpSource.RESOURCE_POOL.value ) resource_spec = serializers.JSONField(help_text=_("部署规格")) - resource_plan = serializers.JSONField(help_text=_("部署方案")) spider_port = serializers.IntegerField(help_text=_("集群访问端口")) + cluster_shard_num = serializers.IntegerField(help_text=_("集群分片数")) + cluster_capacity = serializers.IntegerField(help_text=_("集群容量")) + cluster_qps = serializers.CharField(help_text=_("集群QPS")) immutable_domain = serializers.CharField(help_text=_("集群访问域名")) # display fields @@ -46,7 +47,6 @@ class TenDBClusterApplyDetailSerializer(serializers.Serializer): version = serializers.SerializerMethodField(help_text=_("数据库版本")) db_module_name = serializers.SerializerMethodField(help_text=_("DB模块名")) city_name = serializers.SerializerMethodField(help_text=_("城市名")) - cluster_shard_num = serializers.SerializerMethodField(help_text=_("集群分片数")) machine_pair_cnt = serializers.SerializerMethodField(help_text=_("机器数")) def get_bk_cloud_name(self, obj): @@ -67,9 +67,6 @@ def get_city_name(self, obj): city_code = obj["city_code"] return self.context["ticket_ctx"].city_map.get(city_code, city_code) - def get_cluster_shard_num(self, obj): - return obj["cluster_shard_num"] - def get_machine_pair_cnt(self, obj): return obj["machine_pair_cnt"] @@ -95,19 +92,8 @@ def post_callback(self): nodes = next_flow.details["ticket_data"].pop("nodes") # 格式化后台角色信息 - spider_ip_list = nodes["spider"] - mysql_ip_list = [] - for backend_pair in nodes["backend_group"]: - mysql_ip_list.extend([backend_pair["master"], backend_pair["slave"]]) - - # 补充remote的规格信息 - resource_spec = next_flow.details["ticket_data"]["resource_spec"] - resource_spec["remote"] = resource_spec.pop("master") - resource_spec.pop("slave") - - next_flow.details["ticket_data"].update( - spider_ip_list=spider_ip_list, mysql_ip_list=mysql_ip_list, resource_spec=resource_spec - ) + spider_ip_list, mysql_ip_list = nodes["spider"], nodes["remote"] + next_flow.details["ticket_data"].update(spider_ip_list=spider_ip_list, mysql_ip_list=mysql_ip_list) next_flow.save(update_fields=["details"]) @@ -121,15 +107,6 @@ class TenDBClusterApplyFlowBuilder(BaseTendbTicketFlowBuilder): def patch_ticket_detail(self): """补充spider申请的需求信息参数""" details = self.ticket.details - - # 补充部署方案信息 - deploy_plan = ClusterDeployPlan.objects.get(id=details["resource_plan"]["resource_plan_id"]) - details.update( - deploy_plan_name=deploy_plan.name, - cluster_shard_num=deploy_plan.shard_cnt, - machine_pair_cnt=deploy_plan.machine_pair_cnt, - ) - # 补充字符集和版本信息 db_config = DBConfigApi.query_conf_item( { @@ -146,10 +123,6 @@ def patch_ticket_detail(self): charset=db_config.get("charset"), db_version=db_config.get("db_version"), spider_version=db_config.get("spider_version"), - # TODO: 暂时为了测试用,后续可以删除这些参数 - start_mysql_port=21000, - ctl_charset=db_config.get("charset"), - spider_charset=db_config.get("charset"), ) self.ticket.save(update_fields=["details"]) diff --git a/dbm-ui/backend/ticket/constants.py b/dbm-ui/backend/ticket/constants.py index e79dc883e0..5bf4d0ff76 100644 --- a/dbm-ui/backend/ticket/constants.py +++ b/dbm-ui/backend/ticket/constants.py @@ -96,6 +96,7 @@ class TicketFlowStatus(str, StructuredEnum): StateType.FINISHED.value: TicketFlowStatus.SUCCEEDED.value, StateType.FAILED.value: TicketFlowStatus.FAILED.value, StateType.REVOKED.value: TicketFlowStatus.REVOKED.value, + StateType.RUNNING.value: TicketFlowStatus.RUNNING.value, } EXCLUSIVE_TICKET_EXCEL_PATH = "backend/ticket/exclusive_ticket.xlsx" diff --git a/dbm-ui/backend/ticket/flow_manager/base.py b/dbm-ui/backend/ticket/flow_manager/base.py index f8896f7902..fa95256df7 100644 --- a/dbm-ui/backend/ticket/flow_manager/base.py +++ b/dbm-ui/backend/ticket/flow_manager/base.py @@ -48,8 +48,10 @@ def status(self) -> str: return TicketFlowStatus.FAILED - if self.flow_obj.flow_obj_id or self.flow_obj.status == TicketFlowStatus.RUNNING: + if self.flow_obj.status in [TicketFlowStatus.RUNNING, TicketFlowStatus.FAILED]: # ticket flow 创建成功,查询对应状态 + # 1. 如果是running状态,则查询对应子flow的status + # 2. 如果是failed状态,但不包含err_msg,说明是异步任务导致的(inner flow),也要查询对应状态(因为存在重试可能) return self._status if not self.flow_obj.flow_obj_id: diff --git a/dbm-ui/backend/ticket/flow_manager/inner.py b/dbm-ui/backend/ticket/flow_manager/inner.py index 99f0e59c2f..033b438ea0 100644 --- a/dbm-ui/backend/ticket/flow_manager/inner.py +++ b/dbm-ui/backend/ticket/flow_manager/inner.py @@ -162,7 +162,8 @@ def callback(self, callback_type: FlowCallbackType) -> None: def run(self) -> None: """inner flow执行流程""" - root_id = f"{date.today()}{uuid.uuid1().hex[:6]}".replace("-", "") + # 获取or生成inner flow的root id + root_id = self.flow_obj.flow_obj_id or f"{date.today()}{uuid.uuid1().hex[:6]}".replace("-", "") try: # 判断执行互斥 self.check_exclusive_operations() diff --git a/dbm-ui/backend/ticket/flow_manager/resource.py b/dbm-ui/backend/ticket/flow_manager/resource.py index 0e4a009ed9..acb2d957d8 100644 --- a/dbm-ui/backend/ticket/flow_manager/resource.py +++ b/dbm-ui/backend/ticket/flow_manager/resource.py @@ -19,14 +19,12 @@ from backend.components.dbresource.client import DBResourceApi from backend.db_meta.models import Spec -from backend.db_meta.models.spec import ClusterDeployPlan from backend.db_services.dbresource.exceptions import ResourceApplyException from backend.ticket import constants from backend.ticket.constants import AffinityEnum, FlowCallbackType, FlowType from backend.ticket.flow_manager.base import BaseTicketFlow from backend.ticket.flow_manager.delivery import DeliveryFlow from backend.ticket.models import Flow -from backend.utils.batch_request import request_multi_thread from backend.utils.time import datetime2str @@ -105,7 +103,8 @@ def apply_resource(self, ticket_data): "for_biz_id": ticket_data["bk_biz_id"], "resource_type": self.ticket.group, "bill_id": str(self.ticket.id), - "task_id": self.flow_obj.flow_obj_id, + # 消费情况下的task id为inner flow + "task_id": self.ticket.next_flow().flow_obj_id, "operator": self.ticket.creator, "details": self.fetch_apply_params(ticket_data), } @@ -138,58 +137,51 @@ def fetch_apply_params(self, ticket_data): details: List[Dict[str, Any]] = [] # 根据规格来填充相应机器的申请参数 - if "resource_spec" in ticket_data: - resource_spec = ticket_data["resource_spec"] - for role, role_spec in resource_spec.items(): + resource_spec = ticket_data["resource_spec"] + for role, role_spec in resource_spec.items(): + # 如果该存在无需申请,则跳过 + if not role_spec["count"]: + continue + # 填充规格申请参数 + if role == "backend_group": + details.extend( + Spec.objects.get(spec_id=role_spec["spec_id"]).get_backend_group_apply_params_detail( + bk_cloud_id=bk_cloud_id, backend_group=role_spec + ) + ) + else: details.append( Spec.objects.get(spec_id=role_spec["spec_id"]).get_apply_params_detail( group_mark=role, - count=role_spec["count"], + count=int(role_spec["count"]), bk_cloud_id=bk_cloud_id, - affinity=role_spec.get("affinity", AffinityEnum.NONE), + affinity=role_spec.get("affinity", AffinityEnum.NONE.value), ) ) - # 根据部署方案来填充相应机器的申请参数 - if "resource_plan" in ticket_data: - resource_plan = ticket_data["resource_plan"] - details.extend( - ClusterDeployPlan.objects.get(id=resource_plan["resource_plan_id"]).get_apply_params_details( - bk_cloud_id=bk_cloud_id, affinity=resource_plan.get("affinity", AffinityEnum.NONE) - ) - ) - return details - def patch_resource_params( - self, ticket_data, spec_map: Dict[int, Spec] = None, deploy_plan_map: Dict[int, ClusterDeployPlan] = None - ): + def patch_resource_params(self, ticket_data, spec_map: Dict[int, Spec] = None): """ - 将资源池部署信息写入到ticket_data + 将资源池部署信息写入到ticket_data。 @param ticket_data: 待填充的字典 @param spec_map: 规格缓存数据, 避免频繁查询数据库 - @param deploy_plan_map: 部署方案缓存数据,避免频繁查询数据库 """ spec_map = spec_map or {} - deploy_plan_map = deploy_plan_map or {} - - if "resource_spec" in ticket_data: - resource_spec = ticket_data["resource_spec"] - for role, role_spec in resource_spec.items(): - spec = spec_map.get(role_spec["spec_id"]) or Spec.objects.get(spec_id=role_spec["spec_id"]) - resource_spec[role] = { - **spec.get_spec_info(), - "count": role_spec["count"], - } - - if "resource_plan" in ticket_data: - # 如果是部署规格,默认规格角色是master和slave,如果需要其他角色类型在post callback钩子函数修改 - deploy_plan_id = ticket_data["resource_plan"]["resource_plan_id"] - ticket_data.update(deploy_plan_id=deploy_plan_id) - deploy_plan = deploy_plan_map.get(deploy_plan_id) or ClusterDeployPlan.objects.get(id=deploy_plan_id) - master_spec = slave_spec = {**deploy_plan.spec.get_spec_info(), "count": deploy_plan.machine_pair_cnt} - ticket_data["resource_spec"].update(master=master_spec, slave=slave_spec) + resource_spec = ticket_data["resource_spec"] + for role, role_spec in resource_spec.items(): + # 如果该存在无需申请,则跳过 + if not role_spec["count"]: + continue + + spec = spec_map.get(role_spec["spec_id"]) or Spec.objects.get(spec_id=role_spec["spec_id"]) + role_info = {**spec.get_spec_info(), "count": role_spec["count"]} + # 如果角色是backend_group,则默认角色信息写入master和slave + if role == "backend_group": + resource_spec["master"] = resource_spec["slave"] = role_info + else: + resource_spec[role] = role_info def write_node_infos(self, ticket_data, node_infos): """将资源申请信息写入ticket_data""" @@ -200,6 +192,10 @@ def _run(self) -> None: if next_flow.flow_type != FlowType.INNER_FLOW: raise ResourceApplyException(_("资源申请下一个节点不为部署节点,请重新编排")) + # 提前为inner flow生成root id,要写入操作记录中 + next_flow.flow_obj_id = f"{date.today()}{uuid.uuid1().hex[:6]}".replace("-", "") + next_flow.save() + # 资源申请 resource_request_id, node_infos = self.apply_resource(self.flow_obj.details) @@ -236,18 +232,13 @@ class ResourceBatchApplyFlow(ResourceApplyFlow): def patch_resource_params(self, ticket_data): spec_ids: List[int] = [] - deploy_plan_ids: List[int] = [] for info in ticket_data["infos"]: spec_ids.extend([data["spec_id"] for data in info["resource_spec"].values()]) - if info.get("resource_plan"): - deploy_plan_ids.append(info["resource_plan"]["resource_plan_id"]) # 提前缓存数据库查询数据,避免多次IO spec_map = {spec.spec_id: spec for spec in Spec.objects.filter(spec_id__in=spec_ids)} - deploy_plan_map = {plan.id: plan for plan in ClusterDeployPlan.objects.filter(id__in=deploy_plan_ids)} - for info in ticket_data["infos"]: - super().patch_resource_params(info, spec_map, deploy_plan_map) + super().patch_resource_params(info, spec_map) def write_node_infos(self, ticket_data, node_infos): """ diff --git a/dbm-ui/backend/ticket/models/ticket.py b/dbm-ui/backend/ticket/models/ticket.py index 4e91923438..ff11665b97 100644 --- a/dbm-ui/backend/ticket/models/ticket.py +++ b/dbm-ui/backend/ticket/models/ticket.py @@ -142,7 +142,7 @@ def current_flow(self) -> Flow: def next_flow(self) -> Flow: """ - 下一个流程,即 TicketFlow 中第一个 flow_obj_id 为空的流程 + 下一个流程,即 TicketFlow 中第一个为PENDING的流程 """ next_flows = Flow.objects.filter(ticket=self, status=TicketFlowStatus.PENDING) From 527f3a29497a6825a7b11acd5251b7706d71bf35 Mon Sep 17 00:00:00 2001 From: xfwduke Date: Wed, 5 Jul 2023 12:02:11 +0800 Subject: [PATCH 094/476] =?UTF-8?q?feat(mysql):=20dbha=20api=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20tendbcluster=20=E6=94=AF=E6=8C=81=20close=20#391?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_meta/api/dbha/apis.py | 15 ++- dbm-ui/backend/db_meta/api/fake/__init__.py | 1 + .../db_meta/api/fake/fake_tendbcluster.py | 102 ++++++++++++++++++ .../backend/db_meta/flatten/proxy_instance.py | 7 +- dbm-ui/backend/db_meta/urls.py | 5 + dbm-ui/backend/db_meta/views/fake/views.py | 10 ++ 6 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 dbm-ui/backend/db_meta/api/fake/fake_tendbcluster.py diff --git a/dbm-ui/backend/db_meta/api/dbha/apis.py b/dbm-ui/backend/db_meta/api/dbha/apis.py index 7b02019bd8..688598ac29 100644 --- a/dbm-ui/backend/db_meta/api/dbha/apis.py +++ b/dbm-ui/backend/db_meta/api/dbha/apis.py @@ -46,7 +46,20 @@ def entry_detail(domains: List[str]) -> List[Dict]: for cluster_entry_obj in cluster_obj.clusterentry_set.all(): if cluster_entry_obj.cluster_entry_type == ClusterEntryType.DNS: - clusterentry_set[cluster_entry_obj.cluster_entry_type].append({"domain": cluster_entry_obj.entry}) + clusterentry_set[cluster_entry_obj.cluster_entry_type].append( + { + "domain": cluster_entry_obj.entry, + "bind_ips": list( + set( + [ + ele.machine.ip + for ele in list(cluster_entry_obj.proxyinstance_set.all()) + + list(cluster_entry_obj.storageinstance_set.all()) + ] + ) + ), + } + ) elif cluster_entry_obj.cluster_entry_type == ClusterEntryType.CLB: de = cluster_entry_obj.clbentrydetail_set.get() clusterentry_set[cluster_entry_obj.cluster_entry_type].append( diff --git a/dbm-ui/backend/db_meta/api/fake/__init__.py b/dbm-ui/backend/db_meta/api/fake/__init__.py index 72fb0d852e..c34517ddd1 100644 --- a/dbm-ui/backend/db_meta/api/fake/__init__.py +++ b/dbm-ui/backend/db_meta/api/fake/__init__.py @@ -8,5 +8,6 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ +from .fake_tendbcluster import fake_reset_tendbcluster_cluster from .fake_tendbha import fake_create_tendbha_cluster, fake_reset_tendbha_cluster from .fake_tendbsingle import fake_create_tendbsingle diff --git a/dbm-ui/backend/db_meta/api/fake/fake_tendbcluster.py b/dbm-ui/backend/db_meta/api/fake/fake_tendbcluster.py new file mode 100644 index 0000000000..4f07749aae --- /dev/null +++ b/dbm-ui/backend/db_meta/api/fake/fake_tendbcluster.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from typing import Dict, List, Optional + +from django.db import transaction +from django.db.models import Q + +from backend.constants import IP_PORT_DIVIDER +from backend.db_meta.enums import ClusterType, InstanceInnerRole, InstanceRole, InstanceStatus +from backend.db_meta.models import ( + Cluster, + ClusterEntry, + ProxyInstance, + StorageInstance, + StorageInstanceTuple, + TenDBClusterStorageSet, +) + + +@transaction.atomic +def fake_reset_tendbcluster_cluster( + spider_masters: List[str], + immute_domain: str, + storage_sets: List[Dict], + spider_slaves: Optional[List[str]] = None, + slave_domain: Optional[str] = None, +): + """ + storage_sets: [ + { + "master_instance": "a.b.c.d:20000", + "slave_instance": "e.f.g.h:20000", + } + ... + ] + """ + cluster = Cluster.objects.get(immute_domain=immute_domain, cluster_type=ClusterType.TenDBCluster) + master_entry = ClusterEntry.objects.get(entry=immute_domain, cluster=cluster) + master_entry.proxyinstance_set.clear() + + TenDBClusterStorageSet.objects.filter(cluster=cluster).delete() + + for idx, storage_set in enumerate(storage_sets): + [master_ip, master_port] = storage_set["master_instance"].split(IP_PORT_DIVIDER) + master_obj = StorageInstance.objects.get(machine__ip=master_ip, port=master_port, cluster=cluster) + master_obj.instance_role = InstanceRole.REMOTE_MASTER.value + master_obj.instance_inner_role = InstanceInnerRole.MASTER.value + master_obj.status = InstanceStatus.RUNNING.value + master_obj.save(update_fields=["instance_role", "instance_inner_role", "status"]) + + [slave_ip, slave_port] = storage_set["slave_instance"].split(IP_PORT_DIVIDER) + slave_obj = StorageInstance.objects.get(machine__ip=slave_ip, port=slave_port, cluster=cluster) + slave_obj.instance_role = InstanceRole.REMOTE_SLAVE.value + slave_obj.instance_inner_role = InstanceInnerRole.SLAVE.value + slave_obj.status = InstanceStatus.RUNNING.value + slave_obj.save(update_fields=["instance_role", "instance_inner_role", "status"]) + + StorageInstanceTuple.objects.filter( + (Q(ejector=master_obj) & Q(receiver=slave_obj)) | (Q(ejector=slave_obj) & Q(receiver=master_obj)) + ).delete() + + st_obj = StorageInstanceTuple.objects.create(ejector=master_obj, receiver=slave_obj) + TenDBClusterStorageSet.objects.create(shard_id=idx, cluster=cluster, storage_instance_tuple=st_obj) + + for spider_master in spider_masters: + [spider_ip, spider_port] = spider_master.split(IP_PORT_DIVIDER) + spider_obj = ProxyInstance.objects.get(machine__ip=spider_ip, port=spider_port, cluster=cluster) + spider_obj.storageinstance.clear() + spider_obj.storageinstance.add( + *list( + StorageInstance.objects.filter(cluster=cluster, instance_role=InstanceRole.REMOTE_MASTER.value).all() + ) + ) + spider_obj.status = InstanceStatus.RUNNING.value + spider_obj.save(update_fields=["status"]) + master_entry.proxyinstance_set.add(spider_obj) + + if slave_domain and spider_slaves: + slave_entry = ClusterEntry.objects.get(entry=slave_domain, cluster=cluster) + slave_entry.storageinstance_set.clear() + for spider_slave in spider_slaves: + [spider_ip, spider_port] = spider_slave.split(IP_PORT_DIVIDER) + spider_obj = ProxyInstance.objects.get(machine__ip=spider_ip, port=spider_port, cluster=cluster) + spider_obj.storageinstance.clear() + spider_obj.storageinstance.add( + *list( + StorageInstance.objects.filter( + cluster=cluster, instance_role=InstanceRole.REMOTE_SLAVE.value + ).all() + ) + ) + spider_obj.status = InstanceStatus.RUNNING.value + spider_obj.save(update_fields=["status"]) + slave_entry.proxyinstance_set.add(spider_obj) diff --git a/dbm-ui/backend/db_meta/flatten/proxy_instance.py b/dbm-ui/backend/db_meta/flatten/proxy_instance.py index a81cf9b274..9793f05590 100644 --- a/dbm-ui/backend/db_meta/flatten/proxy_instance.py +++ b/dbm-ui/backend/db_meta/flatten/proxy_instance.py @@ -14,7 +14,9 @@ from django.db.models import QuerySet -from ..models import ProxyInstance +from backend.db_meta.enums import MachineType +from backend.db_meta.models import ProxyInstance + from .machine import _machine_prefetch, _single_machine_cc_info, _single_machine_city_info logger = logging.getLogger("root") @@ -46,6 +48,9 @@ def proxy_instance(proxies: QuerySet) -> List[Dict]: "status": ins.status, } + if ins.machine_type == MachineType.SPIDER.value: + info["spider_role"] = ins.tendbclusterspiderext.spider_role + storageinstance = [] for s in ins.storageinstance.all(): sinfo = {"ip": s.machine.ip, "port": s.port, "is_stand_by": s.is_stand_by} diff --git a/dbm-ui/backend/db_meta/urls.py b/dbm-ui/backend/db_meta/urls.py index 79024f2cfc..989b67c9d2 100644 --- a/dbm-ui/backend/db_meta/urls.py +++ b/dbm-ui/backend/db_meta/urls.py @@ -115,4 +115,9 @@ views.fake.fake_reset_tendbha_cluster, name="fake-tendbha-reset_cluster", ), + path( + "fake/tendbcluster/reset_cluster", + views.fake.fake_reset_tendbcluster_cluster, + name="fake-tendbcluster-reset_cluster", + ), ] diff --git a/dbm-ui/backend/db_meta/views/fake/views.py b/dbm-ui/backend/db_meta/views/fake/views.py index 84e6cc4e0c..c8a779d3b2 100644 --- a/dbm-ui/backend/db_meta/views/fake/views.py +++ b/dbm-ui/backend/db_meta/views/fake/views.py @@ -80,3 +80,13 @@ def fake_reset_tendbha_cluster(request: Request): return JsonResponse({"msg": "", "code": 0, "data": api.fake.fake_reset_tendbha_cluster(**request.data)}) except Exception as e: # pylint: disable=broad-except return JsonResponse({"msg": "{}".format(e), "code": 1, "data": ""}) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fake_reset_tendbcluster_cluster(request: Request): + try: + return JsonResponse({"msg": "", "code": 0, "data": api.fake.fake_reset_tendbcluster_cluster(**request.data)}) + except Exception as e: # pylint: disable=broad-except + return JsonResponse({"msg": "{}".format(e), "code": 1, "data": ""}) From 66203185881510673b778bf1c8bbe677bd76ea4b Mon Sep 17 00:00:00 2001 From: stellanduan Date: Wed, 5 Jul 2023 16:07:59 +0800 Subject: [PATCH 095/476] feat(mysql): mysql-backup support official mysql close #401 --- .../mysql/db-tools/mysql-dbbackup/cmd/root.go | 2 +- .../pkg/src/backupexe/dumper_logical.go | 1 + .../pkg/src/backupexe/dumper_physical.go | 20 +++-- .../mysql-dbbackup/pkg/src/backupexe/env.go | 86 ++++++++++++++----- .../pkg/src/backupexe/execute_dump.go | 15 +++- .../pkg/src/backupexe/execute_load.go | 8 +- .../mysql-dbbackup/pkg/src/backupexe/grant.go | 5 +- .../pkg/src/backupexe/loader_logical.go | 1 + .../pkg/src/backupexe/loader_physical.go | 29 +++++-- .../pkg/src/precheck/check_charset.go | 3 +- .../db-tools/mysql-dbbackup/pkg/util/misc.go | 17 ++-- 11 files changed, 137 insertions(+), 50 deletions(-) diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/cmd/root.go b/dbm-services/mysql/db-tools/mysql-dbbackup/cmd/root.go index b6de534b07..9e340e27ac 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/cmd/root.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/cmd/root.go @@ -11,7 +11,7 @@ import ( ) // DbbackupVersion TODO -var DbbackupVersion = "1.0.2" +var DbbackupVersion = "1.0.3" var cnfFile string diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_logical.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_logical.go index 16ced7565d..c2fa9c358f 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_logical.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_logical.go @@ -110,6 +110,7 @@ func (l *LogicalDumper) initConfig() error { // return nil //} +// Execute excute dumping backup with logical backup tool func (l *LogicalDumper) Execute(enableTimeOut bool) error { binPath := filepath.Join(l.dbbackupHome, "/bin/mydumper") args := []string{ diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_physical.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_physical.go index beb55bfa8c..e0df64168f 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_physical.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/dumper_physical.go @@ -24,6 +24,7 @@ type PhysicalDumper struct { mysqlVersion string innodbCmd InnodbCommand storageEngine string + isOfficial bool } func (p *PhysicalDumper) initConfig() error { @@ -46,14 +47,16 @@ func (p *PhysicalDumper) initConfig() error { if verErr != nil { return verErr } - p.mysqlVersion = util.VersionParser(versionStr) + p.mysqlVersion, p.isOfficial = util.VersionParser(versionStr) p.storageEngine, err = mysqlconn.GetStorageEngine(db) if err != nil { return err } p.storageEngine = strings.ToLower(p.storageEngine) - p.innodbCmd.ChooseXtrabackupTool(p.mysqlVersion) + if err := p.innodbCmd.ChooseXtrabackupTool(p.mysqlVersion, p.isOfficial); err != nil { + return err + } return nil } @@ -137,6 +140,7 @@ func (p *PhysicalDumper) initConfig() error { // return nil //} +// Execute excute dumping backup with physical backup tool func (p *PhysicalDumper) Execute(enableTimeOut bool) error { if p.storageEngine != "innodb" { err := fmt.Errorf("%s engine not support", p.storageEngine) @@ -144,7 +148,7 @@ func (p *PhysicalDumper) Execute(enableTimeOut bool) error { return err } - binPath := filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.innobackupexBin) + binPath := filepath.Join(p.dbbackupHome, p.innodbCmd.innobackupexBin) args := []string{ fmt.Sprintf("--defaults-file=%s", p.cnf.PhysicalBackup.DefaultsFile), fmt.Sprintf("--host=%s", p.cnf.Public.MysqlHost), @@ -152,7 +156,7 @@ func (p *PhysicalDumper) Execute(enableTimeOut bool) error { fmt.Sprintf("--user=%s", p.cnf.Public.MysqlUser), fmt.Sprintf("--password=%s", p.cnf.Public.MysqlPasswd), fmt.Sprintf( - "--ibbackup=%s", filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.xtrabackupBin)), + "--ibbackup=%s", filepath.Join(p.dbbackupHome, p.innodbCmd.xtrabackupBin)), "--no-timestamp", "--compress", "--lazy-backup-non-innodb", @@ -171,7 +175,7 @@ func (p *PhysicalDumper) Execute(enableTimeOut bool) error { if p.cnf.PhysicalBackup.Threads > 0 { args = append(args, []string{ - fmt.Sprintf("--compress-thread=%d", p.cnf.PhysicalBackup.Threads), + fmt.Sprintf("--compress-threads=%d", p.cnf.PhysicalBackup.Threads), fmt.Sprintf("--parallel=%d", p.cnf.PhysicalBackup.Threads), }...) } @@ -188,6 +192,10 @@ func (p *PhysicalDumper) Execute(enableTimeOut bool) error { }...) } + if strings.Compare(p.mysqlVersion, "008000000") >= 0 && p.isOfficial { + args = append(args, "--skip-strict") + } + // ToDo extropt var cmd *exec.Cmd @@ -211,7 +219,7 @@ func (p *PhysicalDumper) Execute(enableTimeOut bool) error { filepath.Join( p.dbbackupHome, "logs", - fmt.Sprintf("mydumper_%d.log", int(time.Now().Weekday())))) + fmt.Sprintf("xtrabackup_%d.log", int(time.Now().Weekday())))) if err != nil { logger.Log.Error("create log file failed: ", err) return err diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/env.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/env.go index 44428b5dc6..317c53a305 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/env.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/env.go @@ -1,6 +1,7 @@ package backupexe import ( + "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util" "encoding/json" "fmt" "os" @@ -18,44 +19,83 @@ type InnodbCommand struct { } // ChooseXtrabackupTool Decide the version of xtrabackup tool -func (i *InnodbCommand) ChooseXtrabackupTool(mysqlVersion string) { - i.innobackupexBin = "innobackupex.pl" - i.xtrabackupBin = "xtrabackup" - if strings.Compare(mysqlVersion, "005006000") >= 0 && - strings.Compare(mysqlVersion, "005007000") < 0 { - i.innobackupexBin = "innobackupex_56.pl" - i.xtrabackupBin = "xtrabackup_56" - } else if strings.Compare(mysqlVersion, "005007000") >= 0 && - strings.Compare(mysqlVersion, "008000000") < 0 { - i.innobackupexBin = "xtrabackup_57" - i.xtrabackupBin = "xtrabackup_57" - } else if strings.Compare(mysqlVersion, "008000000") >= 0 { - i.innobackupexBin = "xtrabackup_80" - i.xtrabackupBin = "xtrabackup_80" +func (i *InnodbCommand) ChooseXtrabackupTool(mysqlVersion string, isOfficial bool) error { + if !isOfficial { + if strings.Compare(mysqlVersion, "005005000") >= 0 && + strings.Compare(mysqlVersion, "005006000") < 0 { + // tmysql 5.5 + i.innobackupexBin = "/bin/xtrabackup/innobackupex_55.pl" + i.xtrabackupBin = "/bin/xtrabackup/xtrabackup_55" + } else if strings.Compare(mysqlVersion, "005006000") >= 0 && + strings.Compare(mysqlVersion, "005007000") < 0 { + // tmysql 5.6 + i.innobackupexBin = "/bin/xtrabackup/innobackupex_56.pl" + i.xtrabackupBin = "/bin/xtrabackup/xtrabackup_56" + } else if strings.Compare(mysqlVersion, "005007000") >= 0 && + strings.Compare(mysqlVersion, "008000000") < 0 { + // tmysql 5.7 + i.innobackupexBin = "/bin/xtrabackup/xtrabackup_57" + i.xtrabackupBin = "/bin/xtrabackup/xtrabackup_57" + } else if strings.Compare(mysqlVersion, "008000000") >= 0 { + // tmysql 8.0 + i.innobackupexBin = "/bin/xtrabackup/xtrabackup_80" + i.xtrabackupBin = "/bin/xtrabackup/xtrabackup_80" + } else { + return fmt.Errorf("unrecognizable mysql version") + } + } else { + if strings.Compare(mysqlVersion, "005007000") >= 0 && + strings.Compare(mysqlVersion, "008000000") < 0 { + // official_mysql_5.7 + i.innobackupexBin = "/bin/xtrabackup_official/xtrabackup_57/xtrabackup" + i.xtrabackupBin = "/bin/xtrabackup_official/xtrabackup_57/xtrabackup" + } else if strings.Compare(mysqlVersion, "008000000") >= 0 { + //official_mysql_8.0 + i.innobackupexBin = "/bin/xtrabackup_official/xtrabackup_80/xtrabackup" + i.xtrabackupBin = "/bin/xtrabackup_official/xtrabackup_80/xtrabackup" + } else { + return fmt.Errorf("unrecognizable mysql version") + } } + return nil } // SetEnv set env variables -func SetEnv() error { - exepath, err := os.Executable() +func SetEnv(backupType string, mysqlVersionStr string) error { + exePath, err := os.Executable() if err != nil { return err } - exepath = filepath.Dir(exepath) - libpath := filepath.Join(exepath, "lib/libmydumper") - libpath2 := filepath.Join(exepath, "lib/libxtra") - libpath3 := filepath.Join(exepath, "lib/libxtra_80") - binpath := filepath.Join(exepath, "bin/xtrabackup") + exePath = filepath.Dir(exePath) + var libPath string + if strings.ToLower(backupType) == "logical" { + libPath = filepath.Join(exePath, "lib/libmydumper") + } else if strings.ToLower(backupType) == "physical" { + _, isOfficial := util.VersionParser(mysqlVersionStr) + if !isOfficial { + libPath = filepath.Join(exePath, "lib/libxtra:") + libPath += filepath.Join(exePath, "lib/libxtra_80") + } else { + libPath = filepath.Join(exePath, "lib/libxtra_57_official/private:") + libPath += filepath.Join(exePath, "lib/libxtra_57_official/plugin:") + libPath += filepath.Join(exePath, "lib/libxtra_80_official/private:") + libPath += filepath.Join(exePath, "lib/libxtra_80_official/plugin") + } + } else { + return fmt.Errorf("setEnv: unknown backupType") + } + logger.Log.Info("libPath:", libPath) + binPath := filepath.Join(exePath, "bin/xtrabackup") oldLibs := strings.Split(os.Getenv("LD_LIBRARY_PATH"), ":") - oldLibs = append(oldLibs, libpath, libpath2, libpath3) + oldLibs = append(oldLibs, libPath) err = os.Setenv("LD_LIBRARY_PATH", strings.Join(oldLibs, ":")) if err != nil { logger.Log.Error("failed to set env variable", err) return err } oldPaths := strings.Split(os.Getenv("PATH"), ":") - oldPaths = append(oldPaths, binpath) + oldPaths = append(oldPaths, binPath) err = os.Setenv("PATH", strings.Join(oldPaths, ":")) if err != nil { logger.Log.Error("failed to set env variable", err) diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_dump.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_dump.go index c60ea2d2ca..2ea0bd1576 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_dump.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_dump.go @@ -1,6 +1,7 @@ package backupexe import ( + "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/mysqlconn" "strings" "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/config" @@ -9,7 +10,19 @@ import ( // ExecuteBackup execute dump backup command func ExecuteBackup(cnf *config.BackupConfig) error { - if envErr := SetEnv(); envErr != nil { + // get mysql version from mysql server, and then set env variables + db, err := mysqlconn.InitConn(&cnf.Public) + if err != nil { + return err + } + defer func() { + _ = db.Close() + }() + versionStr, verErr := mysqlconn.GetMysqlVersion(db) + if verErr != nil { + return verErr + } + if envErr := SetEnv(cnf.Public.BackupType, versionStr); envErr != nil { return envErr } diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_load.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_load.go index 49dc89e5bb..f734bbb494 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_load.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/execute_load.go @@ -16,10 +16,6 @@ func ExecuteLoad(cnf *config.BackupConfig) error { } } - if envErr := SetEnv(); envErr != nil { - return envErr - } - var indexPath string if cnf.LogicalLoad.IndexFilePath != "" { indexPath = cnf.LogicalLoad.IndexFilePath @@ -32,6 +28,10 @@ func ExecuteLoad(cnf *config.BackupConfig) error { return err } + if envErr := SetEnv(indexFileContent.BackupType, indexFileContent.MysqlVersion); envErr != nil { + return envErr + } + loader, err := BuildLoader(cnf, indexFileContent.BackupType) if err != nil { return err diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/grant.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/grant.go index 1ae878fb7b..34349f6630 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/grant.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/grant.go @@ -63,6 +63,7 @@ func GrantBackup(cfg *config.Public) error { writer := bufio.NewWriter(file) version, verErr := mysqlconn.GetMysqlVersion(db) + verStr, _ := util.VersionParser(version) if verErr != nil { return verErr } @@ -75,7 +76,7 @@ func GrantBackup(cfg *config.Public) error { } var grantInfo string - if strings.Compare(util.VersionParser(version), "005007000") >= 0 { // mysql.version >=5.7 + if strings.Compare(verStr, "005007000") >= 0 { // mysql.version >=5.7 sqlString := strings.Join([]string{"show create user `", user, "`@`", host, "`"}, "") gRows, err := db.Query(sqlString) if err != nil { @@ -132,7 +133,7 @@ func GrantBackup(cfg *config.Public) error { return err } - if strings.Compare(util.VersionParser(version), "005007000") >= 0 { // mysql.version >=5.7 + if strings.Compare(verStr, "005007000") >= 0 { // mysql.version >=5.7 cmdStr := fmt.Sprintf(`sed -i 's/CREATE USER IF NOT EXISTS /CREATE USER /g' %s`, filepath) err := exec.Command("/bin/bash", "-c", cmdStr).Run() if err != nil { diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_logical.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_logical.go index de6e84a486..a9aa958c0e 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_logical.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_logical.go @@ -76,6 +76,7 @@ func (l *LogicalLoader) initConfig(_ *IndexContent) error { // return nil //} +// Execute execute loading backup with logical backup tool func (l *LogicalLoader) Execute() error { binPath := filepath.Join(l.dbbackupHome, "bin/myloader") args := []string{ diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_physical.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_physical.go index e16044c763..f24ceab7f5 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_physical.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/backupexe/loader_physical.go @@ -21,6 +21,7 @@ type PhysicalLoader struct { mysqlVersion string storageEngine string innodbCmd InnodbCommand + isOfficial bool } func (p *PhysicalLoader) initConfig(indexContent *IndexContent) error { @@ -33,9 +34,11 @@ func (p *PhysicalLoader) initConfig(indexContent *IndexContent) error { p.dbbackupHome = filepath.Dir(cmdPath) } - p.mysqlVersion = util.VersionParser(indexContent.MysqlVersion) + p.mysqlVersion, p.isOfficial = util.VersionParser(indexContent.MysqlVersion) p.storageEngine = strings.ToLower(indexContent.StorageEngine) - p.innodbCmd.ChooseXtrabackupTool(p.mysqlVersion) + if err := p.innodbCmd.ChooseXtrabackupTool(p.mysqlVersion, p.isOfficial); err != nil { + return err + } return nil } @@ -157,6 +160,7 @@ func (p *PhysicalLoader) initConfig(indexContent *IndexContent) error { // return nil //} +// Execute excute loading backup with physical backup tool func (p *PhysicalLoader) Execute() error { if p.storageEngine != "innodb" { err := fmt.Errorf("%s engine not supported", p.storageEngine) @@ -183,7 +187,7 @@ func (p *PhysicalLoader) Execute() error { } func (p *PhysicalLoader) decompress() error { - binPath := filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.innobackupexBin) + binPath := filepath.Join(p.dbbackupHome, p.innodbCmd.innobackupexBin) args := []string{ "--decompress", @@ -197,6 +201,9 @@ func (p *PhysicalLoader) decompress() error { fmt.Sprintf("--target-dir=%s", p.cnf.PhysicalLoad.MysqlLoadDir), }...) } + if strings.Compare(p.mysqlVersion, "008000000") >= 0 && p.isOfficial { + args = append(args, "--skip-strict") + } cmd := exec.Command("sh", "-c", fmt.Sprintf(`%s %s`, binPath, strings.Join(args, " "))) @@ -211,12 +218,12 @@ func (p *PhysicalLoader) decompress() error { } func (p *PhysicalLoader) apply() error { - binPath := filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.innobackupexBin) + binPath := filepath.Join(p.dbbackupHome, p.innodbCmd.innobackupexBin) args := []string{ fmt.Sprintf("--parallel=%d", p.cnf.PhysicalLoad.Threads), fmt.Sprintf( - "--ibbackup=%s", filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.xtrabackupBin)), + "--ibbackup=%s", filepath.Join(p.dbbackupHome, p.innodbCmd.xtrabackupBin)), "--use-memory=1GB", } @@ -234,6 +241,10 @@ func (p *PhysicalLoader) apply() error { }...) } + if strings.Compare(p.mysqlVersion, "008000000") >= 0 && p.isOfficial { + args = append(args, "--skip-strict") + } + cmd := exec.Command("sh", "-c", fmt.Sprintf(`%s %s`, binPath, strings.Join(args, " "))) logger.Log.Info("apply command: ", cmd.String()) @@ -247,12 +258,12 @@ func (p *PhysicalLoader) apply() error { } func (p *PhysicalLoader) load() error { - binPath := filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.innobackupexBin) + binPath := filepath.Join(p.dbbackupHome, p.innodbCmd.innobackupexBin) args := []string{ fmt.Sprintf("--defaults-file=%s", p.cnf.PhysicalLoad.DefaultsFile), fmt.Sprintf( - "--ibbackup=%s", filepath.Join(p.dbbackupHome, "/bin/xtrabackup", p.innodbCmd.xtrabackupBin)), + "--ibbackup=%s", filepath.Join(p.dbbackupHome, p.innodbCmd.xtrabackupBin)), } if p.cnf.PhysicalLoad.CopyBack { @@ -269,6 +280,10 @@ func (p *PhysicalLoader) load() error { }...) } + if strings.Compare(p.mysqlVersion, "008000000") >= 0 && p.isOfficial { + args = append(args, "--skip-strict") + } + // ToDo extraopt cmd := exec.Command("sh", "-c", diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/precheck/check_charset.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/precheck/check_charset.go index 192b4b4aa3..6cd21fd93e 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/precheck/check_charset.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/precheck/check_charset.go @@ -29,7 +29,8 @@ func CheckCharset(cnf *config.Public) error { if verErr != nil { return verErr } - if strings.Compare(util.VersionParser(version), "005005003") == -1 { // mysql_version <5.5.3 + verStr, _ := util.VersionParser(version) + if strings.Compare(verStr, "005005003") == -1 { // mysql_version <5.5.3 superCharset = "utf8" } else { superCharset = "utf8mb4" diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util/misc.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util/misc.go index 0f90553108..b46499621b 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util/misc.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/util/misc.go @@ -201,10 +201,12 @@ func StringSliceToInterfaceSlice(ids []string) []interface{} { return result } -// VersionParser parse mysql version -// example: 5.7.20-tmysql-3.4.2-log -> 005007020 -func VersionParser(version string) string { - var parse = "000000" +// VersionParser parse mysql version. +// example: +// tmysql-version: 5.7.20-tmysql-3.4.2-log -> return 005007020, false +// official-version: 5.7.42-log -> return 005007042, true +func VersionParser(version string) (parse string, isOfficial bool) { + parse = "000000" reg := regexp.MustCompile(`^\s*(\d+)\.(\d+)\.(\d+)`) temp := reg.FindStringSubmatch(version) if len(temp) > 0 { @@ -212,7 +214,12 @@ func VersionParser(version string) string { newTemp := StringSliceToInterfaceSlice(temp) parse = fmt.Sprintf("%03s%03s%03s", newTemp...) } - return parse + if strings.Contains(version, "tmysql") { + isOfficial = false + } else { + isOfficial = true + } + return parse, isOfficial } // FindBackupConfigFiles TODO From 26cf493217d9297ee4ec376e3b738ff8840a0cd4 Mon Sep 17 00:00:00 2001 From: xiepaup Date: Thu, 6 Jul 2023 10:13:51 +0800 Subject: [PATCH 096/476] fix tendis ssd switch backends --- dbm-ui/backend/flow/consts.py | 1 + .../engine/bamboo/scene/redis/atom_jobs/redis_makesync.py | 8 +++++--- dbm-ui/backend/flow/utils/redis/redis_act_playload.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index 4e4dc7c1f1..438c4ce541 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -340,6 +340,7 @@ class RedisActuatorActionEnum(str, StructuredEnum): KillConn = EnumField("kill_conn", _("kill_conn")) SyncParam = EnumField("param_sync", _("param_sync")) CheckSync = EnumField("sync_check", _("sync_check")) + SwitchBackends = EnumField("switch", _("switch")) DR_RESTORE = EnumField("dr_restore", _("dr_restore")) CheckProxysMd5 = EnumField("check_backends", _("check_backends")) DTS_DATACHECK = EnumField("dts_datacheck", _("dts_datacheck")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py index 3bb40bdd7d..630aeac103 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py @@ -203,9 +203,10 @@ def RedisSSDMakeSyncAtomJob(sub_pipeline: SubBuilder, act_kwargs: ActKwargs, par backup_and_restore(sub_pipeline, act_kwargs, params, data_from, data_to) if params["sync_type"] in [SyncType.SYNC_MMS, SyncType.SYNC_SMS]: - data_from = "origin_1" - data_to = "sync_dst1" - backup_and_restore(sub_pipeline, act_kwargs, params, data_from, data_to) + sub_kwargs = deepcopy(act_kwargs) + data_from = "sync_dst1" + data_to = "sync_dst2" + backup_and_restore(sub_pipeline, sub_kwargs, params, data_from, data_to) return sub_pipeline @@ -222,6 +223,7 @@ def backup_and_restore( # "sync_dst2":"2.2.x.1", # new_slave # "ins_link":[{"origin_1":"port","origin_2":"port","sync_dst1":"port","sync_dst2":"port"}], # } + logger.info("need do make sync for ssd type from {} 2 {}".format(params[data_from], params[data_to])) # 发起备份 act_kwargs.exec_ip = params[data_from] diff --git a/dbm-ui/backend/flow/utils/redis/redis_act_playload.py b/dbm-ui/backend/flow/utils/redis/redis_act_playload.py index 6dec4a0358..b908651346 100644 --- a/dbm-ui/backend/flow/utils/redis/redis_act_playload.py +++ b/dbm-ui/backend/flow/utils/redis/redis_act_playload.py @@ -856,7 +856,7 @@ def redis_twemproxy_arch_switch_4_scene(self, **kwargs) -> dict: return { "db_type": DBActuatorTypeEnum.Redis.value, - "action": DBActuatorTypeEnum.Redis.value + "_" + RedisActuatorActionEnum.CheckSync.value, + "action": DBActuatorTypeEnum.Redis.value + "_" + RedisActuatorActionEnum.SwitchBackends.value, "payload": { "cluster_meta": cluster_meta, # dict "switch_info": params["switch_info"], # list From 3c6c0bb885d213a625129a1c485402854ba4eb7a Mon Sep 17 00:00:00 2001 From: fanfanyangyang Date: Mon, 3 Jul 2023 19:25:22 +0800 Subject: [PATCH 097/476] =?UTF-8?q?fix(dbm-services):=20spider=E5=88=86?= =?UTF-8?q?=E5=8C=BA=E6=9F=A5=E8=AF=A2=E4=B8=AD=E6=8E=A7=E4=B8=BB=E8=8A=82?= =?UTF-8?q?=E7=82=B9=20#377?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/check_partition_base_func.go | 58 +++++-- .../service/execute_partition_object.go | 163 +++++------------- 2 files changed, 94 insertions(+), 127 deletions(-) diff --git a/dbm-services/mysql/db-partition/service/check_partition_base_func.go b/dbm-services/mysql/db-partition/service/check_partition_base_func.go index 7e98983fb5..303d6ea603 100644 --- a/dbm-services/mysql/db-partition/service/check_partition_base_func.go +++ b/dbm-services/mysql/db-partition/service/check_partition_base_func.go @@ -10,12 +10,13 @@ import ( "sync" "time" + "golang.org/x/exp/slog" + "dbm-services/mysql/db-partition/errno" "dbm-services/mysql/db-partition/model" "dbm-services/mysql/db-partition/monitor" "github.com/spf13/viper" - "golang.org/x/exp/slog" ) // GetPartitionDbLikeTbLike TODO @@ -430,23 +431,60 @@ func (m *ConfigDetail) NewPartitionNameDescType4(begin int, need int, name strin // GetSpiderBackends TODO func GetSpiderBackends(address string, bkCloudId int) (tableDataType, int, error) { var splitCnt int - vsql := "select HOST,PORT,replace(server_name,'SPT','') as SPLIT_NUM, SERVER_NAME, WRAPPER from mysql.servers " + - "where wrapper in ('mysql','TDBCTL') and (server_name like 'SPT%' or server_name like 'TDBCTL%') ;" - queryRequest := QueryRequest{Addresses: []string{address}, Cmds: []string{vsql}, Force: true, QueryTimeout: 30, + var tdbctlPrimary string + // 查询tdbctl + dbctlSql := "select HOST,PORT,server_name as SPLIT_NUM, SERVER_NAME, WRAPPER from mysql.servers " + + "where wrapper='TDBCTL' and server_name like 'TDBCTL%' ;" + getTdbctlPrimary := "tdbctl get primary;" + queryRequest := QueryRequest{Addresses: []string{address}, Cmds: []string{dbctlSql}, Force: true, QueryTimeout: 30, BkCloudId: bkCloudId} output, err := OneAddressExecuteSql(queryRequest) if err != nil { - return nil, splitCnt, fmt.Errorf("get spider info error: %s", err.Error()) + return nil, splitCnt, fmt.Errorf("execute [%s] get spider info error: %s", dbctlSql, err.Error()) } else if len(output.CmdResults[0].TableData) == 0 { - return nil, splitCnt, fmt.Errorf("no spider remote db or control spider found") + return nil, splitCnt, fmt.Errorf("no spider tdbctl found") } - vsql = - "select count(*) as COUNT from mysql.servers where WRAPPER='mysql' and SERVER_NAME like 'SPT%' group by host order by 1 desc limit 1;" - queryRequest = QueryRequest{Addresses: []string{address}, Cmds: []string{vsql}, Force: true, QueryTimeout: 30, + + // 查询tdbctl主节点 + for _, item := range output.CmdResults[0].TableData { + tdbctl := fmt.Sprintf("%s:%s", item["HOST"].(string), item["PORT"].(string)) + queryRequest = QueryRequest{Addresses: []string{tdbctl}, Cmds: []string{getTdbctlPrimary}, Force: true, + QueryTimeout: 30, BkCloudId: bkCloudId} + primary, err := OneAddressExecuteSql(queryRequest) + if err != nil { + slog.Warn(fmt.Sprintf("execute [%s] error: %s", getTdbctlPrimary, err.Error())) + continue + } + if len(primary.CmdResults[0].TableData) == 0 { + slog.Error(fmt.Sprintf("execute [%s] nothing return", getTdbctlPrimary)) + return nil, splitCnt, fmt.Errorf("execute [%s] nothing return", getTdbctlPrimary) + } + slog.Info("data:", primary.CmdResults[0].TableData) + tdbctlPrimary = primary.CmdResults[0].TableData[0]["SERVER_NAME"].(string) + break + } + if tdbctlPrimary == "" { + slog.Error(fmt.Sprintf("execute [%s] SERVER_NAME is null", getTdbctlPrimary)) + return nil, splitCnt, fmt.Errorf("execute [%s] SERVER_NAME is null", getTdbctlPrimary) + } + // 查询remote master各分片实例和tdbctl主节点 + splitSql := fmt.Sprintf("select HOST,PORT,replace(server_name,'SPT','') as SPLIT_NUM, SERVER_NAME, WRAPPER "+ + "from mysql.servers where wrapper in ('mysql','TDBCTL') and "+ + "(server_name like 'SPT%%' or server_name like '%s')", tdbctlPrimary) + queryRequest = QueryRequest{Addresses: []string{address}, Cmds: []string{splitSql}, Force: true, QueryTimeout: 30, + BkCloudId: bkCloudId} + output, err = OneAddressExecuteSql(queryRequest) + if err != nil { + return nil, splitCnt, fmt.Errorf("execute [%s] get spider remote and tdbctl master error: %s", splitSql, err.Error()) + } + // 查询一台remote机器上有多少个实例,用于评估存储空间 + cntSql := "select count(*) as COUNT from mysql.servers where WRAPPER='mysql' and " + + "SERVER_NAME like 'SPT%' group by host order by 1 desc limit 1;" + queryRequest = QueryRequest{Addresses: []string{address}, Cmds: []string{cntSql}, Force: true, QueryTimeout: 30, BkCloudId: bkCloudId} output1, err := OneAddressExecuteSql(queryRequest) if err != nil { - return nil, splitCnt, fmt.Errorf("get spider split count error: %s", err.Error()) + return nil, splitCnt, fmt.Errorf("execute [%s] get spider split count error: %s", cntSql, err.Error()) } splitCnt, _ = strconv.Atoi(output1.CmdResults[0].TableData[0]["COUNT"].(string)) return output.CmdResults[0].TableData, splitCnt, nil diff --git a/dbm-services/mysql/db-partition/service/execute_partition_object.go b/dbm-services/mysql/db-partition/service/execute_partition_object.go index 5ee4d0adb9..905917737b 100644 --- a/dbm-services/mysql/db-partition/service/execute_partition_object.go +++ b/dbm-services/mysql/db-partition/service/execute_partition_object.go @@ -4,49 +4,57 @@ import ( "time" ) -// PartitionConfig TODO +// PartitionConfig 分区配置表 type PartitionConfig struct { - ID int `json:"id" gorm:"column:id;primary_key;auto_increment"` - BkBizId int `json:"bk_biz_id" gorm:"column:bk_biz_id"` - ImmuteDomain string `json:"immute_domain" gorm:"column:immute_domain"` - Port int `json:"port" gorm:"column:port"` - BkCloudId int `json:"bk_cloud_id" gorm:"column:bk_cloud_id"` - ClusterId int `json:"cluster_id" gorm:"column:cluster_id"` - DbLike string `json:"dblike" gorm:"column:dblike"` - TbLike string `json:"tblike" gorm:"column:tblike"` - PartitionColumn string `json:"partition_columns" gorm:"column:partition_column"` - PartitionColumnType string `json:"partition_column_type" gorm:"column:partition_column_type"` - ReservedPartition int `json:"reserved_partition" gorm:"column:reserved_partition"` - ExtraPartition int `json:"extra_partition" gorm:"column:extra_partition"` - PartitionTimeInterval int `json:"partition_time_interval" gorm:"column:partition_time_interval"` - PartitionType int `json:"partition_type" gorm:"column:partition_type"` - ExpireTime int `json:"expire_time"` - Phase string `json:"phase" gorm:"column:phase"` - Creator string `json:"creator" gorm:"column:creator"` - Updator string `json:"updator" gorm:"column:updator"` - CreateTime time.Time `json:"create_time" gorm:"column:create_time"` - UpdateTime time.Time `json:"update_time" gorm:"column:update_time"` + ID int `json:"id" gorm:"column:id;primary_key;auto_increment"` + BkBizId int `json:"bk_biz_id" gorm:"column:bk_biz_id"` + ImmuteDomain string `json:"immute_domain" gorm:"column:immute_domain"` + Port int `json:"port" gorm:"column:port"` + BkCloudId int `json:"bk_cloud_id" gorm:"column:bk_cloud_id"` + ClusterId int `json:"cluster_id" gorm:"column:cluster_id"` + DbLike string `json:"dblike" gorm:"column:dblike"` + TbLike string `json:"tblike" gorm:"column:tblike"` + PartitionColumn string `json:"partition_columns" gorm:"column:partition_column"` + PartitionColumnType string `json:"partition_column_type" gorm:"column:partition_column_type"` + // 保留的分区个数 ReservedPartition := ExpireTime / PartitionTimeInterval + ReservedPartition int `json:"reserved_partition" gorm:"column:reserved_partition"` + ExtraPartition int `json:"extra_partition" gorm:"column:extra_partition"` + // 分区间隔 + PartitionTimeInterval int `json:"partition_time_interval" gorm:"column:partition_time_interval"` + PartitionType int `json:"partition_type" gorm:"column:partition_type"` + // 数据过期天数 + ExpireTime int `json:"expire_time"` + // 分区规则启用或者禁用 + Phase string `json:"phase" gorm:"column:phase"` + Creator string `json:"creator" gorm:"column:creator"` + Updator string `json:"updator" gorm:"column:updator"` + CreateTime time.Time `json:"create_time" gorm:"column:create_time"` + UpdateTime time.Time `json:"update_time" gorm:"column:update_time"` } -// PartitionConfigWithLog TODO +// PartitionConfigWithLog 分区配置以及执行日志 type PartitionConfigWithLog struct { PartitionConfig - ExecuteTime time.Time `json:"execute_time" gorm:"execute_time"` - TicketId int `json:"ticket_id" gorm:"ticket_id"` - Status string `json:"status" gorm:"status"` - TicketStatus string `json:"ticket_status" gorm:"ticket_status"` - CheckInfo string `json:"check_info" gorm:"check_info"` + ExecuteTime time.Time `json:"execute_time" gorm:"execute_time"` + TicketId int `json:"ticket_id" gorm:"ticket_id"` + // 分区任务的状态 + Status string `json:"status" gorm:"status"` + // 分区单据的状态 + TicketStatus string `json:"ticket_status" gorm:"ticket_status"` + // 分区检查的结果 + CheckInfo string `json:"check_info" gorm:"check_info"` } -// ConfigDetail TODO +// ConfigDetail 具体到库表的分区配置 type ConfigDetail struct { PartitionConfig - DbName string `json:"dbname"` - TbName string `json:"tbname"` - Partitioned bool `json:"partitioned"` + DbName string `json:"dbname"` + TbName string `json:"tbname"` + // 是否已经分区 + Partitioned bool `json:"partitioned"` } -// Ticket TODO +// Ticket 分区单据 type Ticket struct { BkBizId int `json:"bk_biz_id"` TicketType string `json:"ticket_type"` @@ -54,18 +62,18 @@ type Ticket struct { Details Detail `json:"details"` } -// Details TODO +// Details 单据参数 type Details struct { Infos []Info `json:"infos"` Clusters ClustersResponse `json:"clusters"` } -// ClustersResponse TODO +// ClustersResponse 用于创建单据 type ClustersResponse struct { ClusterResponse map[string]ClusterResponse `json:"cluster_response"` } -// ClusterResponse TODO +// ClusterResponse 用于创建单据 type ClusterResponse struct { Id int `json:"id"` Creator string `json:"creator"` @@ -85,12 +93,12 @@ type ClusterResponse struct { ClusterTypeName string `json:"cluster_type_name"` } -// Detail TODO +// Detail 用于创建单据 type Detail struct { Infos []Info `json:"infos"` } -// Info TODO +// Info 用于创建单据 type Info struct { ConfigId int `json:"config_id"` ClusterId int `json:"cluster_id"` @@ -99,89 +107,10 @@ type Info struct { PartitionObjects []PartitionObject `json:"partition_objects"` } -// PartitionObject TODO +// PartitionObject 待执行的分区语句集合 type PartitionObject struct { Ip string `json:"ip"` Port int `json:"port"` ShardName string `json:"shard_name"` ExecuteObjects []PartitionSql `json:"execute_objects"` } - -// ExecResult TODO -type ExecResult struct { - IsSuccess bool - Sql string - Msg string -} - -// Result TODO -type Result struct { - ExecResult - DbName string - Action string -} - -/* -show create table mysql_partition_conf\G -*************************** 1. row *************************** - Table: mysql_partition_conf -Create Table: CREATE TABLE `mysql_partition_conf` ( - `ID` bigint(20) NOT NULL AUTO_INCREMENT, - `App` varchar(100) NOT NULL, - `Module` varchar(100) NOT NULL, - `Ip` varchar(100) NOT NULL, - `Port` int(11) NOT NULL, - `DbLike` varchar(100) NOT NULL, - `PartitionTableName` varchar(100) NOT NULL, - `PartitionColumn` varchar(100) DEFAULT NULL, - `PartitionColumnType` varchar(100) DEFAULT NULL, - `ReservedPartition` int(11) NOT NULL, - `ExtraPartition` int(11) NOT NULL, - `PartitionTimeInterval` int(11) NOT NULL, - `PartitionTimeWay` enum('DAY','MONTH') DEFAULT NULL, - `PartitionType` int(11) NOT NULL, - `IsExchange` int(11) NOT NULL DEFAULT '0', - `HeartBeat` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', - `Alive` int(11) NOT NULL DEFAULT '3' COMMENT '1:success,2:failed,3:not execute,4+:others', - `DoSuccess` int(11) DEFAULT NULL, - `DoFailed` int(11) DEFAULT NULL, - `Creator` varchar(100) DEFAULT NULL, - `Updator` varchar(100) DEFAULT NULL, - `CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `UpdateTime` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', - PRIMARY KEY (`ID`), - UNIQUE KEY `UK_MPT` (`App`,`Module`,`Ip`,`Port`,`DbLike`,`PartitionTableName`), - UNIQUE KEY `uk_IPDT` (`Ip`,`Port`,`DbLike`,`PartitionTableName`), - KEY `idx_app_alive` (`App`,`Alive`), - KEY `IDX_DT` (`DbLike`,`PartitionTableName`), - KEY `IDX_IDT` (`Ip`,`DbLike`,`PartitionTableName`) -) ENGINE=InnoDB AUTO_INCREMENT=74533 DEFAULT CHARSET=utf8mb4 -1 row in set (0.00 sec) - -select * from mysql_partition_conf limit 1\G -*************************** 1. row *************************** - ID: 25 - App: web - Module: web - Ip: gamedb.amspoint16.web.db - Port: 10000 - DbLike: dbcaccts - PartitionTableName: t_acct_water_0 - PartitionColumn: Fcreate_time - PartitionColumnType: timestamp - ReservedPartition: 30 - ExtraPartition: 14 -PartitionTimeInterval: 1 - PartitionTimeWay: DAY - PartitionType: 5 - IsExchange: 0 - HeartBeat: 2023-02-12 01:30:08 - Alive: 1 - DoSuccess: 2 - DoFailed: 0 - Creator: NULL - Updator: NULL - CreateTime: 0000-00-00 00:00:00 - UpdateTime: 2000-01-01 00:00:00 -1 row in set (0.00 sec) -*/ From 710d95098f80681d57436a9921bf4ace31ae527f Mon Sep 17 00:00:00 2001 From: gaohongsong Date: Thu, 6 Jul 2023 10:34:34 +0800 Subject: [PATCH 098/476] =?UTF-8?q?feat:=20=E5=B7=A5=E5=85=B7=E7=AE=B1?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=A1=A5=E5=85=85=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_meta/models/cluster.py | 13 ++++++++++++- .../db_services/redis/resources/constants.py | 6 ++++-- .../backend/db_services/redis/toolbox/handlers.py | 14 ++++++++++++-- .../db_services/redis/toolbox/serializers.py | 15 ++++++++++++++- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/dbm-ui/backend/db_meta/models/cluster.py b/dbm-ui/backend/db_meta/models/cluster.py index bc7b6d226e..6d21a448f2 100644 --- a/dbm-ui/backend/db_meta/models/cluster.py +++ b/dbm-ui/backend/db_meta/models/cluster.py @@ -64,7 +64,18 @@ def to_dict(self): @property def simple_desc(self): - return model_to_dict(self, ["id", "name", "bk_cloud_id", "region", "cluster_type", "immute_domain"]) + return model_to_dict( + self, + [ + "id", + "name", + "bk_cloud_id", + "region", + "cluster_type", + "immute_domain", + "major_version", + ], + ) @property def extra_desc(self): diff --git a/dbm-ui/backend/db_services/redis/resources/constants.py b/dbm-ui/backend/db_services/redis/resources/constants.py index 61b6132335..769cc244a8 100644 --- a/dbm-ui/backend/db_services/redis/resources/constants.py +++ b/dbm-ui/backend/db_services/redis/resources/constants.py @@ -16,7 +16,8 @@ "LEFT JOIN db_meta_machine m ON i.machine_id = m.bk_host_id " "LEFT JOIN db_meta_storageinstance_cluster c ON i.id = c.storageinstance_id " "{where} " - "GROUP BY ip, role, bk_host_id, bk_cloud_id, cluster_id" + "GROUP BY ip, role, bk_host_id, bk_cloud_id, cluster_id " + "{having}" ) SQL_QUERY_PROXY_INSTANCES = ( @@ -25,7 +26,8 @@ "LEFT JOIN db_meta_machine m ON i.machine_id = m.bk_host_id " "LEFT JOIN db_meta_proxyinstance_cluster c ON i.id = c.proxyinstance_id " "{where} " - "GROUP BY ip, role, bk_host_id, bk_cloud_id, cluster_id" + "GROUP BY ip, role, bk_host_id, bk_cloud_id, cluster_id " + "{having}" ) SQL_QUERY_INSTANCES = f"({SQL_QUERY_STORAGE_INSTANCES}) UNION ({SQL_QUERY_PROXY_INSTANCES}) " + " {limit} {offset}" diff --git a/dbm-ui/backend/db_services/redis/toolbox/handlers.py b/dbm-ui/backend/db_services/redis/toolbox/handlers.py index db00374b72..e0c461e459 100644 --- a/dbm-ui/backend/db_services/redis/toolbox/handlers.py +++ b/dbm-ui/backend/db_services/redis/toolbox/handlers.py @@ -162,7 +162,7 @@ def query_cluster_list(self): for cluster in clusters ] - def query_cluster_ips(self, limit=None, offset=None, cluster_id=None, ip=None): + def query_cluster_ips(self, limit=None, offset=None, cluster_id=None, ip=None, role=None, status=None): """聚合查询集群下的主机""" limit_sql = "" @@ -185,10 +185,20 @@ def query_cluster_ips(self, limit=None, offset=None, cluster_id=None, ip=None): where_sql += "AND m.ip LIKE %s " where_values.append(f"%{ip}%") + if status: + where_sql += "AND i.status = %s " + where_values.append(status) + + having_sql = "" + if role: + having_sql += "HAVING role = %s " + where_values.append(role) + # union查询需要两份参数 where_values = where_values * 2 - sql = SQL_QUERY_INSTANCES.format(where=where_sql, limit=limit_sql, offset=offset_sql) + sql = SQL_QUERY_INSTANCES.format(where=where_sql, having=having_sql, limit=limit_sql, offset=offset_sql) + with connection.cursor() as cursor: cursor.execute(sql, where_values) diff --git a/dbm-ui/backend/db_services/redis/toolbox/serializers.py b/dbm-ui/backend/db_services/redis/toolbox/serializers.py index a772b981eb..5d1789e49f 100644 --- a/dbm-ui/backend/db_services/redis/toolbox/serializers.py +++ b/dbm-ui/backend/db_services/redis/toolbox/serializers.py @@ -11,6 +11,8 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from backend.db_meta.enums import InstanceInnerRole, InstanceRole, InstanceStatus + class QueryByClusterSerializer(serializers.Serializer): role = serializers.ChoiceField(choices=("proxy", "storage", "all"), default="all") @@ -165,6 +167,17 @@ class QueryClusterIpsSerializer(serializers.Serializer): ip = serializers.CharField(max_length=32, required=False) limit = serializers.IntegerField(help_text=_("limit"), required=False, min_value=1) offset = serializers.IntegerField(help_text=_("offset"), required=False, min_value=1) + role = serializers.ChoiceField(help_text=_("role"), required=False, choices=InstanceInnerRole.get_choices()) + status = serializers.ChoiceField(help_text=_("status"), required=False, choices=InstanceStatus.get_choices()) class Meta: - swagger_schema_fields = {"example": {"cluster_id": 1, "ip": "127.0.0.1", "limit": 1, "offset": 2}} + swagger_schema_fields = { + "example": { + "cluster_id": 1, + "ip": "127.0.0.1", + "limit": 1, + "offset": 2, + "role": "master/slave", + "status": "running", + } + } From 0ab3065ac423e62f0f5ab93f9dc91510ee673fb0 Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Wed, 5 Jul 2023 20:30:03 +0800 Subject: [PATCH 099/476] =?UTF-8?q?feat(fronent):=20=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=89=A9=E7=BC=A9=E5=AE=B9=E6=8E=A5=E5=85=A5=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=B1=A0=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 2 +- .../src/components/cluster-common/es-host-replace/Index.vue | 4 ++++ .../src/components/cluster-common/host-replace/Index.vue | 3 +++ dbm-ui/frontend/src/views/es-manage/common/replace/Index.vue | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index 67cabfd6ed..87665f672f 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -15,7 +15,7 @@ "dependencies": { "@blueking/bk-weweb": "^0.0.15", "@blueking/bkflow.js": "^0.1.10", - "@blueking/ip-selector": "0.0.1-beta.111", + "@blueking/ip-selector": "0.0.1-beta.116", "@vueuse/core": "^10.1.2", "axios": "^1.2.1", "bkui-vue": "0.0.1-beta.456", diff --git a/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue b/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue index 00ec5797b6..d985dc97a4 100644 --- a/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue +++ b/dbm-ui/frontend/src/components/cluster-common/es-host-replace/Index.vue @@ -199,6 +199,9 @@ .reduce((result, item) => result + ~~Number(item.bk_disk), 0)); const isError = computed(() => { + if (nodeList.value.length < 1) { + return false; + } if (props.ipSource === 'manual_input') { return hostList.value.length > 0 && hostList.value.length !== nodeList.value.length; } @@ -234,6 +237,7 @@ if (isError.value) { return Promise.reject(); } + if (nodeList.value.length < 1) { return Promise.resolve({ old_nodes: [], diff --git a/dbm-ui/frontend/src/components/cluster-common/host-replace/Index.vue b/dbm-ui/frontend/src/components/cluster-common/host-replace/Index.vue index 7e220d9aca..485a9decfd 100644 --- a/dbm-ui/frontend/src/components/cluster-common/host-replace/Index.vue +++ b/dbm-ui/frontend/src/components/cluster-common/host-replace/Index.vue @@ -190,6 +190,9 @@ generic="T extends EsNodeModel|HdfsNodeModel|KafkaNodeModel|PulsarNodeModel|Infl .reduce((result, item) => result + ~~Number(item.bk_disk), 0)); const isError = computed(() => { + if (nodeList.value.length < 1) { + return false; + } if (props.ipSource === 'manual_input') { return hostList.value.length > 0 && hostList.value.length !== nodeList.value.length; } diff --git a/dbm-ui/frontend/src/views/es-manage/common/replace/Index.vue b/dbm-ui/frontend/src/views/es-manage/common/replace/Index.vue index 80eadfd4a6..a450baba7d 100644 --- a/dbm-ui/frontend/src/views/es-manage/common/replace/Index.vue +++ b/dbm-ui/frontend/src/views/es-manage/common/replace/Index.vue @@ -351,7 +351,7 @@ }); }, }); - }, () => reject()); + }, () => reject('error')); }); }, cancel() { From 26cf81aa2481afbd761660305f1353e4db5243a1 Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Thu, 6 Jul 2023 14:58:50 +0800 Subject: [PATCH 100/476] =?UTF-8?q?feat(fronent):=20=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=89=A9=E7=BC=A9=E5=AE=B9=E6=8E=A5=E5=85=A5=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=B1=A0=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 33 +++++++++---------- dbm-ui/frontend/src/locales/index.ts | 8 +++-- dbm-ui/frontend/src/locales/zh-cn.json | 1 + .../list/components/ExportHostBtn.vue | 10 +++--- .../list/components/export-host/Index.vue | 2 +- .../export-host/components/FormPanel.vue | 10 +++--- .../components/select-host-panel/Index.vue | 4 +-- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index 87665f672f..e5c1f8e218 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -16,17 +16,17 @@ "@blueking/bk-weweb": "^0.0.15", "@blueking/bkflow.js": "^0.1.10", "@blueking/ip-selector": "0.0.1-beta.116", - "@vueuse/core": "^10.1.2", + "@vueuse/core": "^10.2.1", "axios": "^1.2.1", "bkui-vue": "0.0.1-beta.456", "date-fns": "^2.28.0", - "dayjs": "^1.11.7", + "dayjs": "^1.11.9", "html-to-image": "^1.11.3", "js-cookie": "^3.0.1", "jsencrypt": "^3.3.1", "lodash": "^4.17.21", - "mitt": "^3.0.0", - "monaco-editor": "^0.38.0", + "mitt": "^3.0.1", + "monaco-editor": "^0.39.0", "path": "^0.12.7", "pinia": "^2.0.28", "query-string": "^8.1.0", @@ -36,25 +36,24 @@ "tippy.js": "^6.3.7", "unplugin-auto-import": "^0.15.3", "vite-plugin-monaco-editor": "^1.1.0", - "vite-plugin-static-copy": "^0.15.0", + "vite-plugin-static-copy": "^0.16.0", "vue": "^3.3.2", "vue-i18n": "^9.2.2", - "vue-request": "^1.2.4", - "vue-router": "^4.0.15", + "vue-request": "^2.0.3", + "vue-router": "^4.2.3", "vuedraggable": "^4.1.0" }, "devDependencies": { "@commitlint/config-conventional": "^17.1.0", "@types/lodash": "^4.14.191", - "@types/node": "^20.1.5", + "@types/node": "^20.4.0", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-vue": "^4.2.3", "@vitejs/plugin-vue-jsx": "^3.0.0", "@vue/eslint-config-typescript": "^11.0.0", "@vue/tsconfig": "^0.4.0", "commitlint": "^17.1.2", - "consola": "^3.1.0", - "eslint": "^8.40.0", + "eslint": "^8.44.0", "eslint-config-tencent": "^1.0.4", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-vue": "^9.13.0", @@ -63,18 +62,18 @@ "lint-staged": "^13.1.0", "postcss-html": "^1.4.1", "postcss-less": "^6.0.0", - "stylelint": "^15.6.1", - "stylelint-config-standard": "^33.0.0", - "stylelint-less": "^1.0.5", + "stylelint": "15.6.1", + "stylelint-config-standard": "^34.0.0", + "stylelint-less": "^1.0.7", "stylelint-order": "^6.0.3", - "typescript": "^5.0.4", - "unplugin-vue-components": "^0.24.1", + "typescript": "^5.1.6", + "unplugin-vue-components": "^0.25.1", "vite": "^4.3.6", "vite-plugin-babel": "^1.1.3", "vite-plugin-html-env": "^1.2.7", "vite-plugin-imp": "^2.1.8", "vite-plugin-style-import": "^2.0.0", - "vue-tsc": "^1.6.5" + "vue-tsc": "^1.8.4" }, "lint-staged": { "*.css": "stylelint", @@ -86,4 +85,4 @@ "engines": { "node": ">=14.19.0" } -} \ No newline at end of file +} diff --git a/dbm-ui/frontend/src/locales/index.ts b/dbm-ui/frontend/src/locales/index.ts index cca379701a..d15fad56f2 100644 --- a/dbm-ui/frontend/src/locales/index.ts +++ b/dbm-ui/frontend/src/locales/index.ts @@ -31,10 +31,14 @@ import cn from './zh-cn.json'; // }); // } -const language = Cookies.get('blueking_language') || 'zh-cn'; +let localeLanguage = 'zh-cn'; +const bluekingLanguage = Cookies.get('blueking_language'); +if (bluekingLanguage && bluekingLanguage.toLowerCase() === 'en') { + localeLanguage = 'en'; +} const i18n = createI18n({ legacy: false, - locale: language, + locale: localeLanguage, messages: { en, 'zh-cn': cn, diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index c2b6aca55f..96baaf1576 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1510,5 +1510,6 @@ "选择集群后自动生成": "选择集群后自动生成", "复制异常 IP": "复制异常 IP", "导入设置": "导入设置", + "当前已经有n个导入任务正在进行中,": "当前已经有{0}个导入任务正在进行中,", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/ExportHostBtn.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/ExportHostBtn.vue index 1e9926aa8e..b4fa89c153 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/ExportHostBtn.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/ExportHostBtn.vue @@ -8,21 +8,21 @@ theme="danger" :visible="taskNumber < 1"> {{ t('导入') }} diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/Index.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/Index.vue index 2d48368a6c..d426f78e60 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/export-host/Index.vue @@ -126,7 +126,7 @@ diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterRelatedTasks.vue b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterRelatedTasks.vue new file mode 100644 index 0000000000..02fb6b20ec --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterRelatedTasks.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue index 81910dd103..f49e9aa92b 100644 --- a/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/ClusterSelector.vue @@ -174,6 +174,7 @@ import { messageWarn } from '@utils'; + import ClusterRelatedTasks from './ClusterRelatedTasks.vue'; import CollapseMini from './CollapseMini.vue'; import type { ClusterSelectorResult, ClusterSelectorState } from './types'; import { useClusterData } from './useClusterData'; @@ -226,7 +227,6 @@ } const handleClickSearch = async () => { - console.log('key word: ', state.search); const keyword = state.search; if (rawTableData.length === 0) rawTableData = [...state.tableData]; if (keyword) { @@ -276,6 +276,23 @@ label: t('集群'), field: 'immute_domain', showOverflowTooltip: true, + render: ({ data }: { data: RedisModel }) => ( +
+ {data.immute_domain} + {data.operations && data.operations.length > 0 && + {{ + default: () => ( + + {data.operations.length} + + ), + content: () => (), + }} + } + +
), }, { label: t('状态'), field: 'master_domain', @@ -290,7 +307,7 @@ field: 'alias', showOverflowTooltip: true, }, { - label: t('所属云区域'), + label: t('管控区域'), field: 'region', render: ({ data }: { data: RedisModel }) => data.cloud_info.bk_cloud_name, }]; @@ -383,8 +400,6 @@ * 选择当行数据 */ function handleSelected(data: RedisModel, value: boolean) { - // console.log('select: ', data, value); - const targetValue = data.immute_domain; const index = selectedDomains.value.findIndex(val => val === targetValue); if (value && index === -1) { diff --git a/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts b/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts index e48b487330..a55fa55112 100644 --- a/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts +++ b/dbm-ui/frontend/src/views/redis/common/cluster-selector/useClusterData.ts @@ -11,15 +11,8 @@ * the specific language governing permissions and limitations under the License. */ -// import { getResources } from '@services/clusters'; -import { getModules } from '@services/common'; import { listClusterList } from '@services/redis/toolbox'; -// import type { ResourceItem } from '@services/types/clusters'; -import { useGlobalBizs } from '@stores'; - -// import { DBTypes } from '@common/const'; -// import { getSearchSelectorParams } from '@utils'; import type { ClusterSelectorState } from './types'; /** diff --git a/dbm-ui/frontend/src/views/redis/common/edit/Input.vue b/dbm-ui/frontend/src/views/redis/common/edit/Input.vue index de7c9e5828..d3db0c7203 100644 --- a/dbm-ui/frontend/src/views/redis/common/edit/Input.vue +++ b/dbm-ui/frontend/src/views/redis/common/edit/Input.vue @@ -175,7 +175,6 @@ } isFocused.value = false; processMultiInputLocalValue(); - console.log('from handleBlur = ', localValue.value); if (!localValue.value) { return; } diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue index ee4c638f35..88eccf58ab 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/Index.vue @@ -34,14 +34,16 @@ diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue index a507d246f6..201b4f79d5 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/PreviewResult.vue @@ -54,7 +54,9 @@ v-overflow-tips class="text-overflow"> {{ item.ip }} - ({{ firstLetterToUpper(item.role) }}) + {{ + activeTab !== 'masterFailHosts' ? `(${firstLetterToUpper(item.role!)})` : '' + }} { emits('change', { idleHosts: [], + masterFailHosts: [], }); }; @@ -122,7 +127,7 @@ return; } - const instances: ChoosedItem[] = []; + const instances = []; for (const key of keys.value) { instances.push(...props.lastValues[key]); } @@ -204,7 +209,6 @@ .result-item-role { margin-left: 8px; - font-family: AlTarikh; font-size: 12px; color: #C4C6CC; } diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue index 63f547ea45..ddf3cadef1 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualHost.vue @@ -146,7 +146,7 @@ }, { minWidth: 100, - label: t('云区域'), + label: t('管控区域'), field: 'cloud_area', render: ({ data }: TableItem) => data.host_info?.cloud_area.name || '--', }, diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue index 1701beae54..9c95e488b0 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderManualInput.vue @@ -234,7 +234,6 @@ } catch (_) { console.log(_); } - console.log('ip格式错误', count); errorState.format.show = count > 0; errorState.instance.show = newLines.slice(count).length > 0; inputState.isLoading = false; diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue index 9fb3298a58..011d08dd44 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedis.vue @@ -58,7 +58,15 @@
diff --git a/dbm-ui/frontend/src/views/redis/routes.ts b/dbm-ui/frontend/src/views/redis/routes.ts index 24d569fe72..6554acbb10 100644 --- a/dbm-ui/frontend/src/views/redis/routes.ts +++ b/dbm-ui/frontend/src/views/redis/routes.ts @@ -27,7 +27,7 @@ export const toolboxRoutes: RouteRecordRaw[] = [ meta: { routeParentName: MainViewRouteNames.Database, activeMenu: 'RedisToolbox', - navName: '集群容量变更', // TODO: I18n + navName: t('集群容量变更'), submenuId: 'redis', isMenu: true, }, @@ -39,7 +39,7 @@ export const toolboxRoutes: RouteRecordRaw[] = [ meta: { routeParentName: MainViewRouteNames.Database, activeMenu: 'RedisToolbox', - navName: '扩容接入层', // TODO: I18n + navName: t('扩容接入层'), submenuId: 'redis', isMenu: true, }, @@ -51,24 +51,60 @@ export const toolboxRoutes: RouteRecordRaw[] = [ meta: { routeParentName: MainViewRouteNames.Database, activeMenu: 'RedisToolbox', - navName: '缩容接入层', // TODO: I18n + navName: t('缩容接入层'), submenuId: 'redis', isMenu: true, }, component: () => import('@views/redis/proxy-scale-down/Index.vue'), }, + { + name: 'RedisMasterFailover', + path: '/database/:bizId(\\d+)/redis-toolbox/master-failover/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: t('主故障切换'), + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/master-failover/Index.vue'), + }, { name: 'RedisDBReplace', path: '/database/:bizId(\\d+)/redis-toolbox/db-replace/:page?', meta: { routeParentName: MainViewRouteNames.Database, activeMenu: 'RedisToolbox', - navName: '整机替换', // TODO: I18n + navName: t('整机替换'), submenuId: 'redis', isMenu: true, }, component: () => import('@views/redis/db-replace/Index.vue'), }, + { + name: 'RedisDBStructure', + path: '/database/:bizId(\\d+)/redis-toolbox/db-structure/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: t('定点构造'), + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/db-structure/Index.vue'), + }, + { + name: 'RedisStructureInstance', + path: '/database/:bizId(\\d+)/redis-toolbox/structure-instance/:page?', + meta: { + routeParentName: MainViewRouteNames.Database, + activeMenu: 'RedisToolbox', + navName: t('构造实例'), + submenuId: 'redis', + isMenu: true, + }, + component: () => import('@views/redis/structure-instance/Index.vue'), + }, ]; const routes: RouteRecordRaw[] = [ diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/Index.vue b/dbm-ui/frontend/src/views/redis/structure-instance/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/Index.vue new file mode 100644 index 0000000000..656d63e6d1 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/Index.vue @@ -0,0 +1,353 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue new file mode 100644 index 0000000000..9ea81c6eac --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue new file mode 100644 index 0000000000..9084f51063 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue new file mode 100644 index 0000000000..310f54fbb1 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue new file mode 100644 index 0000000000..9e98728f7d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue new file mode 100644 index 0000000000..633f107a3d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue new file mode 100644 index 0000000000..36a43d1fce --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetHostNumber.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetHostNumber.vue new file mode 100644 index 0000000000..993dce58c0 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetHostNumber.vue @@ -0,0 +1,62 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue new file mode 100644 index 0000000000..244df557f8 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue @@ -0,0 +1,194 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue new file mode 100644 index 0000000000..ee2db733c6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue new file mode 100644 index 0000000000..bd47c670e6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue @@ -0,0 +1,425 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page2/Index.vue new file mode 100644 index 0000000000..949386cbbd --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts index b5ce908cd9..b3235161c8 100644 --- a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts +++ b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts @@ -39,6 +39,11 @@ export default [ id: 'RedisProxyScaleDown', parentId: 'redis', }, + { + name: t('主故障切换'), + id: 'RedisMasterFailover', + parentId: 'redis', + }, { name: t('整机替换'), id: 'RedisDBReplace', @@ -46,4 +51,21 @@ export default [ }, ], }, + { + name: t('数据构造'), + id: 'redis', + icon: 'db-icon-cluster', + children: [ + { + name: t('定点构造'), + id: 'RedisDBStructure', + parentId: 'redis', + }, + { + name: t('构造实例'), + id: 'RedisStructureInstance', + parentId: 'redis', + }, + ], + }, ]; From d45339ff35f12fd3f047def8e188c976b3670552 Mon Sep 17 00:00:00 2001 From: OMG-By <504094596@qq.com> Date: Tue, 4 Jul 2023 19:44:41 +0800 Subject: [PATCH 119/476] feat(redis): redis backend scale #428 --- dbm-ui/backend/flow/consts.py | 2 +- .../bamboo/scene/redis/redis_backend_scale.py | 299 ++++++++++++++++++ .../bamboo/scene/redis/redis_proxy_scale.py | 7 +- .../backend/flow/engine/controller/redis.py | 8 + dbm-ui/backend/flow/urls.py | 2 + dbm-ui/backend/flow/utils/dns_manage.py | 2 +- dbm-ui/backend/flow/views/redis_cluster.py | 42 +++ 7 files changed, 359 insertions(+), 3 deletions(-) create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index c770eb7dca..b1a2bcff63 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -698,7 +698,7 @@ class SyncType(str, StructuredEnum): SYNC_MS = EnumField("ms", _("ms")) SYNC_MMS = EnumField("mms", _("mms")) - SYNC_SMS = EnumField("sms", _("sms")) + SYNC_SMS = EnumField("msms", _("msms")) class RedisSlotSep(str, StructuredEnum): diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py new file mode 100644 index 0000000000..32062bd247 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py @@ -0,0 +1,299 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import logging.config +from collections import defaultdict +from dataclasses import asdict +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.configuration.constants import DBType +from backend.constants import IP_PORT_DIVIDER +from backend.db_meta.enums import InstanceRole +from backend.db_meta.enums.cluster_type import ClusterType +from backend.db_meta.models import Cluster +from backend.flow.consts import ( + DEFAULT_LAST_IO_SECOND_AGO, + DEFAULT_MASTER_DIFF_TIME, + DEFAULT_REDIS_START_PORT, + SyncType, +) +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList +from backend.flow.engine.bamboo.scene.redis.atom_jobs import ( + RedisBatchInstallAtomJob, + RedisBatchShutdownAtomJob, + RedisClusterSwitchAtomJob, + RedisMakeSyncAtomJob, +) +from backend.flow.plugins.components.collections.redis.get_redis_payload import GetRedisActPayloadComponent +from backend.flow.utils.redis.redis_context_dataclass import ActKwargs, CommonContext + +logger = logging.getLogger("flow") + + +class RedisBackendScaleFlow(object): + def __init__(self, root_id: str, data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param data : 单据传递过来的参数列表,是dict格式 + """ + self.root_id = root_id + self.data = data + + @staticmethod + def __get_cluster_info(bk_biz_id: int, cluster_id: int, version: str) -> dict: + """ + 获取集群现有信息 + 1. master对应的端口 {"1.1.1.1":[30000,30001]...} + 2. master、slave实例对应关系 {"1.1.1.1:30000":"2.2.2.1:30000"...} + 3. proxy实例列表 [3.3.3.3:50000...] + 4. master、slave机器对应关系 + """ + cluster = Cluster.objects.get(id=cluster_id, bk_biz_id=bk_biz_id) + + master_ip_ports_map = defaultdict(list) + ins_pair_map = defaultdict() + master_slave_map = defaultdict() + for master_obj in cluster.storageinstance_set.filter(instance_role=InstanceRole.REDIS_MASTER.value): + slave_obj = master_obj.as_ejector.get().receiver + master_ip_ports_map[master_obj.machine.ip].append(master_obj.port) + ins_pair_map["{}:{}".format(master_obj.machine.ip, master_obj.port)] = "{}:{}".format( + slave_obj.machine.ip, slave_obj.port + ) + + ifslave = master_slave_map.get(master_obj.machine.ip) + if ifslave and ifslave != slave_obj.machine.ip: + raise Exception( + "unsupport mutil slave with cluster {} 4:{}".format(cluster.immute_domain, master_obj.machine.ip) + ) + + master_slave_map[master_obj.machine.ip] = slave_obj.machine.ip + version = version or cluster.major_version + return { + "immute_domain": cluster.immute_domain, + "cluster_name": cluster.name, + "bk_biz_id": cluster.bk_biz_id, + "bk_cloud_id": cluster.bk_cloud_id, + "cluster_type": cluster.cluster_type, + "master_ip_ports_map": dict(master_ip_ports_map), + "ins_pair_map": dict(ins_pair_map), + "proxy_ips": [proxy_obj.machine.ip for proxy_obj in cluster.proxyinstance_set.all()], + "master_slave_map": dict(master_slave_map), + "db_version": version, + } + + def __init_builder(self, operate_name: str, info: dict): + cluster_info = self.__get_cluster_info(self.data["bk_biz_id"], info["cluster_id"], info["db_version"]) + sync_type = SyncType.SYNC_MMS # ssd sync from master + if cluster_info["cluster_type"] == ClusterType.TendisTwemproxyRedisInstance.value: + sync_type = SyncType.SYNC_SMS + + flow_data = {**info, **self.data} + for k, v in cluster_info.items(): + flow_data[k] = v + sub_pipeline = SubBuilder(root_id=self.root_id, data=flow_data) + trans_files = GetFileList(db_type=DBType.Redis) + act_kwargs = ActKwargs() + act_kwargs.set_trans_data_dataclass = CommonContext.__name__ + act_kwargs.file_list = trans_files.redis_base() + act_kwargs.is_update_trans_data = True + act_kwargs.cluster = { + **cluster_info, + "operate": operate_name, + "sync_type": sync_type, + } + act_kwargs.bk_cloud_id = cluster_info["bk_cloud_id"] + logger.info("+===+++++===current tick_data info+++++===++++ :: {}".format(act_kwargs)) + + sub_pipeline.add_act( + act_name=_("初始化配置"), act_component_code=GetRedisActPayloadComponent.code, kwargs=asdict(act_kwargs) + ) + return sub_pipeline, act_kwargs + + def generate_sync_relation(self, act_kwargs, master_ips, slave_ips, ins_num) -> list: + """ + TODO 需要重点验证这里的算法,机器分别变多变少时,得到的结果是否满足预期 + 计算新老实例对应关系 + 可能一对多,也可能多对一 + """ + sync_relations = [] + new_port_offset = 0 + new_host_index = 0 + sync_type = act_kwargs.cluster["sync_type"] + for old_master, old_master_ports in act_kwargs.cluster["master_ip_ports_map"].items(): + # old_master 或者 new_master变化了就需要append后初始化 + ins_link = [] + old_slave = "" + + old_master_ports.sort() + for old_master_port in old_master_ports: + # 获取老slave的ip和端口。这里端口不一定跟老master一致 + old_master_ins = "{}:{}".format(old_master, old_master_port) + old_slave_ins = act_kwargs.cluster["ins_pair_map"][old_master_ins] + old_slave = old_slave_ins.split(IP_PORT_DIVIDER)[0] + old_slave_port = old_slave_ins.split(IP_PORT_DIVIDER)[1] + # 新部署的实例端口肯定一致 + new_port = DEFAULT_REDIS_START_PORT + new_port_offset + ins_link.append( + { + "origin_1": int(old_master_port), + "origin_2": int(old_slave_port), + "sync_dst1": new_port, + "sync_dst2": new_port, + } + ) + new_port_offset += 1 + + if new_host_index >= len(master_ips): + raise Exception("origin cluster shard_num > new cluster shard_num. pleace use dts") + + # 如果达到了新机器需要部署的实例个数,下一个就要用新机器了。这个地方初始化一些参数 + if new_port_offset >= ins_num: + new_master = master_ips[new_host_index] + new_slave = slave_ips[new_host_index] + sync_relations.append( + { + "sync_type": sync_type, + "origin_1": old_master, + "origin_2": old_slave, + "sync_dst1": new_master, + "sync_dst2": new_slave, + "ins_link": ins_link, + } + ) + + ins_link = [] + new_port_offset = 0 + new_host_index += 1 + + # 遍历完老机器上的端口,如果ins_link里有数据,此时需要先处理一下 + if ins_link: + new_master = master_ips[new_host_index] + new_slave = slave_ips[new_host_index] + sync_relations.append( + { + "sync_type": sync_type, + "origin_1": old_master, + "origin_2": old_slave, + "sync_dst1": new_master, + "sync_dst2": new_slave, + "ins_link": ins_link, + } + ) + return sync_relations + + def generate_shutdown_ins(self, act_kwargs) -> dict: + """ + master和slave机器上的端口可能不一致,需要计算slave上的ports + """ + shutdown_ip_ports_map = defaultdict(list) + for old_master, old_master_ports in act_kwargs.cluster["master_ip_ports_map"].items(): + for old_master_port in old_master_ports: + old_master_ins = "{}:{}".format(old_master, old_master_port) + old_slave_ins = act_kwargs.cluster["ins_pair_map"][old_master_ins] + old_slave = old_slave_ins.split(IP_PORT_DIVIDER)[0] + old_slave_port = old_slave_ins.split(IP_PORT_DIVIDER)[1] + + shutdown_ip_ports_map[old_master].append(int(old_master_port)) + shutdown_ip_ports_map[old_slave].append(int(old_slave_port)) + return dict(shutdown_ip_ports_map) + + def redis_backend_scale_flow(self): + """ + redis 扩缩容流程: + 实例上架->新实例主从关系 -> 同步数据 -> 切换 -> 实例下架 + 需要注意: 这里得new_master/new_slave可以相同。需要提前处理一下 + """ + redis_pipeline = Builder(root_id=self.root_id, data=self.data) + sub_pipelines = [] + for info in self.data["infos"]: + sub_pipeline, act_kwargs = self.__init_builder(_("Redis集群扩缩容"), info) + # 初始化计算一些常用参数 + ins_num = int(info["shard_num"] / info["group_num"]) + new_master_ips = [] + new_slave_ips = [] + new_ports = [] + for group_info in info["backend_group"]: + new_master_ips.append(group_info["master"]) + new_slave_ips.append(group_info["slave"]) + for i in range(0, ins_num): + new_ports.append(DEFAULT_REDIS_START_PORT + i) + + # 安装实例 + redis_install_sub_pipelines = [] + params = { + "meta_role": InstanceRole.REDIS_MASTER.value, + "start_port": DEFAULT_REDIS_START_PORT, + "ports": new_ports, + "instance_numb": ins_num, + "spec_id": info["resource_spec"]["id"], + "spec_config": info["resource_spec"], + } + for ip in new_master_ips: + params["ip"] = ip + redis_install_sub_pipelines.append( + RedisBatchInstallAtomJob(self.root_id, self.data, act_kwargs, params) + ) + params["meta_role"] = InstanceRole.REDIS_SLAVE.value + for ip in new_slave_ips: + params["ip"] = ip + redis_install_sub_pipelines.append( + RedisBatchInstallAtomJob(self.root_id, self.data, act_kwargs, params) + ) + sub_pipeline.add_parallel_sub_pipeline(sub_flow_list=redis_install_sub_pipelines) + + # 计算同步参数 + sync_relations = self.generate_sync_relation( + act_kwargs=act_kwargs, master_ips=new_master_ips, slave_ips=new_slave_ips, ins_num=ins_num + ) + + redis_sync_sub_pipelines = [] + for sync_params in sync_relations: + if act_kwargs.cluster["cluster_type"] == ClusterType.TendisTwemproxyRedisInstance: + pass + sub_builder = RedisMakeSyncAtomJob(self.root_id, self.data, act_kwargs, sync_params) + redis_sync_sub_pipelines.append(sub_builder) + sub_pipeline.add_parallel_sub_pipeline(sub_flow_list=redis_sync_sub_pipelines) + + # TODO 增加一个等待节点 + # 进行切换 + act_kwargs.cluster["cluster_id"] = info["cluster_id"] + act_kwargs.cluster["switch_condition"] = { + "is_check_sync": True, # 不强制切换 + "slave_master_diff_time": DEFAULT_MASTER_DIFF_TIME, + "last_io_second_ago": DEFAULT_LAST_IO_SECOND_AGO, + "can_write_before_switch": True, + "sync_type": act_kwargs.cluster["sync_type"], + } + sub_builder = RedisClusterSwitchAtomJob(self.root_id, self.data, act_kwargs, sync_relations) + sub_pipeline.add_sub_pipeline(sub_flow=sub_builder) + + # 下架老实例 + redis_shutdown_sub_pipelines = [] + act_kwargs.cluster["created_by"] = self.data["created_by"] + shutdown_ip_ports = self.generate_shutdown_ins(act_kwargs) + for ip, ports in shutdown_ip_ports.items(): + params = { + "ip": ip, + "ports": ports, + } + redis_shutdown_sub_pipelines.append( + RedisBatchShutdownAtomJob(self.root_id, self.data, act_kwargs, params) + ) + + sub_pipeline.add_parallel_sub_pipeline(sub_flow_list=redis_shutdown_sub_pipelines) + sub_pipelines.append( + sub_pipeline.build_sub_process(sub_name=_("{}backend扩缩容").format(act_kwargs.cluster["cluster_name"])) + ) + + redis_pipeline.add_parallel_sub_pipeline(sub_pipelines) + redis_pipeline.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py index 5252a0a32b..00914014e5 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_proxy_scale.py @@ -136,6 +136,8 @@ def redis_proxy_scale_up_flow(self): "proxy_port": cluster_info["proxy_port"], "servers": cluster_info["servers"], "conf_configs": config_info, + "spec_id": info["resource_spec"]["id"], + "spec_config": info["resource_spec"], } for proxy_info in info["proxy_scale_up_hosts"]: ip = proxy_info["ip"] @@ -242,7 +244,10 @@ def redis_proxy_scale_down_flow(self): sub_pipeline.add_act( act_name=_("初始化配置"), act_component_code=GetRedisActPayloadComponent.code, kwargs=asdict(act_kwargs) ) - # TODO 增加一个等待节点 + + # TODO + # sub_pipeline.add_act(act_name=_("人工确认"), act_component_code=PauseComponent.code, kwargs={}) + # 清理域名 dns_kwargs = DnsKwargs( dns_op_type=DnsOpType.RECYCLE_RECORD, diff --git a/dbm-ui/backend/flow/engine/controller/redis.py b/dbm-ui/backend/flow/engine/controller/redis.py index 72435f3a55..6fcbcbc8b9 100644 --- a/dbm-ui/backend/flow/engine/controller/redis.py +++ b/dbm-ui/backend/flow/engine/controller/redis.py @@ -9,6 +9,7 @@ specific language governing permissions and limitations under the License. """ from backend.flow.engine.bamboo.scene.redis.redis_add_dts_server import RedisAddDtsServerFlow +from backend.flow.engine.bamboo.scene.redis.redis_backend_scale import RedisBackendScaleFlow from backend.flow.engine.bamboo.scene.redis.redis_cluster_apply_flow import RedisClusterApplyFlow from backend.flow.engine.bamboo.scene.redis.redis_cluster_backup import RedisClusterBackupFlow from backend.flow.engine.bamboo.scene.redis.redis_cluster_dts import RedisClusterDtsFlow @@ -111,6 +112,13 @@ def redis_proxy_scale(self): flow = RedisProxyScaleFlow(root_id=self.root_id, data=self.ticket_data) flow.redis_proxy_scale_flow() + def redis_backend_scale(self): + """ + redis后端扩缩容 + """ + flow = RedisBackendScaleFlow(root_id=self.root_id, data=self.ticket_data) + flow.redis_backend_scale_flow() + def redis_cluster_cutoff_scene(self): """ tendis 集群版, master/slave/proxy 裁撤、迁移场景 diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index e47ce4d0a0..a087a1b9a2 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -94,6 +94,7 @@ InstallRedisCacheClusterSceneApiView, InstallTendisplusClusterSceneApiView, RedisAddDtsServerSceneApiView, + RedisBackendScaleSceneApiView, RedisClusterBackupSceneApiView, RedisClusterDtsSceneApiView, RedisClusterOpenCloseSceneApiView, @@ -152,6 +153,7 @@ url(r"^scene/redis_shutdown$", RedisClusterShutdownSceneApiView.as_view()), url(r"^scene/redis_flush_data$", RedisFlushDataSceneApiView.as_view()), url(r"^scene/redis_proxy_scale$", RedisProxyScaleSceneApiView.as_view()), + url(r"^scene/redis_backend_scale$", RedisBackendScaleSceneApiView.as_view()), url(r"^scene/single_redis_shutdown$", SingleRedisShutdownSceneApiView.as_view()), url(r"^scene/single_proxy_shutdown$", SingleProxyShutdownSceneApiView.as_view()), url(r"^scene/cutoff/redis_cluster$", RedisClusterCompleteReplaceSceneApiView.as_view()), diff --git a/dbm-ui/backend/flow/utils/dns_manage.py b/dbm-ui/backend/flow/utils/dns_manage.py index f293e56885..7988c9bc48 100644 --- a/dbm-ui/backend/flow/utils/dns_manage.py +++ b/dbm-ui/backend/flow/utils/dns_manage.py @@ -67,7 +67,7 @@ def create_domain(self, instance_list: list, add_domain_name: str) -> bool: ) return True - def delete_domain(self, cluster_id: int, is_only_delete_slave_domain: bool) -> bool: + def delete_domain(self, cluster_id: int, is_only_delete_slave_domain=False) -> bool: """ 删除域名, 删除域名的方式是传入的集群id(cluster_id) ,清理db-meta注册的域名信息, 适用场景:集群回收 @param cluster_id : 集群id diff --git a/dbm-ui/backend/flow/views/redis_cluster.py b/dbm-ui/backend/flow/views/redis_cluster.py index ea54ae5de5..d47127a700 100644 --- a/dbm-ui/backend/flow/views/redis_cluster.py +++ b/dbm-ui/backend/flow/views/redis_cluster.py @@ -253,6 +253,48 @@ def post(request): return Response({"root_id": root_id}) +class RedisBackendScaleSceneApiView(FlowTestView): + """ + api: /apis/v1/flow/scene/redis_backend_scale + params{ + "bk_biz_id": "", + "ticket_type":"", + "infos":[ + "bk_cloud_id":", + "online_switch_type":"", + "cluster_id": "", # 必须 + "db_version": "Redis-7", # 可选 + "group_num": 4, + "shard_num": 40, # 需要保证分片数能整除机器组数。并且与老集群架构的分片数是一样的 + "backend_group":[ + { + "master":"1.1.1.1", + "slave":"2.2.2.1" + }, + { + "master":"1.1.1.2", + "slave":"2.2.2.2" + }, + { + "master":"1.1.1.3", + "slave":"2.2.2.3" + }, + { + "master":"1.1.1.4", + "slave":"2.2.2.4" + }], + "deploy_plan_id":3, + "resource_spec":{} + }] + """ + + @staticmethod + def post(request): + root_id = uuid.uuid1().hex + RedisController(root_id=root_id, ticket_data=request.data).redis_backend_scale() + return Response({"root_id": root_id}) + + class RedisClusterDtsSceneApiView(FlowTestView): """ api: /apis/v1/flow/scene/redis_cluster_dts From badf1359a8d58bb759cc2f14c9703fb68d00e250 Mon Sep 17 00:00:00 2001 From: iSecloud <869820505@qq.com> Date: Mon, 10 Jul 2023 20:28:55 +0800 Subject: [PATCH 120/476] =?UTF-8?q?fix(backend):=20=E5=85=BC=E5=AE=B9redis?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E9=83=A8=E7=BD=B2=E6=97=A0=E8=A7=84=E6=A0=BC?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5=20#450?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db_services/dbresource/handlers.py | 63 ++++++++++++------- .../redis/resources/redis_cluster/query.py | 13 +++- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/dbm-ui/backend/db_services/dbresource/handlers.py b/dbm-ui/backend/db_services/dbresource/handlers.py index 372ccb5ab0..7962c019d2 100644 --- a/dbm-ui/backend/db_services/dbresource/handlers.py +++ b/dbm-ui/backend/db_services/dbresource/handlers.py @@ -38,16 +38,22 @@ def calc_cluster_shard_num(self): """计算每种规格的分片数, 根据不同的集群计算方式也不同""" raise NotImplementedError() + def _qps_check(self, user_qps_range, spec_qps_range): + """默认判断规则:当前qps与用户需要存在交集""" + if user_qps_range["min"] > spec_qps_range["max"] or user_qps_range["max"] < spec_qps_range["min"]: + return False + + return True + def qps_filter(self): - """根据qps进行筛选: 剔除掉与用户qps没有交集的规格""" + """根据qps进行筛选""" valid_specs: List[Dict[str, Any]] = [] for spec in self.specs: qps_range = { "min": spec["machine_pair"] * spec["qps"]["min"], "max": spec["machine_pair"] * spec["qps"]["max"], } - # 如果当前规格的qps范围与用户的qps范围没有交集,则过滤 - if qps_range["min"] > self.qps["max"] or qps_range["max"] < self.qps["min"]: + if not self._qps_check(qps_range, self.qps): continue valid_specs.append(spec) @@ -84,12 +90,38 @@ class RedisSpecFilter(ClusterSpecFilter): # 按照机器组数正向/逆向排序 MACHINE_PAIR_SORT = False + def _qps_check(self, user_qps_range, spec_qps_range): + # redis可以接受规格qps过大,不接受规格qps小于用户的最小值 + if user_qps_range["min"] > spec_qps_range["max"]: + return False + + return True + def custom_filter(self): """对规格方案进行排序,如果存在大于4个方案,则按比例淘汰末尾规格方案""" self.specs.sort(key=lambda x: x["machine_pair"], reverse=self.MACHINE_PAIR_SORT) if len(self.specs) > self.RECOMMEND_SPEC_NUM: self.specs = self.specs[: -int(len(self.specs) * self.DISUSE_SPEC_RATIO)] + def filter_too_large_building_capacity(self): + """过滤掉过大的建设容量,当建设容量大于目标容量时,默认只保留最小的一个""" + exceed_target_capacity_specs: List[Dict[str, Any]] = [] + in_target_capacity_specs: List[Dict[str, Any]] = [] + for spec in self.specs: + # 首先筛选出建设容量超出目标容量的规格 + if spec["machine_pair"] * spec["capacity"] > self.capacity: + exceed_target_capacity_specs.append(spec) + else: + in_target_capacity_specs.append(spec) + + # 如果存在多个建设容量>目标容量的规格,则取最接近目标容量的规格 + if exceed_target_capacity_specs: + in_target_capacity_specs.append( + sorted(exceed_target_capacity_specs, key=lambda x: x["machine_pair"] * spec["capacity"])[0] + ) + + self.specs = in_target_capacity_specs + class TendisPlusSpecFilter(RedisSpecFilter): """TendisPlus集群规格过滤器""" @@ -110,28 +142,12 @@ def calc_machine_pair(self): def calc_cluster_shard_num(self): for spec in self.specs: spec["cluster_shard_num"] = max(3, math.ceil(self.capacity / self.OPTIMAL_MANAGE_CAPACITY)) - - def custom_filter(self): - """ - TendisPlus自定义过滤规则:至少需要三组机器,保留最近接建设容量大于目标容量的规格方案 - """ - exceed_target_capacity_specs: List[Dict[str, Any]] = [] - in_target_capacity_specs: List[Dict[str, Any]] = [] - for spec in self.specs: - # 首先筛选出建设容量超出目标容量的规格 - if spec["machine_pair"] * spec["capacity"] > self.capacity: - exceed_target_capacity_specs.append(spec) - else: - in_target_capacity_specs.append(spec) - - # 如果存在多个建设容量>目标容量的规格,则取最接近目标容量的规格 - if exceed_target_capacity_specs: - in_target_capacity_specs.append( - sorted(exceed_target_capacity_specs, key=lambda x: x["machine_pair"] * spec["capacity"])[0] + # 将分片数上取整为机器组数的倍数 + spec["cluster_shard_num"] = ( + math.ceil(spec["cluster_shard_num"] / spec["machine_pair"]) * spec["machine_pair"] ) - # 方案淘汰 - self.specs = in_target_capacity_specs + def custom_filter(self): super().custom_filter() @@ -164,4 +180,5 @@ def calc_cluster_shard_num(self): spec["cluster_shard_num"] = single_machine_shard_num * spec["machine_pair"] def custom_filter(self): + super().filter_too_large_building_capacity() super().custom_filter() diff --git a/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py b/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py index 8d32141bd6..86823b9030 100644 --- a/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py +++ b/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py @@ -242,8 +242,15 @@ def _to_cluster_list(cluster, cluster_entry_map: Dict[int, Dict[str, str]]) -> D machine_list = list(set([inst["bk_host_id"] for inst in [*redis_master, *redis_slave]])) machine_pair_cnt = len(machine_list) / 2 + # 补充集群的规格和容量信息 spec_id = Machine.objects.get(bk_host_id=machine_list[0]).spec_id - cluster_spec = Spec.objects.get(spec_id=spec_id) + if not spec_id: + # TODO: 暂时兼容手动部署的情况,后续会删除该逻辑 + cluster_spec = cluster_capacity = "" + else: + spec = Spec.objects.get(spec_id=spec_id) + cluster_spec = model_to_dict(spec) + cluster_capacity = (spec.capacity * machine_pair_cnt,) return { "id": cluster.id, @@ -251,9 +258,9 @@ def _to_cluster_list(cluster, cluster_entry_map: Dict[int, Dict[str, str]]) -> D "status": cluster.status, "cluster_name": cluster.name, "cluster_alias": cluster.alias, - "cluster_spec": model_to_dict(cluster_spec), + "cluster_spec": cluster_spec, # TODO: 待补充当前集群使用容量,需要监控采集的支持 - "cluster_capacity": cluster_spec.capacity * machine_pair_cnt, + "cluster_capacity": cluster_capacity, "bk_biz_id": cluster.bk_biz_id, "bk_biz_name": AppCache.objects.get(bk_biz_id=cluster.bk_biz_id).bk_biz_name, "bk_cloud_id": cluster.bk_cloud_id, From bf368ba4b5b76e8e41e5c8c038f0b9ee71901090 Mon Sep 17 00:00:00 2001 From: daryl Date: Wed, 5 Jul 2023 17:35:05 +0800 Subject: [PATCH 121/476] =?UTF-8?q?fix(frontend):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=B1=A0=E4=BD=93=E9=AA=8C=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20#287?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/views/mission/common/const.ts | 3 +++ dbm-ui/frontend/src/views/mission/pages/Details.vue | 2 +- dbm-ui/frontend/src/views/mission/pages/index.vue | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dbm-ui/frontend/src/views/mission/common/const.ts b/dbm-ui/frontend/src/views/mission/common/const.ts index 2445f00c9b..94b7839a20 100644 --- a/dbm-ui/frontend/src/views/mission/common/const.ts +++ b/dbm-ui/frontend/src/views/mission/common/const.ts @@ -13,7 +13,10 @@ export enum STATUS { CREATED = '等待执行', + READY = '等待执行', RUNNING = '执行中', + SUSPENDED = '执行中', + BLOCKED = '执行中', FINISHED = '执行成功', FAILED = '执行失败', REVOKED = '已终止' diff --git a/dbm-ui/frontend/src/views/mission/pages/Details.vue b/dbm-ui/frontend/src/views/mission/pages/Details.vue index 524f116595..40495c98b8 100644 --- a/dbm-ui/frontend/src/views/mission/pages/Details.vue +++ b/dbm-ui/frontend/src/views/mission/pages/Details.vue @@ -318,7 +318,7 @@ const baseInfo = computed(() => flowState.details.flow_info || {}); const statusText = computed(() => { const value = baseInfo.value.status as STATUS_STRING; - return value ? t(STATUS[value]) : ''; + return value && STATUS[value] ? t(STATUS[value]) : ''; }); const getStatusTheme = (isTag = false) => { diff --git a/dbm-ui/frontend/src/views/mission/pages/index.vue b/dbm-ui/frontend/src/views/mission/pages/index.vue index a9b3cb5913..57c81b147a 100644 --- a/dbm-ui/frontend/src/views/mission/pages/index.vue +++ b/dbm-ui/frontend/src/views/mission/pages/index.vue @@ -140,10 +140,14 @@ render: ({ cell }: { cell: STATUS_STRING }) => { const themes: Partial> = { RUNNING: 'loading', + SUSPENDED: 'loading', + BLOCKED: 'loading', CREATED: 'default', + READY: 'default', FINISHED: 'success', }; - return {t(STATUS[cell])}; + const text = STATUS[cell] ? t(STATUS[cell]) : '--'; + return {text}; }, }, { label: t('关联单据'), From 328ecd5152587dab3fd44b22f0e3033537bdee9f Mon Sep 17 00:00:00 2001 From: daryl Date: Fri, 7 Jul 2023 17:29:06 +0800 Subject: [PATCH 122/476] =?UTF-8?q?feat(frontend):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=BC=80=E5=85=B3=20#440?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/common/importComps.ts | 2 + .../function-controller/FunController.vue | 43 +++ dbm-ui/frontend/src/main.ts | 14 +- dbm-ui/frontend/src/router/index.ts | 19 +- .../src/services/functionController.ts | 24 ++ .../defaultController.json | 59 ++++ .../function-controller/functionController.ts | 64 ++++ dbm-ui/frontend/src/stores/index.ts | 1 + .../frontend/src/stores/useFunController.ts | 43 +++ dbm-ui/frontend/src/types/biz-components.d.ts | 7 + .../views/db-configure/components/TopTab.vue | 38 +- .../frontend/src/views/db-configure/routes.ts | 4 +- dbm-ui/frontend/src/views/es-manage/routes.ts | 16 +- .../frontend/src/views/event-center/routes.ts | 4 +- .../frontend/src/views/hdfs-manage/routes.ts | 16 +- .../src/views/influxdb-manage/routes.ts | 6 +- .../frontend/src/views/kafka-manage/routes.ts | 16 +- .../main-views/common/getRouteChildren.ts | 79 ----- .../src/views/main-views/pages/Database.vue | 320 +++++++++-------- .../src/views/main-views/pages/Platform.vue | 56 +-- .../frontend/src/views/main-views/routes.ts | 263 +++++++++----- dbm-ui/frontend/src/views/mission/routes.ts | 4 +- .../cluster-management/ClusterSingle.vue | 1 - dbm-ui/frontend/src/views/mysql/routes.ts | 136 ++++---- .../mysql/toolbox/components/ToolboxSide.vue | 4 +- .../src/views/password-policy/routes.ts | 4 +- .../src/views/pulsar-manage/routes.ts | 16 +- .../src/views/redis/apply/ApplyRedis.vue | 14 +- .../views/redis/cluster-manage/list/List.vue | 2 +- dbm-ui/frontend/src/views/redis/routes.ts | 24 +- .../redis/toolbox/components/ToolboxSide.vue | 4 +- .../src/views/resource-pool/routes.ts | 4 +- .../components/spec-form-item/SpecStorage.vue | 4 +- .../src/views/resource-spec/pages/Index.vue | 43 ++- .../src/views/resource-spec/routes.ts | 4 +- .../src/views/service-apply/index.vue | 95 +++-- .../src/views/service-apply/routes.ts | 4 +- .../src/views/staff-setting/routes.ts | 4 +- dbm-ui/frontend/src/views/tickets/routes.ts | 4 +- .../version-files/pages/VersionFiles.vue | 324 ++++++++++++------ .../src/views/version-files/routes.ts | 4 +- dbm-ui/frontend/src/views/whitelist/routes.ts | 4 +- 42 files changed, 1200 insertions(+), 597 deletions(-) create mode 100644 dbm-ui/frontend/src/components/function-controller/FunController.vue create mode 100644 dbm-ui/frontend/src/services/functionController.ts create mode 100644 dbm-ui/frontend/src/services/model/function-controller/defaultController.json create mode 100644 dbm-ui/frontend/src/services/model/function-controller/functionController.ts create mode 100644 dbm-ui/frontend/src/stores/useFunController.ts create mode 100644 dbm-ui/frontend/src/types/biz-components.d.ts delete mode 100644 dbm-ui/frontend/src/views/main-views/common/getRouteChildren.ts diff --git a/dbm-ui/frontend/src/common/importComps.ts b/dbm-ui/frontend/src/common/importComps.ts index 90e9a6548f..4abc5fd81b 100644 --- a/dbm-ui/frontend/src/common/importComps.ts +++ b/dbm-ui/frontend/src/common/importComps.ts @@ -26,6 +26,7 @@ import DbStatus from '@components/db-status/index.vue'; import DbTable from '@components/db-table/index.vue'; import DbOriginalTable from '@components/db-table/OriginalTable.vue'; import DbTextarea from '@components/db-textarea/DbTextarea.vue'; +import FunController from '@components/function-controller/FunController.vue'; import SmartAction from '@components/smart-action/index.vue'; import { ipSelector } from '@components/vue2/ip-selector'; @@ -46,4 +47,5 @@ export const setGlobalComps = (app: App) => { app.component('BkIpSelector', ipSelector); app.component('AuthComponent', AuthComponent); app.component('I18nT', Translation); + app.component('FunController', FunController); }; diff --git a/dbm-ui/frontend/src/components/function-controller/FunController.vue b/dbm-ui/frontend/src/components/function-controller/FunController.vue new file mode 100644 index 0000000000..c1f2b14942 --- /dev/null +++ b/dbm-ui/frontend/src/components/function-controller/FunController.vue @@ -0,0 +1,43 @@ + + + diff --git a/dbm-ui/frontend/src/main.ts b/dbm-ui/frontend/src/main.ts index 747d8f56c1..b7213b3231 100644 --- a/dbm-ui/frontend/src/main.ts +++ b/dbm-ui/frontend/src/main.ts @@ -35,6 +35,13 @@ window.changeConfirm = false; (async function () { const app = createApp(App); + const piniaInstance = createPinia(); + // 提早注册确保 getRouter 中可以使用 store + app.use(piniaInstance); + // piniaInstance.use(({ store }) => { + // // eslint-disable-next-line no-param-reassign + // store.router = markRaw(router); + // }); const router = await getRouter(); // 自定义全局组件 @@ -42,13 +49,6 @@ window.changeConfirm = false; // 注册全局指令 setGlobalDirectives(app); - - const piniaInstance = createPinia(); - piniaInstance.use(({ store }) => { - // eslint-disable-next-line no-param-reassign - store.router = markRaw(router); - }); - app.use(piniaInstance); app.use(bkuiVue); app.use(i18n); app.use(router); diff --git a/dbm-ui/frontend/src/router/index.ts b/dbm-ui/frontend/src/router/index.ts index e885cd470e..a971ddbf7f 100644 --- a/dbm-ui/frontend/src/router/index.ts +++ b/dbm-ui/frontend/src/router/index.ts @@ -17,30 +17,19 @@ import { type Router, } from 'vue-router'; -import { checkAuthAllowed } from '@services/common'; - import { useGlobalBizs, useMainViewStore, } from '@stores'; -import { - databaseRoutes, - platformRoutes, - serviceRoutes, -} from '@views/main-views/routes'; +import getRouters from '@views/main-views/routes'; import { routerInterceptor } from './routerInterceptor'; let router: Router; export default async () => { - // 注册平台管理功能 - const [{ is_allowed: isAllowed = false }] = await checkAuthAllowed({ - action_ids: ['DB_MANAGE'], - resources: [], - }); - const renderRouters = isAllowed ? platformRoutes : []; + const routers = await getRouters(); router = createRouter({ history: createWebHistory(window.PROJECT_ENV.VITE_ROUTER_PERFIX), @@ -56,9 +45,7 @@ export default async () => { name: '404', component: () => import('@views/exception/404.vue'), }, - ...serviceRoutes, - ...databaseRoutes, - ...renderRouters, + ...routers, ], }); diff --git a/dbm-ui/frontend/src/services/functionController.ts b/dbm-ui/frontend/src/services/functionController.ts new file mode 100644 index 0000000000..6d1378a0d3 --- /dev/null +++ b/dbm-ui/frontend/src/services/functionController.ts @@ -0,0 +1,24 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import http from './http'; +import defaultData from './model/function-controller/defaultController.json'; +import FunctionControllerModel from './model/function-controller/functionController'; + +/** + * 获取功能开关信息 + * 当接口报错则返回默认配置功能 + */ +export const getFunController = () => http.get('/apis/conf/function_controller/') + .then(res => new FunctionControllerModel(res)) + .catch(() => new FunctionControllerModel(defaultData)); diff --git a/dbm-ui/frontend/src/services/model/function-controller/defaultController.json b/dbm-ui/frontend/src/services/model/function-controller/defaultController.json new file mode 100644 index 0000000000..43b5d27d88 --- /dev/null +++ b/dbm-ui/frontend/src/services/model/function-controller/defaultController.json @@ -0,0 +1,59 @@ +{ + "mysql": { + "is_enabled": true, + "children": { + "toolbox": { + "is_enabled": true + }, + "tendbsingle": { + "is_enabled": true + }, + "tendbha": { + "is_enabled": true + }, + "tendbcluster": { + "is_enabled": false + }, + "tendbcluster_toolbox": { + "is_enabled": false + } + } + }, + "redis": { + "is_enabled": true, + "children": { + "PredixyTendisplusCluster": { + "is_enabled": true + }, + "TwemproxyRedisInstance": { + "is_enabled": true + }, + "TwemproxyTendisSSDInstance": { + "is_enabled": true + }, + "toolbox": { + "is_enabled": false + } + } + }, + "bigdata": { + "is_enabled": true, + "children": { + "es": { + "is_enabled": true + }, + "kafka": { + "is_enabled": true + }, + "hdfs": { + "is_enabled": true + }, + "influxdb": { + "is_enabled": true + }, + "pulsar": { + "is_enabled": true + } + } + } +} diff --git a/dbm-ui/frontend/src/services/model/function-controller/functionController.ts b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts new file mode 100644 index 0000000000..5ef483efa7 --- /dev/null +++ b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts @@ -0,0 +1,64 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +export type MySQLFunctions = 'toolbox' | 'tendbsingle' | 'tendbha' | 'tendbcluster' | 'tendbcluster_toolbox'; +export type RedisFunctions = 'PredixyTendisplusCluster' | 'TwemproxyRedisInstance' | 'TwemproxyTendisSSDInstance' | 'toolbox'; +export type BigdataFunctions = 'es' | 'kafka' | 'hdfs' | 'influxdb' | 'pulsar'; +export type FunctionKeys = MySQLFunctions | RedisFunctions | BigdataFunctions; + +export interface ControllerBaseInfo { + is_enabled: boolean, +} + +interface ControllerItem extends ControllerBaseInfo { + children: Record +} + +interface ControllerData { + mysql: ControllerItem, + redis: ControllerItem, + bigdata: ControllerItem, +} + +export type ExtractedControllerDataKeys = Extract; + + +export default class FunctionController { + mysql: ControllerItem; + redis: ControllerItem; + bigdata: ControllerItem; + + constructor(payload = {} as ControllerData) { + this.mysql = payload.mysql; + this.redis = payload.redis; + this.bigdata = payload.bigdata; + } + + getFlatData< + T extends FunctionKeys, + K extends ExtractedControllerDataKeys + >(key: K) { + const item = this[key] as ControllerItem; + + const flatData = { + [key]: item.is_enabled, + } as Record; + + const { children } = item; + const keys = Object.keys(children) as T[]; + return keys.reduce((res, childKey) => { + res[childKey] = children[childKey].is_enabled; + return res; + }, flatData); + } +} diff --git a/dbm-ui/frontend/src/stores/index.ts b/dbm-ui/frontend/src/stores/index.ts index 1980c96c1d..05b72d1298 100644 --- a/dbm-ui/frontend/src/stores/index.ts +++ b/dbm-ui/frontend/src/stores/index.ts @@ -13,6 +13,7 @@ export * from './globalBizs'; export * from './mainView'; +export * from './useFunController'; export * from './useMenu'; export * from './useSQLTaskCount'; export * from './useSystemEnviron'; diff --git a/dbm-ui/frontend/src/stores/useFunController.ts b/dbm-ui/frontend/src/stores/useFunController.ts new file mode 100644 index 0000000000..98bfbbaf91 --- /dev/null +++ b/dbm-ui/frontend/src/stores/useFunController.ts @@ -0,0 +1,43 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. +*/ + +import { acceptHMRUpdate, defineStore } from 'pinia'; + +import { getFunController } from '@services/functionController'; +import FunctionControllModel from '@services/model/function-controller/functionController'; + +/** + * 配置功能开关 + */ +export const useFunController = defineStore('useFunController', { + state: () => ({ + funControllerData: {} as FunctionControllModel, + isFetched: false, + }), + actions: { + /** + * 获取功能开关配置 + */ + fetchFunController() { + return getFunController().then((res) => { + this.funControllerData = res; + this.isFetched = true; + return res; + }); + }, + }, +}); + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useFunController, import.meta.hot)); +} diff --git a/dbm-ui/frontend/src/types/biz-components.d.ts b/dbm-ui/frontend/src/types/biz-components.d.ts new file mode 100644 index 0000000000..7aec85039c --- /dev/null +++ b/dbm-ui/frontend/src/types/biz-components.d.ts @@ -0,0 +1,7 @@ +declare module 'vue' { + interface GlobalComponents { + FunController: typeof import('../components/function-controller/FunController.vue').default + } +} + +export {}; diff --git a/dbm-ui/frontend/src/views/db-configure/components/TopTab.vue b/dbm-ui/frontend/src/views/db-configure/components/TopTab.vue index ecc9ed4fa2..15cd6996bb 100644 --- a/dbm-ui/frontend/src/views/db-configure/components/TopTab.vue +++ b/dbm-ui/frontend/src/views/db-configure/components/TopTab.vue @@ -18,7 +18,7 @@ type="unborder-card" @change="handleChange"> @@ -28,47 +28,79 @@ diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue index 06785c3b32..e16a5a69b2 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue @@ -17,7 +17,7 @@ + :title="$t('缩容接入层:XXX')" /> @@ -90,6 +90,7 @@ interface InfoItem { cluster_id: number, + bk_cloud_id: number, target_proxy_count:number, online_switch_type: OnlineSwitchType, } @@ -142,6 +143,7 @@ isLoading: false, cluster: item.cluster.immute_domain, clusterId: item.cluster.id, + bkCloudId: item.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { count: item.proxy.length, @@ -171,6 +173,7 @@ isLoading: false, cluster: data.cluster.immute_domain, clusterId: data.cluster.id, + bkCloudId: data.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { count: data.proxy.length, @@ -193,9 +196,9 @@ // 删除一个集群 const handleRemove = (index: number) => { const dataList = [...tableData.value]; - const removeItem = dataList[index]; - const { cluster } = removeItem; + const { cluster } = dataList[index]; dataList.splice(index, 1); + tableData.value = dataList; delete domainMemo[cluster]; }; @@ -205,6 +208,7 @@ const infos = dataArr.map((item, index) => { const obj: InfoItem = { cluster_id: item.clusterId, + bk_cloud_id: item.bkCloudId, target_proxy_count: Number(moreList[index].targetNum), online_switch_type: moreList[index].switchMode, }; @@ -236,7 +240,6 @@ onConfirm: () => { isSubmitting.value = true; createTicket(params).then((data) => { - console.log('createTicket result: ', data); window.changeConfirm = false; router.push({ name: 'RedisProxyScaleDown', @@ -277,7 +280,7 @@ }; - -@/services/model/redis/redis diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue index c9fc1c4c92..aff684beeb 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/Row.vue @@ -77,6 +77,7 @@ isLoading: boolean; cluster: string; clusterId: number; + bkCloudId: number; nodeType: string; spec?: SpecInfo; targetNum?: string; @@ -88,6 +89,7 @@ isLoading: false, cluster: '', clusterId: 0, + bkCloudId: 0, nodeType: '', }); diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue index 230068a7bb..9b1f0c42db 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue @@ -84,9 +84,10 @@ interface InfoItem { cluster_id: number, + bk_cloud_id: number, target_proxy_count: number, resource_spec: { - proxy_scale_up_hosts: { + proxy: { spec_id: number, count: number } @@ -108,7 +109,7 @@ // 检测列表是否为空 const checkListEmpty = (list: Array) => { - if (list.length > 1) { + if (list.length > 0) { return false; } const [firstRow] = list; @@ -140,6 +141,7 @@ isLoading: false, cluster: item.cluster.immute_domain, clusterId: item.cluster.id, + bkCloudId: item.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { count: item.proxy.length, @@ -169,6 +171,7 @@ isLoading: false, cluster: data.cluster.immute_domain, clusterId: data.cluster.id, + bkCloudId: data.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { count: data.proxy.length, @@ -191,9 +194,9 @@ // 删除一个集群 const handleRemove = (index: number) => { const dataList = [...tableData.value]; - const removeItem = dataList[index]; - const { cluster } = removeItem; + const { cluster } = dataList[index]; dataList.splice(index, 1); + tableData.value = dataList; delete domainMemo[cluster]; }; @@ -201,13 +204,15 @@ const generateRequestParam = (moreList: string[]) => { const dataArr = tableData.value.filter(item => item.cluster !== ''); const infos = dataArr.map((item, index) => { + const proxyCount = Number(moreList[index]); const obj: InfoItem = { cluster_id: item.clusterId, - target_proxy_count: Number(moreList[index]), + bk_cloud_id: item.bkCloudId, + target_proxy_count: proxyCount, resource_spec: { - proxy_scale_up_hosts: { + proxy: { spec_id: item.spec?.id ?? 0, - count: item.spec?.count ?? 0, + count: item.spec?.count ? proxyCount - item.spec.count : 0, }, }, }; @@ -252,18 +257,7 @@ }) .catch((e) => { // 目前后台还未调通 - console.error('单据提交失败:', e); - // 暂时先按成功处理 - window.changeConfirm = false; - router.push({ - name: 'RedisProxyScaleUp', - params: { - page: 'success', - }, - query: { - ticketId: '', - }, - }); + console.error('proxy scale up submit ticket error:', e); }) .finally(() => { isSubmitting.value = false; @@ -278,7 +272,7 @@ }; - diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue index 44b555c9ce..6aca7e7496 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue @@ -68,6 +68,7 @@ isLoading: boolean; cluster: string; clusterId: number; + bkCloudId: number; nodeType: string; spec?: SpecInfo; targetNum?: string; @@ -79,6 +80,7 @@ isLoading: false, cluster: '', clusterId: 0, + bkCloudId: 0, nodeType: '', }); diff --git a/dbm-ui/frontend/src/views/redis/routes.ts b/dbm-ui/frontend/src/views/redis/routes.ts index 2f9044ff86..d155944b27 100644 --- a/dbm-ui/frontend/src/views/redis/routes.ts +++ b/dbm-ui/frontend/src/views/redis/routes.ts @@ -150,7 +150,6 @@ export default function getRoutes(controller: Record Date: Wed, 12 Jul 2023 14:39:25 +0800 Subject: [PATCH 128/476] =?UTF-8?q?fix(dbm-services):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=E4=BD=93=E9=AA=8Cbugs=20fix=20close=20#420?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/controller/apply/apply.go | 10 +- .../internal/controller/manage/rs_import.go | 2 +- .../controller/manage/rs_operation_info.go | 15 ++- .../internal/middleware/middleware.go | 7 ++ .../internal/model/TbRpOperatorInfo.go | 1 + .../db-resource/internal/model/model.go | 10 +- .../db-resource/internal/svr/apply/api.go | 93 ++++++++++++-- .../db-resource/internal/svr/apply/apply.go | 115 ++++++++++-------- .../db-resource/internal/svr/apply/core.go | 48 ++++++-- .../internal/svr/apply/instance.go | 13 ++ dbm-services/common/go-pubpkg/cmutil/slice.go | 39 +++--- .../go-pubpkg/errno/60000_dbresource_code.go | 12 +- dbm-services/common/go-pubpkg/errno/errno.go | 7 +- 13 files changed, 265 insertions(+), 107 deletions(-) diff --git a/dbm-services/common/db-resource/internal/controller/apply/apply.go b/dbm-services/common/db-resource/internal/controller/apply/apply.go index 51ac691094..a1cdd259f2 100644 --- a/dbm-services/common/db-resource/internal/controller/apply/apply.go +++ b/dbm-services/common/db-resource/internal/controller/apply/apply.go @@ -21,6 +21,7 @@ import ( "dbm-services/common/db-resource/internal/svr/apply" "dbm-services/common/db-resource/internal/svr/task" "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/errno" "dbm-services/common/go-pubpkg/logger" "github.com/gin-gonic/gin" @@ -148,14 +149,14 @@ func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { } requestId = r.GetString("request_id") if err := param.ParamCheck(); err != nil { - c.SendResponse(r, err, err.Error(), requestId) + c.SendResponse(r, errno.ErrApplyResourceParamCheck.AddErr(err), err.Error(), requestId) return } // get the resource lock if it is dry run you do not need to acquire it if !param.DryRun { lock := newLocker(param.LockKey(), requestId) if err := lock.Lock(); err != nil { - c.SendResponse(r, err, err.Error(), requestId) + c.SendResponse(r, errno.ErrResourceLock.AddErr(err), err.Error(), requestId) return } defer func() { @@ -170,8 +171,7 @@ func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { }() pickers, err = apply.CycleApply(param) if err != nil { - logger.Error("apply machine failed %s", err.Error()) - c.SendResponse(r, err, err.Error(), requestId) + c.SendResponse(r, err, "", requestId) return } if param.DryRun { @@ -180,7 +180,7 @@ func (c *ApplyHandler) ApplyBase(r *gin.Context, mode string) { } data, err := apply.LockReturnPickers(pickers, mode) if err != nil { - c.SendResponse(r, err, nil, requestId) + c.SendResponse(r, errno.ErresourceLockReturn.AddErr(err), nil, requestId) return } logger.Info(fmt.Sprintf("The %s, will return %d machines", requestId, len(data))) diff --git a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go index 8a34525c66..bd2b50f0e1 100644 --- a/dbm-services/common/db-resource/internal/controller/manage/rs_import.go +++ b/dbm-services/common/db-resource/internal/controller/manage/rs_import.go @@ -158,7 +158,7 @@ func (p ImportMachParam) transParamToBytes() (lableJson, bizJson, rstypes json.R } rstypes = []byte("[]") if len(p.RsTypes) > 0 { - rstypes, err = json.Marshal(p.RsTypes) + rstypes, err = json.Marshal(cmutil.CleanStrElems(p.RsTypes)) if err != nil { logger.Error(fmt.Sprintf("conver resource types Failed,Error:%s", err.Error())) return diff --git a/dbm-services/common/db-resource/internal/controller/manage/rs_operation_info.go b/dbm-services/common/db-resource/internal/controller/manage/rs_operation_info.go index edb7b51430..93bf3be92a 100644 --- a/dbm-services/common/db-resource/internal/controller/manage/rs_operation_info.go +++ b/dbm-services/common/db-resource/internal/controller/manage/rs_operation_info.go @@ -12,6 +12,7 @@ package manage import ( "fmt" + "strings" "dbm-services/common/db-resource/internal/model" "dbm-services/common/go-pubpkg/cmutil" @@ -26,11 +27,13 @@ import ( type GetOperationInfoParam struct { OperationType string `json:"operation_type"` BillIds []string `json:"bill_ids"` + BillTypes []string `json:"bill_types"` TaskIds []string `json:"task_ids"` IpList []string `json:"ip_list"` Operator string `json:"operator"` BeginTime string `json:"begin_time" binding:"omitempty,datetime=2006-01-02 15:04:05" ` EndTime string `json:"end_time" binding:"omitempty,datetime=2006-01-02 15:04:05"` + Orderby string `json:"orderby"` Limit int `json:"limit"` Offset int `json:"offset"` } @@ -43,7 +46,7 @@ func (o MachineResourceHandler) OperationInfoList(r *gin.Context) { logger.Error(fmt.Sprintf("Preare Error %s", err.Error())) return } - db := model.DB.Self.Table(model.TbRpOperationInfoTableName()).Where("status != ? ", model.Prepoccupied) + db := model.DB.Self.Table(model.TbRpOperationInfoTableName()) input.query(db) var count int64 if err := db.Count(&count).Error; err != nil { @@ -72,6 +75,9 @@ func (p GetOperationInfoParam) query(db *gorm.DB) { if len(p.BillIds) > 0 { db.Where("bill_id in (?)", p.BillIds) } + if len(p.BillTypes) > 0 { + db.Where("bill_type in (?)", p.BillTypes) + } if len(p.TaskIds) > 0 { db.Where("task_id in (?)", p.TaskIds) } @@ -87,5 +93,10 @@ func (p GetOperationInfoParam) query(db *gorm.DB) { if cmutil.IsNotEmpty(p.BeginTime) { db.Where("create_time >= ? ", p.BeginTime) } - db.Order("create_time desc") + switch strings.ToLower(strings.TrimSpace(p.Orderby)) { + case "asc": + db.Order("create_time asc") + default: + db.Order("create_time desc") + } } diff --git a/dbm-services/common/db-resource/internal/middleware/middleware.go b/dbm-services/common/db-resource/internal/middleware/middleware.go index c596467de4..5f5247d37d 100644 --- a/dbm-services/common/db-resource/internal/middleware/middleware.go +++ b/dbm-services/common/db-resource/internal/middleware/middleware.go @@ -10,6 +10,7 @@ import ( "dbm-services/common/db-resource/internal/controller" "dbm-services/common/db-resource/internal/model" + "dbm-services/common/go-pubpkg/cmutil" "dbm-services/common/go-pubpkg/logger" "github.com/gin-contrib/requestid" @@ -56,6 +57,11 @@ func ApiLogger(c *gin.Context) { rid := requestid.Get(c) c.Set("request_id", rid) if c.Request.Method == http.MethodPost { + // 记录重要api请求日志 + if !cmutil.HasElem(c.Request.RequestURI, []string{"/resource/pre-apply", "/resource/import", "/resource/apply", + "/resource/confirm/apply", "/resource/update"}) { + return + } var bodyBytes []byte // read from the original request body bodyBytes, err := ioutil.ReadAll(c.Request.Body) @@ -70,6 +76,7 @@ func ApiLogger(c *gin.Context) { if err := model.CreateTbRequestLog(model.TbRequestLog{ RequestID: rid, RequestUser: "", + RequestUrl: c.Request.RequestURI, RequestBody: string(bodyBytes), SourceIP: c.Request.RemoteAddr, CreateTime: time.Now(), diff --git a/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go b/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go index 1ad15e2491..87f40c5e17 100644 --- a/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go +++ b/dbm-services/common/db-resource/internal/model/TbRpOperatorInfo.go @@ -34,6 +34,7 @@ type TbRpOperationInfo struct { Status string `gorm:"column:status;type:varchar(64);not null;comment: status" json:"-"` TaskId string `gorm:"column:task_id;type:varchar(128);not null;comment:'task Id'" json:"task_id"` BillId string `gorm:"column:bill_id;type:varchar(128);not null;comment:'bill Id'" json:"bill_id"` + BillType string `gorm:"column:bill_type;type:varchar(128);not null;comment:'bill type'" json:"bill_type"` Desc string `gorm:"column:desc;type:varchar(256);not null;comment:'desc'" json:"desc"` UpdateTime time.Time `gorm:"column:update_time;type:timestamp" json:"update_time"` // 最后修改时间 CreateTime time.Time `gorm:"column:create_time;type:datetime" json:"create_time"` // 创建时间 diff --git a/dbm-services/common/db-resource/internal/model/model.go b/dbm-services/common/db-resource/internal/model/model.go index bab4a5ed35..bb29d56341 100644 --- a/dbm-services/common/db-resource/internal/model/model.go +++ b/dbm-services/common/db-resource/internal/model/model.go @@ -81,14 +81,16 @@ func createSysDb() { if err != nil { log.Fatalf("init create db failed:%s", err.Error()) } - var autoIncrement int64 + var autoIncrement sql.NullInt64 err = testConn.Raw(fmt.Sprintf("select max(id) from `%s`.`%s`", dbname, TbRpDetailArchiveName())).Scan(&autoIncrement). Error if err != nil { log.Fatalf("get max autoIncrement from tb_rp_detail_archive failed :%s", err.Error()) } - if autoIncrement > 0 { - testConn.Exec(fmt.Sprintf("alter table `%s`.`%s` AUTO_INCREMENT = %d ", dbname, TbRpDetailName(), autoIncrement+1)) + + if autoIncrement.Valid { + testConn.Exec(fmt.Sprintf("alter table `%s`.`%s` AUTO_INCREMENT = %d ", dbname, TbRpDetailName(), + autoIncrement.Int64+1)) if err != nil { log.Fatalf("get max autoIncrement from tb_rp_detail_archive failed :%s", err.Error()) } @@ -230,6 +232,7 @@ func (jsonQuery *JSONQueryExpression) NumRange(min int, max int, keys ...string) func (jsonQuery *JSONQueryExpression) Gte(val int, keys ...string) *JSONQueryExpression { jsonQuery.keys = keys jsonQuery.Gtv = val + jsonQuery.gte = true return jsonQuery } @@ -237,6 +240,7 @@ func (jsonQuery *JSONQueryExpression) Gte(val int, keys ...string) *JSONQueryExp func (jsonQuery *JSONQueryExpression) Lte(val int, keys ...string) *JSONQueryExpression { jsonQuery.keys = keys jsonQuery.Ltv = val + jsonQuery.lte = true return jsonQuery } diff --git a/dbm-services/common/db-resource/internal/svr/apply/api.go b/dbm-services/common/db-resource/internal/svr/apply/api.go index f06fdfa08f..7d804929cf 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/api.go +++ b/dbm-services/common/db-resource/internal/svr/apply/api.go @@ -24,6 +24,17 @@ import ( // ParamCheck TODO func (param *ApplyRequestInputParam) ParamCheck() (err error) { for _, a := range param.Details { + for _, d := range a.StorageSpecs { + if d.MaxSize > 0 && d.MinSize > d.MaxSize { + return fmt.Errorf("min %d great thane min %d", d.MinSize, d.MaxSize) + } + } + if !a.Spec.Cpu.Iegal() { + return fmt.Errorf("cpu参数不合法: min:%d,max:%d", a.Spec.Cpu.Min, a.Spec.Cpu.Max) + } + if !a.Spec.Mem.Iegal() { + return fmt.Errorf("mem参数不合法: min:%d,max:%d", a.Spec.Mem.Min, a.Spec.Mem.Max) + } // 如果只是申请一个机器,则没有亲和性的必要 if a.Count <= 1 { continue @@ -43,19 +54,15 @@ func (param *ApplyRequestInputParam) ParamCheck() (err error) { case NONE: return nil } - for _, d := range a.StorageSpecs { - if d.MaxSize > 0 && d.MinSize > d.MaxSize { - return fmt.Errorf("min %d great thane min %d", d.MinSize, d.MaxSize) - } - } } - return + return nil } // ActionInfo TODO type ActionInfo struct { TaskId string `json:"task_id"` BillId string `json:"bill_id"` + BillType string `json:"bill_type"` Operator string `json:"operator"` } @@ -102,6 +109,7 @@ func (c ApplyRequestInputParam) GetOperationInfo(requestId, mode string, BkHostIds: bkHostIdsBytes, IpList: ipListBytes, BillId: c.BillId, + BillType: c.BillType, TaskId: c.TaskId, Operator: c.Operator, Status: mode, @@ -150,6 +158,69 @@ type ApplyObjectDetail struct { Count int `json:"count" binding:"required,min=1"` // 申请数量 } +// GetDiskMatchInfo TODO +func (a *ApplyObjectDetail) GetDiskMatchInfo() (message string) { + if len(a.StorageSpecs) > 0 { + for _, d := range a.StorageSpecs { + if cmutil.IsNotEmpty(d.MountPoint) { + message += fmt.Sprintf("disk: mount point: %s", d.MountPoint) + } + if !cmutil.IsNotEmpty(d.DiskType) { + message += " disk type: " + d.DiskType + } + switch { + case d.MaxSize > 0 && d.MinSize > 0: + message += fmt.Sprintf(" size: %d ~ %d G ", d.MinSize, d.MaxSize) + case d.MaxSize > 0 && d.MaxSize <= 0: + message += fmt.Sprintf(" size <= %d G ", d.MaxSize) + case d.MaxSize <= 0 && d.MinSize > 0: + message += fmt.Sprintf(" size >= %d G ", d.MinSize) + } + } + message += "\n\r" + } + return +} + +// GetMessage TODO +func (a *ApplyObjectDetail) GetMessage() (message string) { + message += fmt.Sprintf("group: %s\n\r", a.GroupMark) + if len(a.DeviceClass) > 0 { + message += fmt.Sprintf("device_class: %v\n\r", a.DeviceClass) + } + if a.Spec.NotEmpty() { + if a.Spec.Cpu.IsNotEmpty() { + message += fmt.Sprintf("cpu: %d ~ %d 核\n\r", a.Spec.Cpu.Min, a.Spec.Cpu.Max) + } + if a.Spec.Mem.IsNotEmpty() { + message += fmt.Sprintf("mem: %d ~ %d M\n\r", a.Spec.Mem.Min, a.Spec.Mem.Max) + } + } + message += a.GetDiskMatchInfo() + if !a.LocationSpec.IsEmpty() { + message += fmt.Sprintf("city: %s \n\r", a.LocationSpec.City) + if len(a.LocationSpec.SubZoneIds) > 0 { + if a.LocationSpec.IncludeOrExclude { + message += fmt.Sprintf("subzoneId must exist in the %v", a.LocationSpec.SubZoneIds) + } else { + message += fmt.Sprintf("subzoneId must not exist in the %v", a.LocationSpec.SubZoneIds) + } + } + } + switch a.Affinity { + case NONE: + message += "资源亲和性: NONE\n\r" + case CROS_SUBZONE: + message += "资源亲和性: 同城跨园区\n\r" + case SAME_SUBZONE: + message += "资源亲和性: 同城同园区\n\r" + case SAME_SUBZONE_CROSS_SWTICH: + message += "资源亲和性: 同城同园区 跨交换机跨机架\n\r" + } + message += fmt.Sprintf("申请总数: %d \n\r", a.Count) + return message +} + // GetEmptyDiskSpec TODO func GetEmptyDiskSpec(ds []DiskSpec) (dms []DiskSpec) { for _, v := range ds { @@ -163,6 +234,7 @@ func GetEmptyDiskSpec(ds []DiskSpec) (dms []DiskSpec) { // GetDiskSpecMountPoints TODO func GetDiskSpecMountPoints(ds []DiskSpec) (mountPoints []string) { for _, v := range ds { + logger.Info("disk info %v", v) if v.MountPointIsEmpty() { continue } @@ -174,7 +246,7 @@ func GetDiskSpecMountPoints(ds []DiskSpec) (mountPoints []string) { // Spec TODO type Spec struct { Cpu MeasureRange `json:"cpu"` // cpu range - Mem MeasureRange `json:"mem"` + Mem MeasureRange `json:"ram"` } // IsEmpty TODO @@ -184,7 +256,7 @@ func (s Spec) IsEmpty() bool { // NotEmpty TODO func (s Spec) NotEmpty() bool { - return s.Cpu.IsNotEmpty() && s.Mem.IsNotEmpty() + return s.Cpu.IsNotEmpty() || s.Mem.IsNotEmpty() } // MeasureRange TODO @@ -195,7 +267,10 @@ type MeasureRange struct { // Iegal TODO func (m MeasureRange) Iegal() bool { - return m.Max >= m.Min + if m.IsNotEmpty() { + return m.Max >= m.Min + } + return true } // IsNotEmpty TODO diff --git a/dbm-services/common/db-resource/internal/svr/apply/apply.go b/dbm-services/common/db-resource/internal/svr/apply/apply.go index 75e96b9d0e..7c1ff990dc 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/apply.go +++ b/dbm-services/common/db-resource/internal/svr/apply/apply.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package apply TODO package apply @@ -9,6 +19,7 @@ import ( "dbm-services/common/db-resource/internal/model" "dbm-services/common/db-resource/internal/svr/bk" "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/errno" "dbm-services/common/go-pubpkg/logger" "gorm.io/gorm" @@ -63,7 +74,7 @@ func CycleApply(param ApplyRequestInputParam) (pickers []*PickerObject, err erro // 挑选符合需求的资源 picker, err = s.PickInstance() if err != nil { - return pickers, fmt.Errorf("Picker for %s Failed,Error is %v", v.GroupMark, err) + return pickers, err } // Debug Print Log 挑选实例分区的情况 picker.DebugDistrubuteLog() @@ -81,7 +92,7 @@ func CycleApply(param ApplyRequestInputParam) (pickers []*PickerObject, err erro // RollBackAllInstanceUnused 将 Instance Status Selling ==> Not Selled : 2 --> 0 func RollBackAllInstanceUnused(ms []*PickerObject) { for _, m := range ms { - if err := m.RollbackSatisfiedInstanceStatusUnused(); err != nil { + if err := m.RollbackUnusedInstance(); err != nil { logger.Error(fmt.Sprintf("Rollback Satisfied Instance Status NotSelled Failed,Error %s", err.Error())) } } @@ -94,19 +105,20 @@ func (o *SearchContext) Matcher() (fns []func(db *gorm.DB)) { case len(o.DeviceClass) == 0 && o.Spec.NotEmpty(): fns = append(fns, o.MatchSpec) // 机型参数存在、资源规格参数不存在,匹配机型 - case len(o.DeviceClass) > 0 && o.Spec.NotEmpty(): + case len(o.DeviceClass) > 0 && o.Spec.IsEmpty(): fns = append(fns, o.MatchDeviceClass) // 机型参数存在、资源规格参数存在,先匹配机型,在匹配资源规格 case len(o.DeviceClass) > 0 && o.Spec.NotEmpty(): fns = append(fns, o.MatchSpec) fns = append(fns, o.MatchDeviceClass) + default: + fns = append(fns, func(db *gorm.DB) {}) } - // 没有条件的时候也需要遍历一遍 - fns = append(fns, func(db *gorm.DB) {}) + return } -func (o *SearchContext) pickBase(db *gorm.DB) (err error) { +func (o *SearchContext) pickBase(db *gorm.DB) { db.Where("gse_agent_status_code = ? ", bk.GSE_AGENT_OK) if o.BkCloudId <= 0 { db.Where(" bk_cloud_id = ? and status = ? ", o.ApplyObjectDetail.BkCloudId, model.Unused) @@ -129,73 +141,58 @@ func (o *SearchContext) pickBase(db *gorm.DB) (err error) { strconv.Itoa(o.IntetionBkBizId)})) } o.MatchLables(db) - if err = o.MatchLocationSpec(db); err != nil { - return err - } + o.MatchLocationSpec(db) o.MatchStorage(db) // 如果需要存在跨园区检查则需要判断是否存在网卡id,机架id等 if o.Affinity == SAME_SUBZONE_CROSS_SWTICH { o.UseNetDeviceIsNotEmpty(db) } - return nil } // PickCheck TODO func (o *SearchContext) PickCheck() (err error) { var count int64 - db := model.DB.Self.Table(model.TbRpDetailName()).Select("count(*)") - if err := o.pickBase(db); err != nil { - return err - } - for _, fn := range o.Matcher() { + for idx, fn := range o.Matcher() { + logger.Info("前置检查: 第%d轮资源匹配", idx) + db := model.DB.Self.Table(model.TbRpDetailName()).Select("count(*)") + o.pickBase(db) fn(db) var cnt int64 if err := db.Scan(&cnt).Error; err != nil { logger.Error("query pre check count failed %s", err.Error()) - return err + return errno.ErrDBQuery.AddErr(err) } count += cnt } - logger.Info("count is %d", count) if int(count) < o.Count { - return fmt.Errorf("[pre inspection]: total number of resources initially eligible:%d,number of interface requests:%d", - count, o.Count) + return errno.ErrResourceinsufficient.AddErr(fmt.Errorf("申请需求:%s\n\r资源池符合条件的资源总数:%d 小于申请的数量", o.GetMessage(), + count)) } return nil } -// MatchLables TODO -func (o *SearchContext) MatchLables(db *gorm.DB) { - if len(o.Labels) > 0 { - for key, v := range o.Labels { - db.Where(" ( json_contains(label,json_object(?,?) )", key, v) - } - return - } - db.Where(" JSON_TYPE(label) = 'NULL' OR JSON_LENGTH(label) <= 1 ") -} - // PickInstance TODO func (o *SearchContext) PickInstance() (picker *PickerObject, err error) { picker = NewPicker(o.Count, o.GroupMark) - for _, fn := range o.Matcher() { + matchfuncs := o.Matcher() + for _, fn := range matchfuncs { var items []model.TbRpDetail db := model.DB.Self.Table(model.TbRpDetailName()) - if err = o.pickBase(db); err != nil { - return - } + o.pickBase(db) fn(db) if err = db.Scan(&items).Error; err != nil { logger.Error("query failed %s", err.Error()) - return + return nil, errno.ErrDBQuery.AddErr(err) } // 过滤没有挂载点的磁盘匹配需求 - esspec := GetEmptyDiskSpec(o.StorageSpecs) - if len(esspec) > 0 { + logger.Info("storage spec %v", o.StorageSpecs) + diskSpecs := GetEmptyDiskSpec(o.StorageSpecs) + if len(diskSpecs) > 0 { ts := []model.TbRpDetail{} for _, ins := range items { if err := ins.UnmarshalDiskInfo(); err != nil { - logger.Error("umarshal disk failed %s", err.Error()) + logger.Error("%s umarshal disk failed %s", ins.IP, err.Error()) + return picker, err } logger.Info("%v", ins.Storages) noUseStorages := make(map[string]bk.DiskDetail) @@ -206,22 +203,37 @@ func (o *SearchContext) PickInstance() (picker *PickerObject, err error) { } } logger.Info("nouse: %v", noUseStorages) - if matchNoMountPointStorage(esspec, noUseStorages) { + if matchNoMountPointStorage(diskSpecs, noUseStorages) { ts = append(ts, ins) } } if len(ts) <= 0 { - return picker, fmt.Errorf("did not match the appropriate resources") + if len(matchfuncs) < 2 { + return picker, errno.ErrResourceinsufficient.Add(fmt.Sprintf("匹配磁盘%s,的资源为 0", o.GetDiskMatchInfo())) + } + logger.Info("匹配%s的资源为空", o.GetDiskMatchInfo()) + continue } items = ts } o.PickInstanceBase(picker, items) - logger.Info("picker now is %v", picker) if picker.PickerDone() { return picker, nil } } - return nil, fmt.Errorf("all Instances Cannot Satisfy The Requested Parameters") + return nil, errno.ErrResourceinsufficient.Add(fmt.Sprintf("Picker for %s, 所有资源无法满足 %s的参数需求", o.GroupMark, + o.GetMessage())) +} + +// MatchLables TODO +func (o *SearchContext) MatchLables(db *gorm.DB) { + if len(o.Labels) > 0 { + for key, v := range o.Labels { + db.Where(" ( json_contains(label,json_object(?,?) )", key, v) + } + return + } + db.Where(" JSON_TYPE(label) = 'NULL' OR JSON_LENGTH(label) <= 1 ") } func matchNoMountPointStorage(spec []DiskSpec, sinc map[string]bk.DiskDetail) bool { @@ -261,22 +273,22 @@ func (o *ApplyObjectDetail) PickInstanceBase(picker *PickerObject, items []model logger.Info("the anti-affinity is %s", o.Affinity) switch o.Affinity { case NONE: - data := AnalysisResource(items, true) - picker.PickeElements = data - picker.PickerSameSubZone(false) + picker.PickeElements = AnalysisResource(items, true) + picker.PickerRandom() case CROS_SUBZONE: - data := AnalysisResource(items, false) - picker.PickeElements = data + picker.PickeElements = AnalysisResource(items, false) picker.Picker(true) - case SAME_SUBZONE, SAME_SUBZONE_CROSS_SWTICH: - data := AnalysisResource(items, false) - picker.PickeElements = data + case SAME_SUBZONE: + picker.PickeElements = AnalysisResource(items, false) picker.PickerSameSubZone(false) + case SAME_SUBZONE_CROSS_SWTICH: + picker.PickeElements = AnalysisResource(items, false) + picker.PickerSameSubZone(true) } } // MatchLocationSpec TODO -func (o *SearchContext) MatchLocationSpec(db *gorm.DB) (err error) { +func (o *SearchContext) MatchLocationSpec(db *gorm.DB) { if o.LocationSpec.IsEmpty() { return } @@ -308,6 +320,7 @@ func (o *SearchContext) MatchStorage(db *gorm.DB) { if cmutil.IsNotEmpty(d.DiskType) { db.Where(model.JSONQuery("storage_device").Equals(d.DiskType, mp, "disk_type")) } + logger.Info("storage spec is %v", d) switch { case d.MaxSize > 0: db.Where(model.JSONQuery("storage_device").NumRange(d.MinSize, d.MaxSize, mp, "size")) diff --git a/dbm-services/common/db-resource/internal/svr/apply/core.go b/dbm-services/common/db-resource/internal/svr/apply/core.go index ed61e65436..dbf6a7f94f 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/core.go +++ b/dbm-services/common/db-resource/internal/svr/apply/core.go @@ -16,23 +16,27 @@ import ( const ( // MINDISTRUTE TODO MINDISTRUTE = 20 + // RANDOM TODO + RANDOM = "RANDOM" ) type subzone = string // PickerObject TODO type PickerObject struct { - Item string - Count int - PickDistrbute map[string]int - ExistSubZone []subzone // 已存在的园区 - // SatisfiedAssetIds []string // 已选择 满足的实例 - SatisfiedHostIds []int - PickeElements map[subzone][]InstanceObject // 待选择实例 + Item string + Count int + PickDistrbute map[string]int + ExistSubZone []subzone // 已存在的园区 + SatisfiedHostIds []int + SelectedResources []*model.TbRpDetail + + PickeElements map[subzone][]InstanceObject // 待选择实例 // 资源请求在同园区的时候才生效 ExistEquipmentIds []string // 已存在的设备Id ExistLinkNetdeviceIds []string // 已存在的网卡Id + ProcessLogs []string } // LockReturnPickers TODO @@ -51,7 +55,7 @@ func LockReturnPickers(elements []*PickerObject, mode string) ([]model.BatchGetT } data, err := model.BatchGetSatisfiedByAssetIds(getter, mode) if err != nil { - logger.Error(fmt.Sprintf("选择到合适的实例,获取实例详情失败%s", err.Error())) + logger.Error(fmt.Sprintf("占用机器,更改机器状态失败%s", err.Error())) } if mode == model.Used { sendArchiverTask(data) @@ -95,9 +99,10 @@ func AnalysisResource(ins []model.TbRpDetail, israndom bool) map[string][]Instan Equipment: v.RackID, LinkNetdeviceId: linkids, Nice: createNice(int(v.CPUNum), v.DramCap, 0, 0), + InsDetail: &v, } if israndom { - result["RANDOM"] = append(result["RANDOM"], t) + result[RANDOM] = append(result[RANDOM], t) } else { result[v.SubZone] = append(result[v.SubZone], t) } @@ -137,6 +142,8 @@ func (c *PickerObject) PickerSameSubZone(cross_switch bool) { for _, subzone := range sortSubZones { logger.Info("PickerSameSubZone:PickeElements: %v", c.PickeElements[subzone]) if len(c.PickeElements[subzone]) < c.Count || len(c.PickeElements[subzone]) <= 0 { + c.ProcessLogs = append(c.ProcessLogs, fmt.Sprintf("%s 符合条件的资源有%d,实际需要申请%d,不满足!!!", + subzone, len(c.PickeElements[subzone]), c.Count)) continue } logger.Info("dbeug %v", subzone) @@ -157,6 +164,19 @@ func (c *PickerObject) PickerSameSubZone(cross_switch bool) { } } +// PickerRandom TODO +func (c *PickerObject) PickerRandom() { + for idx := range c.PickeElements[RANDOM] { + logger.Info("loop %d", idx) + c.pickerOne(RANDOM, false) + // 匹配资源完成 + logger.Info("%d,%d", c.Count, len(c.SatisfiedHostIds)) + if c.PickerDone() { + return + } + } +} + // Picker 筛选,匹配资源 // // @receiver c @@ -214,6 +234,7 @@ func (c *PickerObject) pickerOne(key string, cross_switch bool) bool { } c.ExistEquipmentIds = append(c.ExistEquipmentIds, v.Equipment) c.SatisfiedHostIds = append(c.SatisfiedHostIds, v.BkHostId) + c.SelectedResources = append(c.SelectedResources, v.InsDetail) c.ExistLinkNetdeviceIds = append(c.ExistLinkNetdeviceIds, v.LinkNetdeviceId...) c.PickDistrbute[key]++ c.deleteElement(key, v.BkHostId) @@ -268,11 +289,16 @@ func (c *PickerObject) PreselectedSatisfiedInstance() error { return nil } -// RollbackSatisfiedInstanceStatusUnused TODO -func (c *PickerObject) RollbackSatisfiedInstanceStatusUnused() error { +// RollbackUnusedInstance TODO +func (c *PickerObject) RollbackUnusedInstance() error { return model.UpdateTbRpDetailStatusAtSelling(c.SatisfiedHostIds, model.Unused) } +// GetReason TODO +func (c *PickerObject) GetReason() (message string) { + return +} + // CampusNice TODO type CampusNice struct { Campus string `json:"campus"` diff --git a/dbm-services/common/db-resource/internal/svr/apply/instance.go b/dbm-services/common/db-resource/internal/svr/apply/instance.go index a1af259855..59f5aa577b 100644 --- a/dbm-services/common/db-resource/internal/svr/apply/instance.go +++ b/dbm-services/common/db-resource/internal/svr/apply/instance.go @@ -1,11 +1,24 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package apply +import "dbm-services/common/db-resource/internal/model" + // InstanceObject TODO type InstanceObject struct { BkHostId int Equipment string LinkNetdeviceId []string Nice int64 + InsDetail *model.TbRpDetail } // GetLinkNetDeviceIdsInterface TODO diff --git a/dbm-services/common/go-pubpkg/cmutil/slice.go b/dbm-services/common/go-pubpkg/cmutil/slice.go index 18b1bc2664..40b6ade003 100644 --- a/dbm-services/common/go-pubpkg/cmutil/slice.go +++ b/dbm-services/common/go-pubpkg/cmutil/slice.go @@ -1,8 +1,17 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package cmutil import ( "fmt" - "reflect" "strconv" "strings" @@ -91,11 +100,11 @@ func SplitGroup(laxiconid []string, subGroupLength int64) [][]string { } // RemoveEmpty 过滤掉空字符串 -func RemoveEmpty(input []string) []string { +func CleanStrElems(elems []string) []string { var result []string - for _, item := range input { + for _, item := range elems { if strings.TrimSpace(item) != "" { - result = append(result, item) + result = append(result, strings.TrimSpace(item)) } } return result @@ -153,21 +162,13 @@ func ArrayInGroupsOf(arr []string, num int64) [][]string { return segments } -// HasElem TODO -func HasElem(elem interface{}, slice interface{}) bool { - defer func() { - if err := recover(); err != nil { - fmt.Println("HasElem error", err) - } - }() - arrV := reflect.ValueOf(slice) - if arrV.Kind() == reflect.Slice || arrV.Kind() == reflect.Array { - for i := 0; i < arrV.Len(); i++ { - // XXX - panics if slice element points to an unexported struct field - // see https://golang.org/pkg/reflect/#Value.Interface - if reflect.DeepEqual(arrV.Index(i).Interface(), elem) { - return true - } +func HasElem[T int | string](elem T, elems []T) bool { + if len(elems) <= 0 { + return true + } + for _, v := range elems { + if elem == v { + return true } } return false diff --git a/dbm-services/common/go-pubpkg/errno/60000_dbresource_code.go b/dbm-services/common/go-pubpkg/errno/60000_dbresource_code.go index 5d29e1b03a..233e6ffd7f 100644 --- a/dbm-services/common/go-pubpkg/errno/60000_dbresource_code.go +++ b/dbm-services/common/go-pubpkg/errno/60000_dbresource_code.go @@ -13,6 +13,14 @@ package errno var ( // dbresource code start 60000 - // ErrorResourceinsufficient TODO - ErrorResourceinsufficient = Errno{Code: 60001, Message: "resource insufficient", CNMessage: "资源不足"} + // ErrResourceinsufficient TODO + ErrResourceinsufficient = Errno{Code: 60001, Message: "resource insufficient", CNMessage: "资源不足"} + // ErrResourceLock TODO + ErrResourceLock = Errno{Code: 60002, Message: "failed to acquire resource lock", CNMessage: "获取资源锁失败"} + // ErrApplyResourceParamCheck TODO + ErrApplyResourceParamCheck = Errno{Code: 60003, Message: "failed to check the parameters of the applied resource", + CNMessage: "申请资源参数合法性检查不通过"} + // ErresourceLockReturn TODO + ErresourceLockReturn = Errno{Code: 6004, CNMessage: "锁定机器,返回机器失败", + Message: "failed to lock the machine and return the machine"} ) diff --git a/dbm-services/common/go-pubpkg/errno/errno.go b/dbm-services/common/go-pubpkg/errno/errno.go index 10bfc8632b..cc7e659d3b 100644 --- a/dbm-services/common/go-pubpkg/errno/errno.go +++ b/dbm-services/common/go-pubpkg/errno/errno.go @@ -37,12 +37,12 @@ func (err Errno) Error() string { } // Addf TODO -func (err *Errno) Addf(format string, args ...interface{}) error { +func (err Errno) Addf(format string, args ...interface{}) error { return err.Add(fmt.Sprintf(format, args...)) } // Add TODO -func (err *Errno) Add(message string) error { +func (err Errno) Add(message string) error { switch lang { case "zh_CN": err.CNMessage = fmt.Sprintf("[%s]: %s", err.CNMessage, message) @@ -72,7 +72,7 @@ func (err Errno) AddBefore(message string) error { } // AddErr TODO -func (err *Errno) AddErr(xerr error) error { +func (err Errno) AddErr(xerr error) error { message := xerr.Error() if xerr == nil { message = "error is nil" @@ -116,7 +116,6 @@ func DecodeErr(err error) (int, string) { if err == nil { return OK.Code, OK.Message } - switch typed := err.(type) { case Err: if CN { From 8deb40ba363ac8c632bcd731b68bb51ec6b11cc6 Mon Sep 17 00:00:00 2001 From: secloud <47274844+iSecloud@users.noreply.github.com> Date: Thu, 13 Jul 2023 09:47:34 +0800 Subject: [PATCH 129/476] =?UTF-8?q?feat(backend):=20=E6=B1=A1=E7=82=B9?= =?UTF-8?q?=E6=B1=A0=E5=BC=80=E5=8F=91=20#459=20(#460)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/configuration/constants.py | 2 +- dbm-ui/backend/configuration/models/system.py | 2 +- dbm-ui/backend/db_dirty/__init__.py | 10 ++ dbm-ui/backend/db_dirty/admin.py | 20 ++++ dbm-ui/backend/db_dirty/apps.py | 16 +++ dbm-ui/backend/db_dirty/constants.py | 16 +++ dbm-ui/backend/db_dirty/filters.py | 34 ++++++ dbm-ui/backend/db_dirty/handlers.py | 105 ++++++++++++++++++ .../db_dirty/migrations/0001_initial.py | 45 ++++++++ .../backend/db_dirty/migrations/__init__.py | 10 ++ dbm-ui/backend/db_dirty/mock.py | 25 +++++ dbm-ui/backend/db_dirty/models.py | 30 +++++ dbm-ui/backend/db_dirty/serializers.py | 51 +++++++++ dbm-ui/backend/db_dirty/urls.py | 20 ++++ dbm-ui/backend/db_dirty/views.py | 99 +++++++++++++++++ dbm-ui/backend/db_meta/admin.py | 14 +++ dbm-ui/backend/db_meta/models/spec.py | 4 +- .../migrations/0002_auto_20230711_1147.py | 21 ++++ .../db_services/dbresource/serializers.py | 5 + .../db_services/dbresource/views/resource.py | 10 +- .../db_services/ipchooser/constants.py | 2 + .../redis/resources/redis_cluster/query.py | 2 +- .../db_services/taskflow/views/flow.py | 12 +- dbm-ui/backend/dbm_init/services.py | 37 +++--- .../bamboo/scene/common/machine_os_init.py | 4 +- dbm-ui/backend/flow/signal/handlers.py | 36 +++++- dbm-ui/backend/ticket/builders/__init__.py | 28 ++++- dbm-ui/backend/ticket/builders/common/base.py | 5 +- .../backend/ticket/builders/common/bigdata.py | 5 +- dbm-ui/backend/ticket/builders/es/es_apply.py | 3 +- .../backend/ticket/builders/es/es_destroy.py | 3 +- .../backend/ticket/builders/es/es_disable.py | 3 +- .../backend/ticket/builders/es/es_enable.py | 3 +- .../backend/ticket/builders/es/es_replace.py | 2 +- .../backend/ticket/builders/es/es_scale_up.py | 2 +- .../ticket/builders/hdfs/hdfs_apply.py | 3 +- .../ticket/builders/hdfs/hdfs_destroy.py | 3 +- .../ticket/builders/hdfs/hdfs_disable.py | 3 +- .../ticket/builders/hdfs/hdfs_enable.py | 3 +- .../ticket/builders/hdfs/hdfs_replace.py | 2 +- .../ticket/builders/hdfs/hdfs_scale_up.py | 2 +- .../builders/influxdb/influxdb_apply.py | 3 +- .../builders/influxdb/influxdb_destroy.py | 3 +- .../builders/influxdb/influxdb_disable.py | 3 +- .../builders/influxdb/influxdb_enable.py | 3 +- .../builders/influxdb/influxdb_replace.py | 2 +- .../ticket/builders/kafka/kafka_apply.py | 3 +- .../ticket/builders/kafka/kafka_destroy.py | 3 +- .../ticket/builders/kafka/kafka_disable.py | 3 +- .../ticket/builders/kafka/kafka_enable.py | 3 +- .../ticket/builders/kafka/kafka_replace.py | 2 +- .../ticket/builders/kafka/kafka_scale_up.py | 2 +- dbm-ui/backend/ticket/builders/mysql/base.py | 6 +- .../ticket/builders/mysql/mysql_add_slave.py | 2 +- .../ticket/builders/mysql/mysql_ha_apply.py | 2 +- .../ticket/builders/mysql/mysql_ha_destroy.py | 3 +- .../ticket/builders/mysql/mysql_ha_disable.py | 3 +- .../ticket/builders/mysql/mysql_ha_enable.py | 3 +- .../builders/mysql/mysql_migrate_cluster.py | 2 +- .../ticket/builders/mysql/mysql_proxy_add.py | 2 +- .../builders/mysql/mysql_proxy_switch.py | 2 +- .../builders/mysql/mysql_restore_slave.py | 2 +- .../builders/mysql/mysql_single_apply.py | 2 +- .../builders/mysql/mysql_single_destroy.py | 3 +- .../builders/mysql/mysql_single_disable.py | 3 +- .../builders/mysql/mysql_single_enable.py | 3 +- .../ticket/builders/pulsar/pulsar_apply.py | 3 +- .../ticket/builders/pulsar/pulsar_destroy.py | 3 +- .../ticket/builders/pulsar/pulsar_disable.py | 3 +- .../ticket/builders/pulsar/pulsar_enable.py | 3 +- .../ticket/builders/pulsar/pulsar_replace.py | 2 +- .../ticket/builders/pulsar/pulsar_scale_up.py | 2 +- .../ticket/builders/redis/redis_close.py | 3 +- .../builders/redis/redis_cluster_apply.py | 2 +- .../ticket/builders/redis/redis_destroy.py | 3 +- .../ticket/builders/redis/redis_open.py | 3 +- .../builders/redis/redis_toolbox_cut_off.py | 2 +- .../redis/redis_toolbox_proxy_scale_up.py | 2 +- .../redis/redis_toolbox_redis_scale_up.py | 2 +- dbm-ui/backend/ticket/constants.py | 68 +----------- .../backend/ticket/flow_manager/resource.py | 15 ++- dbm-ui/backend/ticket/handler.py | 64 +++++++++++ dbm-ui/backend/ticket/todos/pause_todo.py | 10 +- dbm-ui/backend/ticket/views.py | 63 +---------- dbm-ui/backend/urls.py | 1 + dbm-ui/config/default.py | 1 + 86 files changed, 808 insertions(+), 217 deletions(-) create mode 100644 dbm-ui/backend/db_dirty/__init__.py create mode 100644 dbm-ui/backend/db_dirty/admin.py create mode 100644 dbm-ui/backend/db_dirty/apps.py create mode 100644 dbm-ui/backend/db_dirty/constants.py create mode 100644 dbm-ui/backend/db_dirty/filters.py create mode 100644 dbm-ui/backend/db_dirty/handlers.py create mode 100644 dbm-ui/backend/db_dirty/migrations/0001_initial.py create mode 100644 dbm-ui/backend/db_dirty/migrations/__init__.py create mode 100644 dbm-ui/backend/db_dirty/mock.py create mode 100644 dbm-ui/backend/db_dirty/models.py create mode 100644 dbm-ui/backend/db_dirty/serializers.py create mode 100644 dbm-ui/backend/db_dirty/urls.py create mode 100644 dbm-ui/backend/db_dirty/views.py create mode 100644 dbm-ui/backend/db_proxy/migrations/0002_auto_20230711_1147.py diff --git a/dbm-ui/backend/configuration/constants.py b/dbm-ui/backend/configuration/constants.py index d6147a1838..c0e65e24ea 100644 --- a/dbm-ui/backend/configuration/constants.py +++ b/dbm-ui/backend/configuration/constants.py @@ -62,7 +62,7 @@ class DBType(str, StructuredEnum): # mysql/redis-监控自定义上报: dataid/token BKM_DBM_REPORT = "BKM_DBM_REPORT" # 默认资源池空闲模块 -RESOURCE_TOPO = "RESOURCE_TOPO" +MANAGE_TOPO = "MANAGE_TOPO" # 业务空闲模块ID diff --git a/dbm-ui/backend/configuration/models/system.py b/dbm-ui/backend/configuration/models/system.py index ea1c51dcfc..bdecc2f178 100644 --- a/dbm-ui/backend/configuration/models/system.py +++ b/dbm-ui/backend/configuration/models/system.py @@ -27,7 +27,7 @@ class SystemSettingsEnum(str, StructuredEnum): """配置的枚举项,建议将系统配置都录入到这里方便统一管理""" BK_ITSM_SERVICE_ID = EnumField("BK_ITSM_SERVICE_ID", _("DBM的流程服务ID")) - RESOURCE_TOPO = EnumField("RESOURCE_TOPO", _("资源池主机存放的拓扑信息")) + MANAGE_TOPO = EnumField("MANAGE_TOPO", _("DBM系统的管理集群拓扑")) class SystemSettings(AuditedModel): diff --git a/dbm-ui/backend/db_dirty/__init__.py b/dbm-ui/backend/db_dirty/__init__.py new file mode 100644 index 0000000000..aa5085c628 --- /dev/null +++ b/dbm-ui/backend/db_dirty/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" diff --git a/dbm-ui/backend/db_dirty/admin.py b/dbm-ui/backend/db_dirty/admin.py new file mode 100644 index 0000000000..86f0e6ac8e --- /dev/null +++ b/dbm-ui/backend/db_dirty/admin.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.contrib import admin + +from . import models + + +@admin.register(models.DirtyMachine) +class DirtyMachineAdmin(admin.ModelAdmin): + list_display = ("ip", "bk_biz_id", "bk_host_id", "flow", "ticket") + list_filter = ("ip", "bk_biz_id", "bk_host_id", "flow", "ticket") + search_fields = ("ip", "bk_biz_id", "bk_host_id", "flow", "ticket") diff --git a/dbm-ui/backend/db_dirty/apps.py b/dbm-ui/backend/db_dirty/apps.py new file mode 100644 index 0000000000..30b9fd7bb6 --- /dev/null +++ b/dbm-ui/backend/db_dirty/apps.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.apps import AppConfig + + +class DbDirtyConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "backend.db_dirty" diff --git a/dbm-ui/backend/db_dirty/constants.py b/dbm-ui/backend/db_dirty/constants.py new file mode 100644 index 0000000000..08bd76fb1c --- /dev/null +++ b/dbm-ui/backend/db_dirty/constants.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import ugettext_lazy as _ + +from backend.ticket.constants import TicketType + +SWAGGER_TAG = _("污点池") diff --git a/dbm-ui/backend/db_dirty/filters.py b/dbm-ui/backend/db_dirty/filters.py new file mode 100644 index 0000000000..26d5915d18 --- /dev/null +++ b/dbm-ui/backend/db_dirty/filters.py @@ -0,0 +1,34 @@ +# -*- coding:utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import ugettext_lazy as _ +from django_filters import rest_framework as filters + +from backend.db_dirty.models import DirtyMachine +from backend.ticket.constants import TicketType + + +class DirtyMachineFilter(filters.FilterSet): + ticket_type = filters.ChoiceFilter( + field_name="ticket__ticket_type", choices=TicketType.get_choices(), label=_("单据类型") + ) + ticket_id = filters.NumberFilter(field_name="ticket__id", label=_("单据ID")) + task_id = filters.CharFilter(field_name="flow__flow_obj_id", lookup_expr="exact", label=_("任务ID")) + operator = filters.CharFilter(field_name="ticket__creator", lookup_expr="icontains", label=_("操作者")) + ip_list = filters.CharFilter(field_name="ip_list", method="filter_ip_list", label=_("过滤IP")) + + def filter_ip_list(self, queryset, name, value): + ip_list = value.split(",") + return queryset.filter(ip__in=ip_list) + + class Meta: + model = DirtyMachine + fields = ["ticket_type", "ticket_id", "task_id", "operator", "ip_list"] diff --git a/dbm-ui/backend/db_dirty/handlers.py b/dbm-ui/backend/db_dirty/handlers.py new file mode 100644 index 0000000000..248d9bbdb3 --- /dev/null +++ b/dbm-ui/backend/db_dirty/handlers.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from collections import defaultdict +from typing import Any, Dict, List + +from backend.components import CCApi +from backend.configuration.constants import MANAGE_TOPO +from backend.configuration.models import SystemSettings +from backend.db_dirty.models import DirtyMachine +from backend.db_meta.models import Machine +from backend.flow.utils.cc_manage import CcManage +from backend.ticket.models import Flow, Ticket + + +class DBDirtyMachineHandler(object): + """ + 污点池处理接口的逻辑处理 + """ + + @classmethod + def transfer_dirty_machines(cls, bk_host_ids: List[int]): + """ + 将污点主机转移待回收模块 + @param bk_host_ids: 主机列表 + """ + dirty_machines = DirtyMachine.objects.filter(bk_host_id__in=bk_host_ids) + bk_biz_id__host_ids = defaultdict(list) + for machine in dirty_machines: + bk_biz_id__host_ids[machine.bk_biz_id].append(machine.bk_host_id) + + for bk_biz_id, bk_host_ids in bk_biz_id__host_ids.items(): + CCApi.transfer_host_to_recyclemodule({"bk_biz_id": bk_biz_id, "bk_host_id": bk_host_ids}) + + dirty_machines.delete() + + @classmethod + def insert_dirty_machines(cls, bk_biz_id: int, bk_host_ids: List[Dict[str, Any]], ticket: Ticket, flow: Flow): + """ + 将机器导入到污点池中 + @param bk_biz_id: 业务ID + @param bk_host_ids: 主机列表 + @param ticket: 关联的单据 + @param flow: 关联的flow任务 + """ + # 排除已经录入到Machine表的机器(因为是成功消费不算污点机器) + db_machines = list(Machine.objects.filter(bk_host_id__in=bk_host_ids).values_list("bk_host_id", flat=True)) + dirty_host_ids = list(set(bk_host_ids) - set(db_machines)) + + # 查询污点机器信息 + host_property_filter = { + "condition": "AND", + "rules": [{"field": "bk_host_id", "operator": "in", "value": dirty_host_ids}], + } + dirty_host_infos = CCApi.list_biz_hosts( + { + "bk_biz_id": bk_biz_id, + # 默认一次性录入的机器不会超过500 + "page": {"start": 0, "limit": 500, "sort": "bk_host_id"}, + "host_property_filter": host_property_filter, + "fields": ["bk_host_id", "bk_cloud_id", "bk_host_innerip"], + } + )["info"] + + # 将污点机器信息转移至污点池模块 + dirty_module = SystemSettings.get_setting_value(key=MANAGE_TOPO)["dirty_module_id"] + CcManage.transfer_host_module(bk_host_ids=dirty_host_ids, target_module_ids=[dirty_module]) + + # 录入污点池表中 + exist_dirty_machine_ids = list( + DirtyMachine.objects.filter(bk_host_id__in=dirty_host_ids).values_list("bk_host_id", flat=True) + ) + DirtyMachine.objects.bulk_create( + [ + DirtyMachine( + ticket=ticket, + flow=flow, + ip=host["bk_host_innerip"], + bk_biz_id=bk_biz_id, + bk_host_id=host["bk_host_id"], + bk_cloud_id=host["bk_cloud_id"], + ) + for host in dirty_host_infos + if host["bk_host_id"] not in exist_dirty_machine_ids + ] + ) + + @classmethod + def remove_dirty_machines(cls, bk_host_ids: List[Dict[str, Any]]): + """ + 将机器从污点池挪走,一般是重试后会调用此函数。 + 这里只用删除记录,无需做其他挪模块的操作,原因如下: + 1. 如果重试依然失败,则机器会重新回归污点池,模块不变 + 2. 如果重试成功,则机器已经由flow挪到了对应的DB模块 + 3. 如果手动处理,则机器会被挪到待回收模块 + @param bk_host_ids: 主机列表 + """ + DirtyMachine.objects.filter(bk_host_id__in=bk_host_ids).delete() diff --git a/dbm-ui/backend/db_dirty/migrations/0001_initial.py b/dbm-ui/backend/db_dirty/migrations/0001_initial.py new file mode 100644 index 0000000000..5d9216b55b --- /dev/null +++ b/dbm-ui/backend/db_dirty/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.19 on 2023-07-11 09:19 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("ticket", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="DirtyMachine", + fields=[ + ("creator", models.CharField(max_length=64, verbose_name="创建人")), + ("create_at", models.DateTimeField(auto_now_add=True, verbose_name="创建时间")), + ("updater", models.CharField(max_length=64, verbose_name="修改人")), + ("update_at", models.DateTimeField(auto_now=True, verbose_name="更新时间")), + ("bk_biz_id", models.IntegerField(default=0, help_text="业务ID")), + ( + "bk_host_id", + models.PositiveBigIntegerField(default=0, help_text="主机ID", primary_key=True, serialize=False), + ), + ("bk_cloud_id", models.IntegerField(default=0, help_text="主机云区域")), + ("ip", models.CharField(help_text="主机IP", max_length=128)), + ( + "flow", + models.ForeignKey(help_text="关联任务", on_delete=django.db.models.deletion.CASCADE, to="ticket.flow"), + ), + ( + "ticket", + models.ForeignKey( + help_text="关联单据", on_delete=django.db.models.deletion.CASCADE, to="ticket.ticket" + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/dbm-ui/backend/db_dirty/migrations/__init__.py b/dbm-ui/backend/db_dirty/migrations/__init__.py new file mode 100644 index 0000000000..aa5085c628 --- /dev/null +++ b/dbm-ui/backend/db_dirty/migrations/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" diff --git a/dbm-ui/backend/db_dirty/mock.py b/dbm-ui/backend/db_dirty/mock.py new file mode 100644 index 0000000000..4dbd38149c --- /dev/null +++ b/dbm-ui/backend/db_dirty/mock.py @@ -0,0 +1,25 @@ +# -*- coding:utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + + +DIRTY_MACHINE_LIST = [ + { + "ip": "127.0.0.4", + "bk_host_id": 4, + "bk_cloud_name": "direct area", + "bk_cloud_id": 0, + "bk_biz_name": "DBA", + "bk_biz_id": 3, + "ticket_type": "REDIS_CLUSTER_APPLY", + "ticket_id": 1, + "task_id": "", + } +] diff --git a/dbm-ui/backend/db_dirty/models.py b/dbm-ui/backend/db_dirty/models.py new file mode 100644 index 0000000000..4d94d0d217 --- /dev/null +++ b/dbm-ui/backend/db_dirty/models.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from backend.bk_web.constants import LEN_MIDDLE +from backend.bk_web.models import AuditedModel +from backend.ticket.models import Flow, Ticket + + +class DirtyMachine(AuditedModel): + """ + 污点机器记录:从资源池申请成功后,但是部署失败未处理的机器记录 + """ + + bk_biz_id = models.IntegerField(default=0, help_text=_("业务ID")) + bk_host_id = models.PositiveBigIntegerField(primary_key=True, default=0, help_text=_("主机ID")) + bk_cloud_id = models.IntegerField(default=0, help_text=_("主机云区域")) + ip = models.CharField(max_length=LEN_MIDDLE, help_text=_("主机IP")) + flow = models.ForeignKey(Flow, on_delete=models.CASCADE, help_text=_("关联任务")) + ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, help_text=_("关联单据")) diff --git a/dbm-ui/backend/db_dirty/serializers.py b/dbm-ui/backend/db_dirty/serializers.py new file mode 100644 index 0000000000..276c450494 --- /dev/null +++ b/dbm-ui/backend/db_dirty/serializers.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.db.models import Q +from django.utils.translation import ugettext_lazy as _ +from rest_framework import serializers + +from backend import env +from backend.configuration.constants import DBType +from backend.constants import INT_MAX +from backend.db_dirty.mock import DIRTY_MACHINE_LIST +from backend.db_meta.enums import ClusterType, InstanceRole, MachineType +from backend.db_meta.models import Spec +from backend.db_services.dbresource.constants import ResourceOperation +from backend.db_services.dbresource.mock import RECOMMEND_SPEC_DATA, RESOURCE_LIST_DATA, SPEC_DATA +from backend.db_services.ipchooser.serializers.base import QueryHostsBaseSer +from backend.ticket.constants import TicketStatus, TicketType + + +class QueryDirtyMachineSerializer(serializers.Serializer): + ip_list = serializers.CharField(help_text=_("过滤的主机IP列表,以逗号分隔"), required=False) + ticket_id = serializers.IntegerField(help_text=_("过滤的单据ID"), required=False) + task_id = serializers.CharField(help_text=_("过滤的任务ID"), required=False) + ticket_type = serializers.ChoiceField(help_text=_("过滤的单据类型"), choices=TicketType.get_choices(), required=False) + operator = serializers.CharField(help_text=_("操作人"), required=False) + + limit = serializers.IntegerField(help_text=_("分页限制"), required=False, default=10) + offset = serializers.IntegerField(help_text=_("分页起始"), required=False, default=0) + + def validate(self, attrs): + if "ip_list" in attrs: + attrs["ip_list"] = attrs["ip_list"].split(",") + + return attrs + + +class QueryDirtyMachineResponseSerializer(serializers.Serializer): + class Meta: + swagger_schema_fields = {"example": DIRTY_MACHINE_LIST} + + +class DeleteDirtyMachineSerializer(serializers.Serializer): + bk_host_ids = serializers.ListField(child=serializers.IntegerField(), help_text=_("待转移的主机ID列表")) diff --git a/dbm-ui/backend/db_dirty/urls.py b/dbm-ui/backend/db_dirty/urls.py new file mode 100644 index 0000000000..59ffa385dd --- /dev/null +++ b/dbm-ui/backend/db_dirty/urls.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from rest_framework.routers import DefaultRouter + +from backend.db_dirty.views import DBDirtyMachineViewSet + +routers = DefaultRouter(trailing_slash=True) + +routers.register(r"", DBDirtyMachineViewSet, basename="db_dirty") + +urlpatterns = routers.urls diff --git a/dbm-ui/backend/db_dirty/views.py b/dbm-ui/backend/db_dirty/views.py new file mode 100644 index 0000000000..1566d53893 --- /dev/null +++ b/dbm-ui/backend/db_dirty/views.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from collections import defaultdict + +from django.utils.translation import ugettext_lazy as _ +from django_filters import rest_framework +from rest_framework import status +from rest_framework.decorators import action +from rest_framework.response import Response + +from backend.bk_web import viewsets +from backend.bk_web.pagination import AuditedLimitOffsetPagination +from backend.bk_web.swagger import common_swagger_auto_schema +from backend.components import CCApi +from backend.db_dirty.constants import SWAGGER_TAG +from backend.db_dirty.filters import DirtyMachineFilter +from backend.db_dirty.handlers import DBDirtyMachineHandler +from backend.db_dirty.models import DirtyMachine +from backend.db_dirty.serializers import ( + DeleteDirtyMachineSerializer, + QueryDirtyMachineResponseSerializer, + QueryDirtyMachineSerializer, +) +from backend.db_meta.models import AppCache +from backend.db_services.ipchooser.query.resource import ResourceQueryHelper +from backend.iam_app.handlers.drf_perm import GlobalManageIAMPermission + + +class DBDirtyMachineViewSet(viewsets.SystemViewSet): + pagination_class = None + filter_class = None + + def _get_custom_permissions(self): + return [GlobalManageIAMPermission()] + + @common_swagger_auto_schema( + operation_summary=_("查询污点池列表"), + responses={status.HTTP_200_OK: QueryDirtyMachineResponseSerializer()}, + tags=[SWAGGER_TAG], + ) + @action( + detail=False, + methods=["GET"], + url_path="query_dirty_machines", + serializer_class=QueryDirtyMachineSerializer, + pagination_class=AuditedLimitOffsetPagination, + filter_class=DirtyMachineFilter, + filter_backends=(rest_framework.DjangoFilterBackend,), + queryset=DirtyMachine.objects.all(), + ) + def query_operation_list(self, request): + dirty_machines = self.filter_queryset(self.get_queryset()) + page_dirty_machines = self.paginate_queryset(dirty_machines) + + # 提前缓存云区域和业务信息 + bk_biz_ids = [dirty_machine.bk_biz_id for dirty_machine in page_dirty_machines] + for_biz_infos = AppCache.batch_get_app_attr(bk_biz_ids=bk_biz_ids, attr_name="bk_biz_name") + cloud_info = ResourceQueryHelper.search_cc_cloud(get_cache=True) + + # 获取污点池列表 + page_dirty_machine_list = [ + { + "ip": dirty.ip, + "bk_host_id": dirty.bk_host_id, + "bk_cloud_name": cloud_info[str(dirty.bk_cloud_id)]["bk_cloud_name"], + "bk_cloud_id": dirty.bk_cloud_id, + "bk_biz_name": for_biz_infos[int(dirty.bk_biz_id)], + "bk_biz_id": dirty.bk_biz_id, + "ticket_type": dirty.ticket.ticket_type, + "ticket_id": dirty.ticket.id, + "task_id": dirty.flow.flow_obj_id, + } + for dirty in page_dirty_machines + ] + return self.paginator.get_paginated_response(data=page_dirty_machine_list) + + @common_swagger_auto_schema( + operation_summary=_("将污点池主机转移至待回收模块"), + request_body=DeleteDirtyMachineSerializer(), + tags=[SWAGGER_TAG], + ) + @action( + detail=False, + methods=["POST"], + url_path="transfer_dirty_machines", + serializer_class=DeleteDirtyMachineSerializer, + ) + def transfer_dirty_machines(self, request): + bk_host_ids = self.params_validate(self.get_serializer_class())["bk_host_ids"] + DBDirtyMachineHandler.transfer_dirty_machines(bk_host_ids) + return Response() diff --git a/dbm-ui/backend/db_meta/admin.py b/dbm-ui/backend/db_meta/admin.py index 20fdb8074b..2645482ea5 100644 --- a/dbm-ui/backend/db_meta/admin.py +++ b/dbm-ui/backend/db_meta/admin.py @@ -135,3 +135,17 @@ class StorageInstanceTupleAdmin(admin.ModelAdmin): "receiver", ) search_fields = ("ejector__machine__ip", "receiver__machine__ip") + + +@admin.register(models.spec.Spec) +class SpecAdmin(admin.ModelAdmin): + list_display = ( + "spec_name", + "spec_cluster_type", + "spec_machine_type", + "cpu", + "mem", + "device_class", + "storage_spec", + ) + search_fields = ("spec_name", "spec_cluster_type", "spec_machine_type") diff --git a/dbm-ui/backend/db_meta/models/spec.py b/dbm-ui/backend/db_meta/models/spec.py index ee0e61f2b9..8a874c7434 100644 --- a/dbm-ui/backend/db_meta/models/spec.py +++ b/dbm-ui/backend/db_meta/models/spec.py @@ -16,6 +16,7 @@ from backend.bk_web.models import AuditedModel from ...constants import INT_MAX +from ...db_services.ipchooser.constants import DEVICE_CLASS from ...ticket.constants import AffinityEnum from ..enums import ClusterType, MachineType @@ -81,7 +82,8 @@ def get_apply_params_detail(self, group_mark, count, bk_cloud_id, affinity=Affin "storage_spec": [ { "mount_point": storage_spec["mount_point"], - "disk_type": storage_spec["type"], + # 如果是all,则需要传空 + "disk_type": "" if storage_spec["type"] == "ALL" else storage_spec["type"], "min": storage_spec["size"], "max": INT_MAX, } diff --git a/dbm-ui/backend/db_proxy/migrations/0002_auto_20230711_1147.py b/dbm-ui/backend/db_proxy/migrations/0002_auto_20230711_1147.py new file mode 100644 index 0000000000..145e04574a --- /dev/null +++ b/dbm-ui/backend/db_proxy/migrations/0002_auto_20230711_1147.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.19 on 2023-07-11 03:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("db_proxy", "0001_initial"), + ] + + operations = [ + migrations.AlterUniqueTogether( + name="clusterextension", + unique_together=set(), + ), + migrations.AlterIndexTogether( + name="clusterextension", + index_together={("bk_biz_id", "db_type", "cluster_name", "service_type")}, + ), + ] diff --git a/dbm-ui/backend/db_services/dbresource/serializers.py b/dbm-ui/backend/db_services/dbresource/serializers.py index 124b82a63f..8e00680515 100644 --- a/dbm-ui/backend/db_services/dbresource/serializers.py +++ b/dbm-ui/backend/db_services/dbresource/serializers.py @@ -151,8 +151,10 @@ class QueryOperationListSerializer(serializers.Serializer): ) ticket_ids = serializers.CharField(help_text=_("过滤的单据ID列表"), required=False) + ticket_types = serializers.CharField(help_text=_("过滤的单据类型列表"), required=False) task_ids = serializers.CharField(help_text=_("过滤的任务ID列表"), required=False) ip_list = serializers.CharField(help_text=_("过滤IP列表"), required=False) + orderby = serializers.CharField(help_text=_("排序模式"), required=False) operator = serializers.CharField(help_text=_("操作者"), required=False) begin_time = serializers.CharField(help_text=_("操作开始时间"), required=False) @@ -166,6 +168,9 @@ def validate(self, attrs): if attrs.get("ticket_ids"): attrs["bill_ids"] = attrs.pop("ticket_ids").split(",") + if attrs.get("ticket_types"): + attrs["bill_types"] = attrs.pop("ticket_types").split(",") + if attrs.get("task_ids"): attrs["task_ids"] = attrs["task_ids"].split(",") diff --git a/dbm-ui/backend/db_services/dbresource/views/resource.py b/dbm-ui/backend/db_services/dbresource/views/resource.py index 5978e8b567..6236ce0662 100644 --- a/dbm-ui/backend/db_services/dbresource/views/resource.py +++ b/dbm-ui/backend/db_services/dbresource/views/resource.py @@ -25,7 +25,7 @@ from backend.bk_web.swagger import common_swagger_auto_schema from backend.components import CCApi from backend.components.dbresource.client import DBResourceApi -from backend.configuration.constants import RESOURCE_TOPO +from backend.configuration.constants import MANAGE_TOPO from backend.configuration.models import SystemSettings from backend.db_meta.models import AppCache from backend.db_services.dbresource.constants import ( @@ -288,9 +288,12 @@ def resource_delete(self, request): resp = DBResourceApi.resource_delete(params=validated_data) # 将在资源池模块的机器移到空闲机,若机器处于其他模块,则忽略 move_idle_hosts: List[int] = [] - resource_topo = SystemSettings.get_setting_value(key=RESOURCE_TOPO) + resource_topo = SystemSettings.get_setting_value(key=MANAGE_TOPO) for topo in CCApi.find_host_biz_relations({"bk_host_id": validated_data["bk_host_ids"]}): - if topo["bk_set_id"] == resource_topo["set_id"] and topo["bk_module_id"] == resource_topo["module_id"]: + if ( + topo["bk_set_id"] == resource_topo["set_id"] + and topo["bk_module_id"] == resource_topo["resource_module_id"] + ): move_idle_hosts.append(topo["bk_host_id"]) if move_idle_hosts: @@ -347,6 +350,7 @@ def query_operation_list(self, request): op["update_time"] = remove_timezone(op["update_time"]) op["ticket_id"] = int(op.pop("bill_id") or 0) + op["ticket_type"] = op.pop("bill_type", "") op["bk_biz_id"] = getattr(task_id__task.get(op["task_id"]), "bk_biz_id", env.DBA_APP_BK_BIZ_ID) task_status = getattr(task_id__task.get(op["task_id"]), "status", "") op["status"] = BAMBOO_STATE__TICKET_STATE_MAP.get(task_status, TicketStatus.RUNNING) diff --git a/dbm-ui/backend/db_services/ipchooser/constants.py b/dbm-ui/backend/db_services/ipchooser/constants.py index dd0bd7c662..3e7982200a 100644 --- a/dbm-ui/backend/db_services/ipchooser/constants.py +++ b/dbm-ui/backend/db_services/ipchooser/constants.py @@ -114,6 +114,8 @@ def _get_member__alias_map(cls) -> Dict[Enum, str]: # DBM管理的CC集群名 DB_MANAGE_SET = "db.manage.set" +RESOURCE_MODULE = "resource.idle.module" +DIRTY_MODULE = "dirty.module" # 磁盘类型,目前固定写死 DEVICE_CLASS = ["SSD", "HDD", "ALL"] diff --git a/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py b/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py index 86823b9030..24c0b65cd7 100644 --- a/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py +++ b/dbm-ui/backend/db_services/redis/resources/redis_cluster/query.py @@ -250,7 +250,7 @@ def _to_cluster_list(cluster, cluster_entry_map: Dict[int, Dict[str, str]]) -> D else: spec = Spec.objects.get(spec_id=spec_id) cluster_spec = model_to_dict(spec) - cluster_capacity = (spec.capacity * machine_pair_cnt,) + cluster_capacity = spec.capacity * machine_pair_cnt return { "id": cluster.id, diff --git a/dbm-ui/backend/db_services/taskflow/views/flow.py b/dbm-ui/backend/db_services/taskflow/views/flow.py index 6d131330c2..7f1089b52b 100644 --- a/dbm-ui/backend/db_services/taskflow/views/flow.py +++ b/dbm-ui/backend/db_services/taskflow/views/flow.py @@ -26,6 +26,8 @@ from backend.flow.engine.bamboo.engine import BambooEngine from backend.flow.models import FlowTree from backend.iam_app.handlers.drf_perm import TaskFlowIAMPermission +from backend.ticket.models import Flow +from backend.utils.basic import get_target_items_from_details SWAGGER_TAG = "taskflow" @@ -70,8 +72,16 @@ def list(self, requests, *args, **kwargs): ) def retrieve(self, requests, *args, **kwargs): root_id = kwargs["root_id"] - flow_info = super().retrieve(requests, *args, **kwargs) tree_states = BambooEngine(root_id=root_id).get_pipeline_tree_states() + + flow_info = super().retrieve(requests, *args, **kwargs) + ticket_flow = Flow.objects.get(flow_obj_id=root_id) + # 查询当前flow涉及的主机和业务信息 + bk_host_ids = get_target_items_from_details( + obj=ticket_flow.details, match_keys=["host_id", "bk_host_id", "bk_host_ids"] + ) + flow_info.data.update(bk_host_ids=bk_host_ids, bk_biz_id=ticket_flow.ticket.bk_biz_id) + return Response({"flow_info": flow_info.data, **tree_states}) @common_swagger_auto_schema( diff --git a/dbm-ui/backend/dbm_init/services.py b/dbm-ui/backend/dbm_init/services.py index 29f96d216c..001bcd536e 100644 --- a/dbm-ui/backend/dbm_init/services.py +++ b/dbm-ui/backend/dbm_init/services.py @@ -21,7 +21,7 @@ from backend import env from backend.components import BKLogApi, BKMonitorV3Api, CCApi, ItsmApi from backend.components.constants import SSL_KEY -from backend.configuration.constants import BKM_DBM_REPORT, DBM_REPORT_INITIAL_VALUE, DBM_SSL, RESOURCE_TOPO, DBType +from backend.configuration.constants import BKM_DBM_REPORT, DBM_REPORT_INITIAL_VALUE, DBM_SSL, MANAGE_TOPO, DBType from backend.configuration.models.system import SystemSettings, SystemSettingsEnum from backend.core.storages.constants import FileCredentialType, StorageType from backend.core.storages.file_source import BkJobFileSourceManager @@ -29,7 +29,7 @@ from backend.db_meta.models import AppMonitorTopo from backend.db_monitor.constants import TPLS_ALARM_DIR, TPLS_COLLECT_DIR from backend.db_monitor.models import AlertRule, CollectInstance, CollectTemplate, NoticeGroup, RuleTemplate -from backend.db_services.ipchooser.constants import DB_MANAGE_SET +from backend.db_services.ipchooser.constants import DB_MANAGE_SET, DIRTY_MODULE, RESOURCE_MODULE from backend.dbm_init.constants import CC_APP_ABBR_ATTR, CC_HOST_DBM_ATTR from backend.dbm_init.json_files.format import JsonConfigFormat from backend.exceptions import ApiError, ApiRequestError, ApiResultError @@ -186,25 +186,36 @@ def auto_create_bkcc_service() -> bool: logger.info("init cc topo for monitor discover.") AppMonitorTopo.init_topo() - # 初始化空闲集群的DB空闲模块,用于存放资源池机器 - if not SystemSettings.get_setting_value(key=RESOURCE_TOPO): + # 初始化db的管理集群和相关模块 + if not SystemSettings.get_setting_value(key=MANAGE_TOPO): + # 创建管理集群 manage_set = CCApi.create_set( { "bk_biz_id": env.DBA_APP_BK_BIZ_ID, "data": {"bk_parent_id": env.DBA_APP_BK_BIZ_ID, "bk_set_name": DB_MANAGE_SET}, } ) - resource_module = CCApi.create_module( - { - "bk_biz_id": env.DBA_APP_BK_BIZ_ID, - "bk_set_id": manage_set["bk_set_id"], - "data": {"bk_parent_id": manage_set["bk_set_id"], "bk_module_name": "resource.idle.module"}, - } - ) + # 创建资源池模块和污点池模块 + manage_modules = [RESOURCE_MODULE, DIRTY_MODULE] + module_name__module_info = {} + for module in manage_modules: + module_info = CCApi.create_module( + { + "bk_biz_id": env.DBA_APP_BK_BIZ_ID, + "bk_set_id": manage_set["bk_set_id"], + "data": {"bk_parent_id": manage_set["bk_set_id"], "bk_module_name": module}, + } + ) + module_name__module_info[module] = module_info + # 插入管理集群的配置 SystemSettings.insert_setting_value( - key=RESOURCE_TOPO, + key=MANAGE_TOPO, value_type="dict", - value={"set_id": manage_set["bk_set_id"], "module_id": resource_module["bk_module_id"]}, + value={ + "set_id": manage_set["bk_set_id"], + "resource_module_id": module_name__module_info[RESOURCE_MODULE]["bk_module_id"], + "dirty_module_id": module_name__module_info[DIRTY_MODULE]["bk_module_id"], + }, ) # 初始化主机自定义属性,用于system数据拷贝 diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/common/machine_os_init.py b/dbm-ui/backend/flow/engine/bamboo/scene/common/machine_os_init.py index e0a453c95f..58fedf0c7e 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/common/machine_os_init.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/common/machine_os_init.py @@ -15,7 +15,7 @@ from backend import env from backend.components.dbresource.client import DBResourceApi -from backend.configuration.constants import RESOURCE_TOPO +from backend.configuration.constants import MANAGE_TOPO from backend.configuration.models import SystemSettings from backend.flow.engine.bamboo.scene.common.builder import Builder from backend.flow.plugins.components.collections.common.external_service import ExternalServiceComponent @@ -79,7 +79,7 @@ def machine_init_flow(self): act_name=_("主机转移至资源池空闲模块"), act_component_code=TransferHostServiceComponent.code, kwargs={ - "bk_module_ids": [SystemSettings.get_setting_value(key=RESOURCE_TOPO)["module_id"]], + "bk_module_ids": [SystemSettings.get_setting_value(key=MANAGE_TOPO)["resource_module_id"]], "bk_host_ids": [host["host_id"] for host in ip_list], }, ) diff --git a/dbm-ui/backend/flow/signal/handlers.py b/dbm-ui/backend/flow/signal/handlers.py index 07dd54fedb..40bfc8e901 100644 --- a/dbm-ui/backend/flow/signal/handlers.py +++ b/dbm-ui/backend/flow/signal/handlers.py @@ -15,13 +15,16 @@ from django.utils.translation import ugettext as _ from pipeline.eri.signals import post_set_state -from backend.flow.consts import StateType +from backend.db_dirty.handlers import DBDirtyMachineHandler +from backend.flow.consts import FAILED_STATES, StateType from backend.flow.engine.bamboo.engine import BambooEngine from backend.flow.models import FlowNode, FlowTree +from backend.ticket.builders import BuilderFactory from backend.ticket.constants import BAMBOO_STATE__TICKET_STATE_MAP, FlowCallbackType, FlowType, TicketFlowStatus from backend.ticket.flow_manager.inner import InnerFlow from backend.ticket.flow_manager.manager import TicketFlowManager from backend.ticket.models import Flow, Ticket +from backend.utils.basic import get_target_items_from_details logger = logging.getLogger("flow") @@ -64,6 +67,7 @@ def post_set_state_signal_handler(sender, node_id, to_state, version, root_id, * tree.updated_at = now tree.status = target_tree_status tree.save() + handle_dirty_machine(tree.uid, root_id, origin_tree_status, target_tree_status) callback_ticket(tree.uid, root_id) except FlowTree.DoesNotExist: logger.debug(_("【状态信号捕获】未查找到FlowTree root_id={}").format(root_id)) @@ -92,3 +96,33 @@ def callback_ticket(ticket_id, root_id): if current_flow and current_flow.flow_obj_id == root_id: manager = TicketFlowManager(ticket=ticket) manager.run_next_flow() + + +def handle_dirty_machine(ticket_id, root_id, origin_tree_status, target_tree_status): + """处理执行失败/重试成功涉及的污点池机器""" + if (origin_tree_status not in FAILED_STATES) and (target_tree_status not in FAILED_STATES): + return + + try: + ticket = Ticket.objects.get(id=ticket_id) + flow = Flow.objects.get(flow_obj_id=root_id) + # 如果不是部署类单据,则无需处理 + if ticket.ticket_type not in BuilderFactory.apply_ticket_type: + return + except (Ticket.DoesNotExist, Flow.DoesNotExist, ValueError): + return + + # 如果初始状态是失败,则证明是重试,将机器从污点池中移除 + bk_host_ids = get_target_items_from_details( + obj=ticket.details, match_keys=["host_id", "bk_host_id", "bk_host_ids"] + ) + if origin_tree_status in FAILED_STATES: + logger.info(_("主机列表:{} 将从污点池挪出").format(bk_host_ids)) + DBDirtyMachineHandler.remove_dirty_machines(bk_host_ids) + + # 如果是目标状态失败,则证明是执行失败,将机器加入污点池 + if target_tree_status in FAILED_STATES: + logger.info(_("单据-{}:任务-{}执行失败,主机列表:{}将挪到污点池").format(ticket_id, root_id, bk_host_ids)) + DBDirtyMachineHandler.insert_dirty_machines( + bk_biz_id=ticket.bk_biz_id, bk_host_ids=bk_host_ids, ticket=ticket, flow=flow + ) diff --git a/dbm-ui/backend/ticket/builders/__init__.py b/dbm-ui/backend/ticket/builders/__init__.py index 445b813cf1..b060946b47 100644 --- a/dbm-ui/backend/ticket/builders/__init__.py +++ b/dbm-ui/backend/ticket/builders/__init__.py @@ -353,7 +353,7 @@ def init_ticket_flows(self): # 如果使用资源池,则在最后需要进行资源交付 if self.need_resource_pool: - flow_type = FlowType.RESOURCE_DELIVERY if self.resource_apply_builder else FlowType.RESOURCE_BATCH_APPLY + flow_type = FlowType.RESOURCE_DELIVERY if self.resource_apply_builder else FlowType.RESOURCE_BATCH_DELIVERY flows.append(Flow(ticket=self.ticket, flow_type=flow_type)) Flow.objects.bulk_create(flows) @@ -365,14 +365,38 @@ def patch_ticket_detail(self): class BuilderFactory: + # 单据的注册器类集合 registry = {} + # 部署类单据集合 + apply_ticket_type = [] + # 单据与集群状态的映射 + ticket_type__cluster_phase = {} + # 单据和集群类型的映射 + ticket_type__cluster_type = {} @classmethod - def register(cls, ticket_type: str) -> Callable: + def register(cls, ticket_type: str, **kwargs) -> Callable: + """ + 将单据构造类注册到注册器中 + @param ticket_type: 单据类型 + @param kwargs: 单据注册的额外信息,主要是将单据归为不同的集合中,目前有这几种类型 + 1. is_apply: bool ---- 表示单据是否是部署类单据(类似集群的部署,扩容,替换等) + 2. phase: ClusterPhase ---- 表示单据与集群状态的映射 + 3. cluster_type: ClusterType ---- 表示单据与集群类型的映射 + """ + def inner_wrapper(wrapped_class: TicketFlowBuilder) -> TicketFlowBuilder: if ticket_type in cls.registry: logger.warning(f"Builder [{ticket_type}] already exists. Will replace it") cls.registry[ticket_type] = wrapped_class + + if kwargs.get("is_apply") and kwargs.get("is_apply") not in cls.apply_ticket_type: + cls.apply_ticket_type.append(ticket_type) + if kwargs.get("phase"): + cls.ticket_type__cluster_phase[ticket_type] = kwargs["phase"] + if kwargs.get("cluster_type"): + cls.ticket_type__cluster_type[ticket_type] = kwargs["cluster_type"] + return wrapped_class return inner_wrapper diff --git a/dbm-ui/backend/ticket/builders/common/base.py b/dbm-ui/backend/ticket/builders/common/base.py index 024326e7c9..0f4b2a1a9e 100644 --- a/dbm-ui/backend/ticket/builders/common/base.py +++ b/dbm-ui/backend/ticket/builders/common/base.py @@ -23,7 +23,8 @@ from backend.db_services.mysql.cluster.handlers import ClusterServiceHandler from backend.db_services.mysql.remote_service.handlers import RemoteServiceHandler from backend.ticket import builders -from backend.ticket.constants import TICKET_TYPE__CLUSTER_TYPE_MAP, TicketType +from backend.ticket.builders import BuilderFactory +from backend.ticket.constants import TicketType def fetch_cluster_ids(details: Dict[str, Any]) -> List[int]: @@ -180,7 +181,7 @@ def validate_db_name(cls, db_name: str) -> Tuple[bool, str]: @classmethod def validate_duplicate_cluster_name(cls, bk_biz_id, ticket_type, cluster_name): - cluster_type = TICKET_TYPE__CLUSTER_TYPE_MAP.get(ticket_type, ticket_type) + cluster_type = BuilderFactory.ticket_type__cluster_type.get(ticket_type, ticket_type) if Cluster.objects.filter(bk_biz_id=bk_biz_id, cluster_type=cluster_type, name=cluster_name).exists(): raise serializers.ValidationError( _("业务{}下已经存在同类型: {}, 同名: {} 集群,请重新命名").format(bk_biz_id, cluster_type, cluster_name) diff --git a/dbm-ui/backend/ticket/builders/common/bigdata.py b/dbm-ui/backend/ticket/builders/common/bigdata.py index c017b43458..257c105076 100644 --- a/dbm-ui/backend/ticket/builders/common/bigdata.py +++ b/dbm-ui/backend/ticket/builders/common/bigdata.py @@ -22,7 +22,7 @@ from backend.db_meta.models.machine import Machine from backend.db_services.dbbase.constants import IpSource from backend.ticket import builders -from backend.ticket.builders import TicketFlowBuilder +from backend.ticket.builders import BuilderFactory, TicketFlowBuilder from backend.ticket.builders.common.base import ( BigDataTicketFlowBuilderPatchMixin, CommonValidate, @@ -30,7 +30,6 @@ remove_useless_spec, ) from backend.ticket.builders.common.constants import BigDataRole -from backend.ticket.constants import TICKET_TYPE__CLUSTER_PHASE_MAP, TICKET_TYPE__CLUSTER_TYPE_MAP class BigDataDetailsSerializer(serializers.Serializer): @@ -75,7 +74,7 @@ def validate_cluster_id(self, value): ticket_type = self.context["ticket_type"] cluster = Cluster.objects.get(id=value) - ticket_cluster_phase = TICKET_TYPE__CLUSTER_PHASE_MAP.get(ticket_type) + ticket_cluster_phase = BuilderFactory.ticket_type__cluster_phase.get(ticket_type) if not ClusterPhase.cluster_status_transfer_valid(cluster.phase, ticket_cluster_phase): raise ValidationError( _("集群{}状态转移不合法:{}--->{} is invalid").format(cluster.name, cluster.phase, ticket_cluster_phase) diff --git a/dbm-ui/backend/ticket/builders/es/es_apply.py b/dbm-ui/backend/ticket/builders/es/es_apply.py index afa0d8ab80..f73c8d2aac 100644 --- a/dbm-ui/backend/ticket/builders/es/es_apply.py +++ b/dbm-ui/backend/ticket/builders/es/es_apply.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from backend.db_meta.enums import ClusterType from backend.db_services.dbbase.constants import ES_DEFAULT_PORT, IpSource from backend.flow.consts import ES_DEFAULT_INSTANCE_NUM from backend.flow.engine.controller.es import EsController @@ -131,7 +132,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.ES_APPLY) +@builders.BuilderFactory.register(TicketType.ES_APPLY, is_apply=True, cluster_type=ClusterType.Es) class EsApplyFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsApplyDetailSerializer inner_flow_builder = EsApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/es/es_destroy.py b/dbm-ui/backend/ticket/builders/es/es_destroy.py index 3863fa4736..75ce17fe71 100644 --- a/dbm-ui/backend/ticket/builders/es/es_destroy.py +++ b/dbm-ui/backend/ticket/builders/es/es_destroy.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.es import EsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseEsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class EsDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = EsController.es_destroy_scene -@builders.BuilderFactory.register(TicketType.ES_DESTROY) +@builders.BuilderFactory.register(TicketType.ES_DESTROY, phase=ClusterPhase.DESTROY) class EsDestroyFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsDestroyDetailSerializer inner_flow_builder = EsDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/es/es_disable.py b/dbm-ui/backend/ticket/builders/es/es_disable.py index ff927d9ca9..7422cc6a9f 100644 --- a/dbm-ui/backend/ticket/builders/es/es_disable.py +++ b/dbm-ui/backend/ticket/builders/es/es_disable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.es import EsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseEsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class EsDisableFlowParamBuilder(builders.FlowParamBuilder): controller = EsController.es_disable_scene -@builders.BuilderFactory.register(TicketType.ES_DISABLE) +@builders.BuilderFactory.register(TicketType.ES_DISABLE, phase=ClusterPhase.OFFLINE) class EsDisableFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsDisableDetailSerializer inner_flow_builder = EsDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/es/es_enable.py b/dbm-ui/backend/ticket/builders/es/es_enable.py index 3bb50ce399..1abb0a7453 100644 --- a/dbm-ui/backend/ticket/builders/es/es_enable.py +++ b/dbm-ui/backend/ticket/builders/es/es_enable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.es import EsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseEsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class EsEnableFlowParamBuilder(builders.FlowParamBuilder): controller = EsController.es_enable_scene -@builders.BuilderFactory.register(TicketType.ES_ENABLE) +@builders.BuilderFactory.register(TicketType.ES_ENABLE, phase=ClusterPhase.ONLINE) class EsEnableFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsEnableDetailSerializer inner_flow_builder = EsEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/es/es_replace.py b/dbm-ui/backend/ticket/builders/es/es_replace.py index 01e11dd765..b9f03beedd 100644 --- a/dbm-ui/backend/ticket/builders/es/es_replace.py +++ b/dbm-ui/backend/ticket/builders/es/es_replace.py @@ -46,7 +46,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.ES_REPLACE) +@builders.BuilderFactory.register(TicketType.ES_REPLACE, is_apply=True) class EsReplaceFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsReplaceDetailSerializer inner_flow_builder = EsReplaceFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/es/es_scale_up.py b/dbm-ui/backend/ticket/builders/es/es_scale_up.py index de35e92d6c..e7bce4b43f 100644 --- a/dbm-ui/backend/ticket/builders/es/es_scale_up.py +++ b/dbm-ui/backend/ticket/builders/es/es_scale_up.py @@ -97,7 +97,7 @@ def format_ticket_data(self): super().format_ticket_data() -@builders.BuilderFactory.register(TicketType.ES_SCALE_UP) +@builders.BuilderFactory.register(TicketType.ES_SCALE_UP, is_apply=True) class EsScaleUpFlowBuilder(BaseEsTicketFlowBuilder): serializer = EsScaleUpDetailSerializer inner_flow_builder = EsScaleUpFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_apply.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_apply.py index c0ad664daf..f1391b9a0f 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_apply.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_apply.py @@ -12,6 +12,7 @@ from django.utils.translation import ugettext as _ from rest_framework import serializers +from backend.db_meta.enums import ClusterType from backend.db_services.dbbase.constants import HDFS_DEFAULT_HTTP_PORT, HDFS_DEFAULT_RPC_PORT, IpSource from backend.flow.engine.controller.hdfs import HdfsController from backend.ticket import builders @@ -136,7 +137,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.HDFS_APPLY) +@builders.BuilderFactory.register(TicketType.HDFS_APPLY, is_apply=True, cluster_type=ClusterType.Hdfs) class HdfsApplyFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsApplyDetailSerializer inner_flow_builder = HdfsApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_destroy.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_destroy.py index c57068f384..359cfb7903 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_destroy.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_destroy.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.hdfs import HdfsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseHdfsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class HdfsDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = HdfsController.hdfs_destroy_scene -@builders.BuilderFactory.register(TicketType.HDFS_DESTROY) +@builders.BuilderFactory.register(TicketType.HDFS_DESTROY, phase=ClusterPhase.DESTROY) class HdfsDestroyFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsDestroyDetailSerializer inner_flow_builder = HdfsDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_disable.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_disable.py index 1a4cf0e0ca..ece1fa6fbf 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_disable.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_disable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.hdfs import HdfsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseHdfsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class HdfsDisableFlowParamBuilder(builders.FlowParamBuilder): controller = HdfsController.hdfs_disable_scene -@builders.BuilderFactory.register(TicketType.HDFS_DISABLE) +@builders.BuilderFactory.register(TicketType.HDFS_DISABLE, phase=ClusterPhase.OFFLINE) class HdfsDisableFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsDisableDetailSerializer inner_flow_builder = HdfsDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_enable.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_enable.py index 350efd8f1b..6b1c624186 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_enable.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_enable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.hdfs import HdfsController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseHdfsTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -29,7 +30,7 @@ class HdfsEnableFlowParamBuilder(builders.FlowParamBuilder): controller = HdfsController.hdfs_enable_scene -@builders.BuilderFactory.register(TicketType.HDFS_ENABLE) +@builders.BuilderFactory.register(TicketType.HDFS_ENABLE, phase=ClusterPhase.ONLINE) class HdfsEnableFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsEnableDetailSerializer inner_flow_builder = HdfsEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_replace.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_replace.py index e1a29c7d74..22e898e9fd 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_replace.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_replace.py @@ -50,7 +50,7 @@ class HdfsResourceParamBuilder(BigDataReplaceResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.HDFS_REPLACE) +@builders.BuilderFactory.register(TicketType.HDFS_REPLACE, is_apply=True) class HdfsReplaceFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsReplaceDetailSerializer inner_flow_builder = HdfsReplaceFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/hdfs/hdfs_scale_up.py b/dbm-ui/backend/ticket/builders/hdfs/hdfs_scale_up.py index 3eb5a6adaf..0c4d8f7775 100644 --- a/dbm-ui/backend/ticket/builders/hdfs/hdfs_scale_up.py +++ b/dbm-ui/backend/ticket/builders/hdfs/hdfs_scale_up.py @@ -57,7 +57,7 @@ class HdfsScaleUpResourceParamBuilder(BigDataScaleUpResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.HDFS_SCALE_UP) +@builders.BuilderFactory.register(TicketType.HDFS_SCALE_UP, is_apply=True) class HdfsScaleUpFlowBuilder(BaseHdfsTicketFlowBuilder): serializer = HdfsScaleUpDetailSerializer inner_flow_builder = HdfsScaleUpFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/influxdb/influxdb_apply.py b/dbm-ui/backend/ticket/builders/influxdb/influxdb_apply.py index 01f2d1aef6..d097443815 100644 --- a/dbm-ui/backend/ticket/builders/influxdb/influxdb_apply.py +++ b/dbm-ui/backend/ticket/builders/influxdb/influxdb_apply.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ from rest_framework import serializers +from backend.db_meta.enums import ClusterType from backend.db_meta.models import Group from backend.db_services.dbbase.constants import IpSource from backend.flow.engine.controller.influxdb import InfluxdbController @@ -68,7 +69,7 @@ class InfluxApplyDBResourceParamBuilder(builders.ResourceApplyParamBuilder): pass -@builders.BuilderFactory.register(TicketType.INFLUXDB_APPLY) +@builders.BuilderFactory.register(TicketType.INFLUXDB_APPLY, is_apply=True, cluster_type=ClusterType.Influxdb) class InfluxDBApplyFlowBuilder(BaseInfluxDBTicketFlowBuilder): serializer = InfluxDBApplyDetailSerializer inner_flow_builder = InfluxDBApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/influxdb/influxdb_destroy.py b/dbm-ui/backend/ticket/builders/influxdb/influxdb_destroy.py index de5c5e223b..f9fa3495cc 100644 --- a/dbm-ui/backend/ticket/builders/influxdb/influxdb_destroy.py +++ b/dbm-ui/backend/ticket/builders/influxdb/influxdb_destroy.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.influxdb import InfluxdbController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseInfluxDBOpsDetailSerializer, BaseInfluxDBTicketFlowBuilder @@ -30,7 +31,7 @@ class InfluxDBDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = InfluxdbController.influxdb_destroy_scene -@builders.BuilderFactory.register(TicketType.INFLUXDB_DESTROY) +@builders.BuilderFactory.register(TicketType.INFLUXDB_DESTROY, phase=ClusterPhase.DESTROY) class InfluxDBDestroyFlowBuilder(BaseInfluxDBTicketFlowBuilder): serializer = InfluxDBDestroyDetailSerializer inner_flow_builder = InfluxDBDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/influxdb/influxdb_disable.py b/dbm-ui/backend/ticket/builders/influxdb/influxdb_disable.py index 0fdf054ea4..b68025ff08 100644 --- a/dbm-ui/backend/ticket/builders/influxdb/influxdb_disable.py +++ b/dbm-ui/backend/ticket/builders/influxdb/influxdb_disable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.influxdb import InfluxdbController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseInfluxDBOpsDetailSerializer, BaseInfluxDBTicketFlowBuilder @@ -30,7 +31,7 @@ class InfluxDBDisableFlowParamBuilder(builders.FlowParamBuilder): controller = InfluxdbController.influxdb_disable_scene -@builders.BuilderFactory.register(TicketType.INFLUXDB_DISABLE) +@builders.BuilderFactory.register(TicketType.INFLUXDB_DISABLE, phase=ClusterPhase.OFFLINE) class InfluxDBDisableFlowBuilder(BaseInfluxDBTicketFlowBuilder): serializer = InfluxDBDisableDetailSerializer inner_flow_builder = InfluxDBDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/influxdb/influxdb_enable.py b/dbm-ui/backend/ticket/builders/influxdb/influxdb_enable.py index f5fa4a69c6..ddae43e251 100644 --- a/dbm-ui/backend/ticket/builders/influxdb/influxdb_enable.py +++ b/dbm-ui/backend/ticket/builders/influxdb/influxdb_enable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.influxdb import InfluxdbController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseInfluxDBOpsDetailSerializer, BaseInfluxDBTicketFlowBuilder @@ -30,7 +31,7 @@ class InfluxDBEnableFlowParamBuilder(builders.FlowParamBuilder): controller = InfluxdbController.influxdb_enable_scene -@builders.BuilderFactory.register(TicketType.INFLUXDB_ENABLE) +@builders.BuilderFactory.register(TicketType.INFLUXDB_ENABLE, phase=ClusterPhase.ONLINE) class InfluxDBEnableFlowBuilder(BaseInfluxDBTicketFlowBuilder): serializer = InfluxDBEnableDetailSerializer inner_flow_builder = InfluxDBEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/influxdb/influxdb_replace.py b/dbm-ui/backend/ticket/builders/influxdb/influxdb_replace.py index 1c6f790a03..898c3e9c18 100644 --- a/dbm-ui/backend/ticket/builders/influxdb/influxdb_replace.py +++ b/dbm-ui/backend/ticket/builders/influxdb/influxdb_replace.py @@ -39,7 +39,7 @@ def format(self): self.ticket_data["bk_cloud_id"] = self.ticket_data["old_nodes"]["influxdb"][0]["bk_cloud_id"] -@builders.BuilderFactory.register(TicketType.INFLUXDB_REPLACE) +@builders.BuilderFactory.register(TicketType.INFLUXDB_REPLACE, is_apply=True) class InfluxDBReplaceFlowBuilder(BaseInfluxDBTicketFlowBuilder): serializer = InfluxDBReplaceDetailSerializer inner_flow_builder = InfluxDBReplaceFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_apply.py b/dbm-ui/backend/ticket/builders/kafka/kafka_apply.py index dd0a6e7a9f..ad1fc7643a 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_apply.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_apply.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from backend.db_meta.enums import ClusterType from backend.db_services.dbbase.constants import KAFKA_DEFAULT_PORT, IpSource from backend.flow.engine.controller.kafka import KafkaController from backend.ticket import builders @@ -126,7 +127,7 @@ class KafkaApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): pass -@builders.BuilderFactory.register(TicketType.KAFKA_APPLY) +@builders.BuilderFactory.register(TicketType.KAFKA_APPLY, is_apply=True, cluster_type=ClusterType.Kafka) class KafkaApplyFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaApplyDetailSerializer inner_flow_builder = KafkaApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_destroy.py b/dbm-ui/backend/ticket/builders/kafka/kafka_destroy.py index af867af64c..35e80e99c3 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_destroy.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_destroy.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.kafka import KafkaController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseKafkaTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class KafkaDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = KafkaController.kafka_destroy_scene -@builders.BuilderFactory.register(TicketType.KAFKA_DESTROY) +@builders.BuilderFactory.register(TicketType.KAFKA_DESTROY, phase=ClusterPhase.DESTROY) class KafkaDestroyFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaDestroyDetailSerializer inner_flow_builder = KafkaDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_disable.py b/dbm-ui/backend/ticket/builders/kafka/kafka_disable.py index 4a23909c75..27a6a183da 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_disable.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_disable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.kafka import KafkaController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseKafkaTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class KafkaDisableFlowParamBuilder(builders.FlowParamBuilder): controller = KafkaController.kafka_disable_scene -@builders.BuilderFactory.register(TicketType.KAFKA_DISABLE) +@builders.BuilderFactory.register(TicketType.KAFKA_DISABLE, phase=ClusterPhase.OFFLINE) class KafkaDisableFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaDisableDetailSerializer inner_flow_builder = KafkaDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_enable.py b/dbm-ui/backend/ticket/builders/kafka/kafka_enable.py index f3b775f8d6..6dc57063c8 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_enable.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_enable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.kafka import KafkaController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BaseKafkaTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class KafkaEnableFlowParamBuilder(builders.FlowParamBuilder): controller = KafkaController.kafka_enable_scene -@builders.BuilderFactory.register(TicketType.KAFKA_ENABLE) +@builders.BuilderFactory.register(TicketType.KAFKA_ENABLE, phase=ClusterPhase.ONLINE) class KafkaEnableFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaEnableDetailSerializer inner_flow_builder = KafkaEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_replace.py b/dbm-ui/backend/ticket/builders/kafka/kafka_replace.py index b58f0adc2b..be583f2a8d 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_replace.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_replace.py @@ -41,7 +41,7 @@ class KafkaReplaceResourceParamBuilder(BigDataReplaceResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.KAFKA_REPLACE) +@builders.BuilderFactory.register(TicketType.KAFKA_REPLACE, is_apply=True) class KafkaReplaceFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaReplaceDetailSerializer inner_flow_builder = KafkaReplaceFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/kafka/kafka_scale_up.py b/dbm-ui/backend/ticket/builders/kafka/kafka_scale_up.py index 7af0baacb9..546f14ff2b 100644 --- a/dbm-ui/backend/ticket/builders/kafka/kafka_scale_up.py +++ b/dbm-ui/backend/ticket/builders/kafka/kafka_scale_up.py @@ -58,7 +58,7 @@ class KafkaScaleUpResourceParamBuilder(BigDataScaleUpResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.KAFKA_SCALE_UP) +@builders.BuilderFactory.register(TicketType.KAFKA_SCALE_UP, is_apply=True) class KafkaScaleUpFlowBuilder(BaseKafkaTicketFlowBuilder): serializer = KafkaScaleUpDetailSerializer inner_flow_builder = KafkaScaleUpFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/base.py b/dbm-ui/backend/ticket/builders/mysql/base.py index bee2f4ac5b..3279a7bd5d 100644 --- a/dbm-ui/backend/ticket/builders/mysql/base.py +++ b/dbm-ui/backend/ticket/builders/mysql/base.py @@ -19,14 +19,14 @@ from backend.db_meta.enums import AccessLayer, ClusterDBHAStatusFlags, ClusterType, InstanceInnerRole from backend.db_meta.models.cluster import Cluster, ClusterPhase from backend.ticket import builders -from backend.ticket.builders import TicketFlowBuilder +from backend.ticket.builders import BuilderFactory, TicketFlowBuilder from backend.ticket.builders.common.base import ( CommonValidate, MySQLTicketFlowBuilderPatchMixin, SkipToRepresentationMixin, fetch_cluster_ids, ) -from backend.ticket.constants import TICKET_TYPE__CLUSTER_PHASE_MAP, TicketType +from backend.ticket.constants import TicketType class BaseMySQLTicketFlowBuilder(MySQLTicketFlowBuilderPatchMixin, TicketFlowBuilder): @@ -152,7 +152,7 @@ class MySQLClustersTakeDownDetailsSerializer(SkipToRepresentationMixin, serializ def clusters_status_transfer_valid(cls, cluster_ids: List[int], ticket_type: str): cluster_list = Cluster.objects.filter(id__in=cluster_ids) for cluster in cluster_list: - ticket_cluster_phase = TICKET_TYPE__CLUSTER_PHASE_MAP.get(ticket_type) + ticket_cluster_phase = BuilderFactory.ticket_type__cluster_phase.get(ticket_type) if not ClusterPhase.cluster_status_transfer_valid(cluster.phase, ticket_cluster_phase): raise ValidationError( _("集群{}状态转移不合法:{}--->{} is invalid").format(cluster.name, cluster.phase, ticket_cluster_phase) diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_add_slave.py b/dbm-ui/backend/ticket/builders/mysql/mysql_add_slave.py index 16be013b98..80e91fa3ff 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_add_slave.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_add_slave.py @@ -75,7 +75,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.MYSQL_ADD_SLAVE) +@builders.BuilderFactory.register(TicketType.MYSQL_ADD_SLAVE, is_apply=True) class MysqlAddSlaveFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlAddSlaveDetailSerializer inner_flow_builder = MysqlAddSlaveParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_apply.py b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_apply.py index fa51e6653b..a028bde2fc 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_apply.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_apply.py @@ -119,7 +119,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@BuilderFactory.register(TicketType.MYSQL_HA_APPLY) +@BuilderFactory.register(TicketType.MYSQL_HA_APPLY, is_apply=True, cluster_type=ClusterType.TenDBHA) class MysqlHAApplyFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlHAApplyDetailSerializer inner_flow_builder = MysqlHAApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_destroy.py b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_destroy.py index 00e53ab018..0a05430514 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_destroy.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_destroy.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -27,7 +28,7 @@ class MysqlHADestroyFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_ha_destroy_scene -@builders.BuilderFactory.register(TicketType.MYSQL_HA_DESTROY) +@builders.BuilderFactory.register(TicketType.MYSQL_HA_DESTROY, phase=ClusterPhase.DESTROY) class MysqlHaDestroyFlowBuilder(BaseMySQLTicketFlowBuilder): """Mysql下架流程的构建基类""" diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_disable.py b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_disable.py index 3d181fac21..8c279cd33d 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_disable.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_disable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -27,7 +28,7 @@ class MysqlHADisableFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_ha_disable_scene -@builders.BuilderFactory.register(TicketType.MYSQL_HA_DISABLE) +@builders.BuilderFactory.register(TicketType.MYSQL_HA_DISABLE, phase=ClusterPhase.OFFLINE) class MysqlHaDisableFlowBuilder(BaseMySQLTicketFlowBuilder): """Mysql下架流程的构建基类""" diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_enable.py b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_enable.py index 6d758d8b1e..d99d51115d 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_ha_enable.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_ha_enable.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -27,7 +28,7 @@ class MysqlHAEnableFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_ha_enable_scene -@builders.BuilderFactory.register(TicketType.MYSQL_HA_ENABLE) +@builders.BuilderFactory.register(TicketType.MYSQL_HA_ENABLE, phase=ClusterPhase.ONLINE) class MysqlHaEnableFlowBuilder(BaseMySQLTicketFlowBuilder): """Mysql下架流程的构建基类""" diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_migrate_cluster.py b/dbm-ui/backend/ticket/builders/mysql/mysql_migrate_cluster.py index 92af4d2328..5d0e1554ad 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_migrate_cluster.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_migrate_cluster.py @@ -73,7 +73,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.MYSQL_MIGRATE_CLUSTER) +@builders.BuilderFactory.register(TicketType.MYSQL_MIGRATE_CLUSTER, is_apply=True) class MysqlMigrateClusterFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlMigrateClusterDetailSerializer inner_flow_builder = MysqlMigrateClusterParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_add.py b/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_add.py index 84e3324f21..4e10f9f03d 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_add.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_add.py @@ -72,7 +72,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.MYSQL_PROXY_ADD) +@builders.BuilderFactory.register(TicketType.MYSQL_PROXY_ADD, is_apply=True) class MysqlProxyAddFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlProxyAddDetailSerializer inner_flow_builder = MysqlProxyAddParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_switch.py b/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_switch.py index c3ddeda159..1cf660ac36 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_switch.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_proxy_switch.py @@ -86,7 +86,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.MYSQL_PROXY_SWITCH) +@builders.BuilderFactory.register(TicketType.MYSQL_PROXY_SWITCH, is_apply=True) class MysqlProxySwitchFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlProxySwitchDetailSerializer inner_flow_builder = MysqlProxySwitchParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_restore_slave.py b/dbm-ui/backend/ticket/builders/mysql/mysql_restore_slave.py index 6bf287acaf..78cc4d9ccc 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_restore_slave.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_restore_slave.py @@ -63,7 +63,7 @@ def format_ticket_data(self): info["old_slave_ip"], info["new_slave_ip"] = info["old_slave"]["ip"], info["new_slave"]["ip"] -@builders.BuilderFactory.register(TicketType.MYSQL_RESTORE_SLAVE) +@builders.BuilderFactory.register(TicketType.MYSQL_RESTORE_SLAVE, is_apply=True) class MysqlSingleDestroyFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlRestoreSlaveDetailSerializer inner_flow_builder = MysqlRestoreSlaveParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py b/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py index 3c3a0d15b4..0200ab0147 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_single_apply.py @@ -178,7 +178,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_APPLY) +@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_APPLY, is_apply=True, cluster_type=ClusterType.TenDBSingle) class MysqlSingleApplyFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlSingleApplyDetailSerializer inner_flow_builder = MysqlSingleApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_single_destroy.py b/dbm-ui/backend/ticket/builders/mysql/mysql_single_destroy.py index 48f9c02b1e..1c50c70761 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_single_destroy.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_single_destroy.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -25,7 +26,7 @@ class MysqlSingleDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_single_destroy_scene -@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_DESTROY) +@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_DESTROY, phase=ClusterPhase.DESTROY) class MysqlSingleDestroyFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlSingleDestroyDetailSerializer inner_flow_builder = MysqlSingleDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_single_disable.py b/dbm-ui/backend/ticket/builders/mysql/mysql_single_disable.py index ceb2b4da15..26691b0120 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_single_disable.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_single_disable.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -25,7 +26,7 @@ class MysqlSingleDisableFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_single_disable_scene -@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_DISABLE) +@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_DISABLE, phase=ClusterPhase.OFFLINE) class MysqlSingleDisableFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlSingleDisableDetailSerializer inner_flow_builder = MysqlSingleDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_single_enable.py b/dbm-ui/backend/ticket/builders/mysql/mysql_single_enable.py index c2e67aa7ca..43e2d9f6e3 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_single_enable.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_single_enable.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.mysql import MySQLController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLClustersTakeDownDetailsSerializer @@ -25,7 +26,7 @@ class MysqlSingleEnableFlowParamBuilder(builders.FlowParamBuilder): controller = MySQLController.mysql_single_enable_scene -@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_ENABLE) +@builders.BuilderFactory.register(TicketType.MYSQL_SINGLE_ENABLE, phase=ClusterPhase.ONLINE) class MysqlSingleEnableFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlSingleEnableDetailSerializer inner_flow_builder = MysqlSingleEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_apply.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_apply.py index 3d4c0a5511..0936f8126d 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_apply.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_apply.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ from rest_framework import serializers +from backend.db_meta.enums import ClusterType from backend.db_services.dbbase.constants import IpSource from backend.flow.engine.controller.pulsar import PulsarController from backend.ticket import builders @@ -91,7 +92,7 @@ class PulsarApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): pass -@builders.BuilderFactory.register(TicketType.PULSAR_APPLY) +@builders.BuilderFactory.register(TicketType.PULSAR_APPLY, is_apply=True, cluster_type=ClusterType.Pulsar) class PulsarApplyFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarApplyDetailSerializer inner_flow_builder = PulsarApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_destroy.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_destroy.py index 8140659649..0099a38ac7 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_destroy.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_destroy.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.pulsar import PulsarController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BasePulsarTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class PulsarDestroyFlowParamBuilder(builders.FlowParamBuilder): controller = PulsarController.pulsar_destroy_scene -@builders.BuilderFactory.register(TicketType.PULSAR_DESTROY) +@builders.BuilderFactory.register(TicketType.PULSAR_DESTROY, phase=ClusterPhase.DESTROY) class PulsarDestroyFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarDestroyDetailSerializer inner_flow_builder = PulsarDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_disable.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_disable.py index 6a973d5146..fb61626ebf 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_disable.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_disable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.pulsar import PulsarController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BasePulsarTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class PulsarDisableFlowParamBuilder(builders.FlowParamBuilder): controller = PulsarController.pulsar_disable_scene -@builders.BuilderFactory.register(TicketType.PULSAR_DISABLE) +@builders.BuilderFactory.register(TicketType.PULSAR_DISABLE, phase=ClusterPhase.OFFLINE) class PulsarDisableFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarDisableDetailSerializer inner_flow_builder = PulsarDisableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_enable.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_enable.py index ce91ad9fd2..5c89e72739 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_enable.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_enable.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.pulsar import PulsarController from backend.ticket import builders from backend.ticket.builders.common.bigdata import BasePulsarTicketFlowBuilder, BigDataTakeDownDetailSerializer @@ -30,7 +31,7 @@ class PulsarEnableFlowParamBuilder(builders.FlowParamBuilder): controller = PulsarController.pulsar_enable_scene -@builders.BuilderFactory.register(TicketType.PULSAR_ENABLE) +@builders.BuilderFactory.register(TicketType.PULSAR_ENABLE, phase=ClusterPhase.ONLINE) class PulsarEnableFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarEnableDetailSerializer inner_flow_builder = PulsarEnableFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_replace.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_replace.py index 9de40cd9a1..c864037f80 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_replace.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_replace.py @@ -40,7 +40,7 @@ class PulsarReplaceResourceParamBuilder(BigDataReplaceResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.PULSAR_REPLACE) +@builders.BuilderFactory.register(TicketType.PULSAR_REPLACE, is_apply=True) class PulsarReplaceFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarReplaceDetailSerializer inner_flow_builder = PulsarReplaceFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/pulsar/pulsar_scale_up.py b/dbm-ui/backend/ticket/builders/pulsar/pulsar_scale_up.py index 3c8b68d2e2..832f3cd8a8 100644 --- a/dbm-ui/backend/ticket/builders/pulsar/pulsar_scale_up.py +++ b/dbm-ui/backend/ticket/builders/pulsar/pulsar_scale_up.py @@ -40,7 +40,7 @@ class PulsarScaleUpResourceParamBuilder(BigDataScaleUpResourceParamBuilder): pass -@builders.BuilderFactory.register(TicketType.PULSAR_SCALE_UP) +@builders.BuilderFactory.register(TicketType.PULSAR_SCALE_UP, is_apply=True) class PulsarScaleUpFlowBuilder(BasePulsarTicketFlowBuilder): serializer = PulsarScaleUpDetailSerializer inner_flow_builder = PulsarScaleUpFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_close.py b/dbm-ui/backend/ticket/builders/redis/redis_close.py index 341cf1b0a2..3403fa0637 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_close.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_close.py @@ -10,6 +10,7 @@ """ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.redis import RedisController from backend.ticket import builders from backend.ticket.builders.redis.base import BaseRedisTicketFlowBuilder, RedisSingleOpsBaseDetailSerializer @@ -38,7 +39,7 @@ def format_ticket_data(self): super().format_ticket_data() -@builders.BuilderFactory.register(TicketType.REDIS_CLOSE) +@builders.BuilderFactory.register(TicketType.REDIS_CLOSE, phase=ClusterPhase.OFFLINE) class RedisCloseFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisCloseDetailSerializer inner_flow_builder = RedisCloseFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py b/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py index 4b77722e33..501d21a26a 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_cluster_apply.py @@ -262,7 +262,7 @@ def post_callback(self): next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.REDIS_CLUSTER_APPLY) +@builders.BuilderFactory.register(TicketType.REDIS_CLUSTER_APPLY, is_apply=True) class RedisClusterApplyFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisClusterApplyDetailSerializer inner_flow_builder = RedisClusterApplyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_destroy.py b/dbm-ui/backend/ticket/builders/redis/redis_destroy.py index fa68d1cd5f..af62cfbf8c 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_destroy.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_destroy.py @@ -10,6 +10,7 @@ """ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.redis import RedisController from backend.ticket import builders from backend.ticket.builders.redis.base import ( @@ -39,7 +40,7 @@ def format_ticket_data(self): super().format_ticket_data() -@builders.BuilderFactory.register(TicketType.REDIS_DESTROY) +@builders.BuilderFactory.register(TicketType.REDIS_DESTROY, phase=ClusterPhase.DESTROY) class RedisDestroyFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisDestroyDetailSerializer inner_flow_builder = RedisDestroyFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_open.py b/dbm-ui/backend/ticket/builders/redis/redis_open.py index 75470ac8dd..d75830e3c7 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_open.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_open.py @@ -10,6 +10,7 @@ """ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.redis import RedisController from backend.ticket import builders from backend.ticket.builders.redis.base import BaseRedisTicketFlowBuilder, RedisSingleOpsBaseDetailSerializer @@ -35,7 +36,7 @@ def format_ticket_data(self): super().format_ticket_data() -@builders.BuilderFactory.register(TicketType.REDIS_OPEN) +@builders.BuilderFactory.register(TicketType.REDIS_OPEN, phase=ClusterPhase.ONLINE) class RedisOpenFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisOpenDetailSerializer inner_flow_builder = RedisOpenFlowParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_cut_off.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_cut_off.py index 3aacc2a9f6..44171842ab 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_cut_off.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_cut_off.py @@ -41,7 +41,7 @@ def post_callback(self): super().post_callback() -@builders.BuilderFactory.register(TicketType.REDIS_CLUSTER_CUTOFF) +@builders.BuilderFactory.register(TicketType.REDIS_CLUSTER_CUTOFF, is_apply=True) class RedisClusterCutOffFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisClusterCutOffDetailSerializer inner_flow_builder = RedisClusterCutOffParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_proxy_scale_up.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_proxy_scale_up.py index 120a85931a..5eb60d5631 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_proxy_scale_up.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_proxy_scale_up.py @@ -42,7 +42,7 @@ def post_callback(self): super().post_callback() -@builders.BuilderFactory.register(TicketType.PROXY_SCALE_UP) +@builders.BuilderFactory.register(TicketType.PROXY_SCALE_UP, is_apply=True) class ProxyScaleUpFlowBuilder(BaseRedisTicketFlowBuilder): serializer = ProxyScaleUpDetailSerializer inner_flow_builder = ProxyScaleUpParamBuilder diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_redis_scale_up.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_redis_scale_up.py index d33f3dda78..b075e87683 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_redis_scale_up.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_redis_scale_up.py @@ -41,7 +41,7 @@ def post_callback(self): super().post_callback() -@builders.BuilderFactory.register(TicketType.REDIS_SCALE_UP) +@builders.BuilderFactory.register(TicketType.REDIS_SCALE_UP, is_apply=True) class RedisScaleUpFlowBuilder(BaseRedisTicketFlowBuilder): serializer = RedisScaleUpDetailSerializer inner_flow_builder = RedisScaleUpParamBuilder diff --git a/dbm-ui/backend/ticket/constants.py b/dbm-ui/backend/ticket/constants.py index cf3b171715..40aa051ec9 100644 --- a/dbm-ui/backend/ticket/constants.py +++ b/dbm-ui/backend/ticket/constants.py @@ -71,8 +71,10 @@ class ResourceApplyErrCode(int, StructuredEnum): 资源申请错误码 """ - RESOURCE_LAKE = EnumField(10001, _("资源不足")) - SYSTEM_ERROR = EnumField(10000, _("系统错误")) + RESOURCE_LAKE = EnumField(60001, _("资源不足")) + RESOURCE_LOCK_FAIL = EnumField(60002, _("获取资源所失败")) + RESOURCE_PARAMS_INVALID = EnumField(60003, _("参数合法性校验失败")) + RESOURCE_MACHINE_FAIL = EnumField(60004, _("锁定返回机器失败")) DONE_STATUS = [TodoStatus.DONE_SUCCESS, TodoStatus.DONE_FAILED] @@ -113,8 +115,6 @@ class TicketFlowStatus(str, StructuredEnum): class TicketType(str, StructuredEnum): - """单据类型枚举""" - @classmethod def get_choice_value(cls, label: str) -> str: """Get the value of field member by label""" @@ -280,66 +280,6 @@ def get_choice_value(cls, label: str) -> str: RESOURCE_IMPORT = EnumField("RESOURCE_IMPORT", _("资源池导入")) -# 单据动作与集群状态的映射 -TICKET_TYPE__CLUSTER_PHASE_MAP = { - # MySQL单据----MySQL phase - TicketType.MYSQL_HA_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.MYSQL_HA_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.MYSQL_HA_DESTROY.value: ClusterPhase.DESTROY.value, - TicketType.MYSQL_SINGLE_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.MYSQL_SINGLE_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.MYSQL_SINGLE_DESTROY.value: ClusterPhase.DESTROY.value, - # ES单据---ES phase - TicketType.ES_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.ES_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.ES_DESTROY.value: ClusterPhase.DESTROY.value, - # Kafka单据---Kafka phase - TicketType.KAFKA_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.KAFKA_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.KAFKA_DESTROY.value: ClusterPhase.DESTROY.value, - # Hdfs单据---Hdfs phase - TicketType.HDFS_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.HDFS_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.HDFS_DESTROY.value: ClusterPhase.DESTROY.value, - # Pulsar单据---Pulsar phase - TicketType.PULSAR_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.PULSAR_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.PULSAR_DESTROY.value: ClusterPhase.DESTROY.value, - # Influxdb单据---Influxdb phase - TicketType.INFLUXDB_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.INFLUXDB_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.INFLUXDB_DESTROY.value: ClusterPhase.DESTROY.value, - # Spider单据---Spider phase - TicketType.TENDB_CLUSTER_ENABLE.value: ClusterPhase.ONLINE.value, - TicketType.TENDB_CLUSTER_DISABLE.value: ClusterPhase.OFFLINE.value, - TicketType.TENDB_CLUSTER_DESTROY.value: ClusterPhase.DESTROY.value, -} - -# 单据类型和集群类型的映射 -TICKET_TYPE__CLUSTER_TYPE_MAP = { - # MySQL - TicketType.MYSQL_SINGLE_APPLY: ClusterType.TenDBSingle, - TicketType.MYSQL_HA_APPLY: ClusterType.TenDBHA, - # 大数据 - TicketType.KAFKA_APPLY: ClusterType.Kafka, - TicketType.HDFS_APPLY: ClusterType.Hdfs, - TicketType.ES_APPLY: ClusterType.Es, - TicketType.PULSAR_APPLY: ClusterType.Pulsar, - TicketType.INFLUXDB_APPLY: ClusterType.Influxdb - # Redis TODO: redis集群类型太多了,但是单据类型就一种,如何区分? -} - -# 扩容单据合集 -SCALE_UP_TICKET_TYPES = [ - TicketType.REDIS_SCALE_UP, - TicketType.ES_SCALE_UP, - TicketType.HDFS_SCALE_UP, - TicketType.KAFKA_SCALE_UP, - TicketType.PULSAR_SCALE_UP, - TicketType.PROXY_SCALE_UP, -] - - class FlowType(str, StructuredEnum): """流程类型枚举""" diff --git a/dbm-ui/backend/ticket/flow_manager/resource.py b/dbm-ui/backend/ticket/flow_manager/resource.py index d41ace0f7c..5a547d12a3 100644 --- a/dbm-ui/backend/ticket/flow_manager/resource.py +++ b/dbm-ui/backend/ticket/flow_manager/resource.py @@ -116,12 +116,17 @@ def apply_resource(self, ticket_data): # 如果是资源不足,则创建补货单,用户手动处理后可以重试资源申请 self.create_replenish_todo() raise ResourceApplyException(_("资源不足申请失败,请前往补货后重试")) - elif resp["code"] == ResourceApplyErrCode.SYSTEM_ERROR: - raise ResourceApplyException(_("资源池相关服务出现系统错误,请联系管理员或稍后重试")) - - resource_request_id, apply_data = resp["request_id"], resp["data"] + elif resp["code"] in [ + ResourceApplyErrCode.RESOURCE_LOCK_FAIL, + ResourceApplyErrCode.RESOURCE_MACHINE_FAIL, + ResourceApplyErrCode.RESOURCE_PARAMS_INVALID, + ]: + raise ResourceApplyException( + _("资源池相关服务出现系统错误,请联系管理员或稍后重试。错误信息: {}").format(ResourceApplyErrCode.get_choice_label(resp["code"])) + ) # 将资源池申请的主机信息转换为单据参数 + resource_request_id, apply_data = resp["request_id"], resp["data"] node_infos: Dict[str, List] = defaultdict(list) for info in apply_data: role = info["item"] @@ -144,7 +149,7 @@ def create_replenish_todo(self): from backend.ticket.todos.pause_todo import PauseTodoContext Todo.objects.create( - name=_("【{}】流程所需资源不足,请前往补货").format(self.ticket.get_ticket_type_display()), + name=_("【{}】流程所需资源不足").format(self.ticket.get_ticket_type_display()), flow=self.flow_obj, ticket=self.ticket, type=TodoType.RESOURCE_REPLENISH, diff --git a/dbm-ui/backend/ticket/handler.py b/dbm-ui/backend/ticket/handler.py index 21bd0412b7..3c7262295d 100644 --- a/dbm-ui/backend/ticket/handler.py +++ b/dbm-ui/backend/ticket/handler.py @@ -12,7 +12,10 @@ from django.utils.translation import ugettext as _ +from backend import env from backend.db_meta.models import Cluster, StorageInstance +from backend.db_services.ipchooser.handlers.host_handler import HostHandler +from backend.ticket.constants import TicketType from backend.ticket.models import Ticket from backend.utils.basic import get_target_items_from_details @@ -68,3 +71,64 @@ def add_related_object(cls, ticket_data: List[Dict]) -> List[Dict]: ], } return ticket_data + + @classmethod + def fast_create_cloud_component_method(cls, bk_biz_id, bk_cloud_id, ips, user="admin"): + def _get_base_info(host): + return { + "bk_host_id": host["host_id"], + "ip": host["ip"], + "bk_cloud_id": host["cloud_id"], + } + + # 查询的机器的信息 + host_list = [{"cloud_id": bk_cloud_id, "ip": ip} for ip in ips] + host_infos = HostHandler.details(scope_list=[{"bk_biz_id": bk_biz_id}], host_list=host_list) + + # 构造nginx部署信息 + nginx_host_infos = [ + { + "bk_outer_ip": host_infos[1].get("bk_host_outerip") or host_infos[1]["ip"], + **_get_base_info(host_infos[1]), + } + ] + # 构造dns的部署信息 + dns_host_infos = [{**_get_base_info(host_infos[0])}, {**_get_base_info(host_infos[1])}] + # 构造drs的部署信息 + drs_host_infos = [ + {**_get_base_info(host_infos[0]), "drs_port": env.DRS_PORT}, + {**_get_base_info(host_infos[1]), "drs_port": env.DRS_PORT}, + ] + # 构造agent的部署信息 + agent_host_infos = [ + { + **_get_base_info(host_infos[0]), + "bk_city_code": host_infos[0].get("bk_idc_id") or 0, + "bk_city_name": host_infos[0].get("bk_idc_name", ""), + } + ] + # 构造gm的部署信息 + gm_host_infos = [ + agent_host_infos[0], # 允许将一个gm和agent部署在同一台机器 + { + **_get_base_info(host_infos[1]), + "bk_city_code": host_infos[1].get("bk_idc_id") or 1, + "bk_city_name": host_infos[1].get("bk_idc_name", ""), + }, + ] + + # 创建单据进行部署 + details = { + "bk_cloud_id": bk_cloud_id, + "dns": {"host_infos": dns_host_infos}, + "nginx": {"host_infos": nginx_host_infos}, + "drs": {"host_infos": drs_host_infos}, + "dbha": {"gm": gm_host_infos, "agent": agent_host_infos}, + } + Ticket.create_ticket( + ticket_type=TicketType.CLOUD_SERVICE_APPLY, + creator=user, + bk_biz_id=bk_biz_id, + remark=_("云区域组件快速部署单据"), + details=details, + ) diff --git a/dbm-ui/backend/ticket/todos/pause_todo.py b/dbm-ui/backend/ticket/todos/pause_todo.py index e48aa29ffb..1e8b45a5a4 100644 --- a/dbm-ui/backend/ticket/todos/pause_todo.py +++ b/dbm-ui/backend/ticket/todos/pause_todo.py @@ -11,7 +11,7 @@ from dataclasses import dataclass from backend.ticket import todos -from backend.ticket.constants import TodoType +from backend.ticket.constants import TicketFlowStatus, TodoType from backend.ticket.flow_manager import manager from backend.ticket.flow_manager.manager import TicketFlowManager from backend.ticket.todos import ActionType, BaseTodoContext @@ -51,6 +51,10 @@ def process(self, username, action, params): self.todo.set_failed(username, action) return - TicketFlowManager(ticket=self.todo.ticket).get_ticket_flow_cls(self.todo.flow.flow_type)( + # 尝试重新申请资源 + resource_apply_flow = TicketFlowManager(ticket=self.todo.ticket).get_ticket_flow_cls(self.todo.flow.flow_type)( self.todo.flow - ).retry() + ) + + resource_apply_flow.retry() + self.todo.set_success(username, action) diff --git a/dbm-ui/backend/ticket/views.py b/dbm-ui/backend/ticket/views.py index d8ece63a25..9da6557be2 100644 --- a/dbm-ui/backend/ticket/views.py +++ b/dbm-ui/backend/ticket/views.py @@ -451,66 +451,5 @@ def fast_create_cloud_component(self, request, *args, **kwargs): bk_cloud_id = validated_data["bk_cloud_id"] ips = validated_data["ips"] bk_biz_id = validated_data["bk_biz_id"] - self.fast_create_cloud_component_method(bk_biz_id, bk_cloud_id, ips, request.user.username) + TicketHandler.fast_create_cloud_component_method(bk_biz_id, bk_cloud_id, ips, request.user.username) return Response() - - @classmethod - def fast_create_cloud_component_method(cls, bk_biz_id, bk_cloud_id, ips, user="admin"): - def _get_base_info(host): - return { - "bk_host_id": host["host_id"], - "ip": host["ip"], - "bk_cloud_id": host["cloud_id"], - } - - # 查询的机器的信息 - host_list = [{"cloud_id": bk_cloud_id, "ip": ip} for ip in ips] - host_infos = HostHandler.details(scope_list=[{"bk_biz_id": bk_biz_id}], host_list=host_list) - - # 构造nginx部署信息 - nginx_host_infos = [ - { - "bk_outer_ip": host_infos[1].get("bk_host_outerip") or host_infos[1]["ip"], - **_get_base_info(host_infos[1]), - } - ] - # 构造dns的部署信息 - dns_host_infos = [{**_get_base_info(host_infos[0])}, {**_get_base_info(host_infos[1])}] - # 构造drs的部署信息 - drs_host_infos = [ - {**_get_base_info(host_infos[0]), "drs_port": env.DRS_PORT}, - {**_get_base_info(host_infos[1]), "drs_port": env.DRS_PORT}, - ] - # 构造agent的部署信息 - agent_host_infos = [ - { - **_get_base_info(host_infos[0]), - "bk_city_code": host_infos[0].get("bk_idc_id") or 0, - "bk_city_name": host_infos[0].get("bk_idc_name", ""), - } - ] - # 构造gm的部署信息 - gm_host_infos = [ - agent_host_infos[0], # 允许将一个gm和agent部署在同一台机器 - { - **_get_base_info(host_infos[1]), - "bk_city_code": host_infos[1].get("bk_idc_id") or 1, - "bk_city_name": host_infos[1].get("bk_idc_name", ""), - }, - ] - - # 创建单据进行部署 - details = { - "bk_cloud_id": bk_cloud_id, - "dns": {"host_infos": dns_host_infos}, - "nginx": {"host_infos": nginx_host_infos}, - "drs": {"host_infos": drs_host_infos}, - "dbha": {"gm": gm_host_infos, "agent": agent_host_infos}, - } - Ticket.create_ticket( - ticket_type=TicketType.CLOUD_SERVICE_APPLY, - creator=user, - bk_biz_id=bk_biz_id, - remark=_("云区域组件快速部署单据"), - details=details, - ) diff --git a/dbm-ui/backend/urls.py b/dbm-ui/backend/urls.py index ff12a67333..08417b5671 100644 --- a/dbm-ui/backend/urls.py +++ b/dbm-ui/backend/urls.py @@ -50,6 +50,7 @@ path("proxypass/", include("backend.db_proxy.urls")), path("monitor/", include("backend.db_monitor.urls")), path("event/", include("backend.db_event.urls")), + path("db_dirty/", include("backend.db_dirty.urls")), path("redisdts/", include("backend.db_services.redis_dts.urls")), ] diff --git a/dbm-ui/config/default.py b/dbm-ui/config/default.py index 7bd32fb02c..cfb3fb2132 100644 --- a/dbm-ui/config/default.py +++ b/dbm-ui/config/default.py @@ -79,6 +79,7 @@ "backend.db_monitor", "backend.db_services.redis_dts", "backend.db_services.redis.rollback", + "backend.db_dirty" ) From e058821a18f6691b3a603b0291615ae230c92769 Mon Sep 17 00:00:00 2001 From: seanlook Date: Wed, 12 Jul 2023 21:33:04 +0800 Subject: [PATCH 130/476] =?UTF-8?q?feat(mysql):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AE=98=E6=96=B9mysql=208.0=E9=83=A8=E7=BD=B2=20close=20#469?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/go-pubpkg/mysqlcomm/spider.go | 7 +++++ .../common/go-pubpkg/reportlog/report.go | 4 ++- .../pkg/components/db_base_account.go | 3 +- .../dbactuator/pkg/components/medium.go | 2 +- .../pkg/components/mysql/install_mysql.go | 13 ++++---- .../components/mysql/install_new_dbbackup.go | 30 ++++++++++++++++--- .../db-tools/dbactuator/pkg/core/cst/os.go | 15 ++++++++-- .../dbactuator/pkg/native/dbworker.go | 15 ++++++---- .../db-tools/mysql-dbbackup/dbbackup_main.sh | 2 +- .../pkg/src/dbareport/backup_result.go | 2 +- .../pkg/src/dbareport/prepareinfo.go | 9 ++++-- .../mysql-dbbackup/pkg/src/mysqlconn/conn.go | 3 +- 12 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 dbm-services/common/go-pubpkg/mysqlcomm/spider.go diff --git a/dbm-services/common/go-pubpkg/mysqlcomm/spider.go b/dbm-services/common/go-pubpkg/mysqlcomm/spider.go new file mode 100644 index 0000000000..8d72e4fc3b --- /dev/null +++ b/dbm-services/common/go-pubpkg/mysqlcomm/spider.go @@ -0,0 +1,7 @@ +package mysqlcomm + +// GetTdbctlPortBySpider 根据 spider master 端口,获取 tdbctl 端口 +// tdbctl port = spider_port + 1000 +func GetTdbctlPortBySpider(spiderPort int) int { + return spiderPort + 1000 +} diff --git a/dbm-services/common/go-pubpkg/reportlog/report.go b/dbm-services/common/go-pubpkg/reportlog/report.go index cd78be6753..329760a3ce 100644 --- a/dbm-services/common/go-pubpkg/reportlog/report.go +++ b/dbm-services/common/go-pubpkg/reportlog/report.go @@ -56,8 +56,10 @@ func NewReporter(reportDir, filename string, logOpt *LoggerOption) (*Reporter, e if err := os.MkdirAll(reportDir, 0755); err != nil { return nil, errors.Wrap(err, "create report path") } + } + if !cmutil.FileExists(logFilePath) { // lumberjack 默认创建的文件权限是 600 - if f, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_WRONLY, 0644); err != nil { + if f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY, 0644); err != nil { return nil, err } else { f.Close() diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/db_base_account.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/db_base_account.go index ea1e99dcb5..379cc921f8 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/db_base_account.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/db_base_account.go @@ -206,7 +206,8 @@ type MySQLDbBackupAccount struct { DbBackupPwd string `json:"backup_pwd,omitempty"` // dbbackup pwd } -// GetAccountPrivs TODO +// GetAccountPrivs 获取备份语句 +// 如果是 mysql 8.0,grant 需要 BACKUP_ADMIN 权限 func (m MySQLDbBackupAccount) GetAccountPrivs(is80 bool, grantHosts ...string) MySQLAccountPrivs { privPairs := []PrivPari{ {Object: "*.*", Privs: backupUserPriv}, diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/medium.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/medium.go index cf24fbb9da..86f7785df1 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/medium.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/medium.go @@ -46,7 +46,7 @@ func (m *Medium) GetAbsolutePath() string { // 用于做软连接使用 func (m *Medium) GePkgBaseName() string { pkgFullName := filepath.Base(m.GetAbsolutePath()) - return regexp.MustCompile("(.tar.gz|.tgz)$").ReplaceAllString(pkgFullName, "") + return regexp.MustCompile("(.tar.gz|.tgz|.tar.xz)$").ReplaceAllString(pkgFullName, "") } // GetPkgTypeName 通过介质包文件名称获取对应的组件类型 diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_mysql.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_mysql.go index bb3d5aea81..3d0c76e9ec 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_mysql.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_mysql.go @@ -311,10 +311,10 @@ func (i *InstallMySQLComp) precheckMysqlProcess() (err error) { func (i *InstallMySQLComp) precheckMysqlPackageBitOS() error { var mysqlBits = cst.Bit64 - if strings.Contains(i.Params.MysqlVersion, cst.Bit32) { + if strings.Contains(i.Params.Medium.Pkg, cst.X32) { mysqlBits = cst.Bit32 } - if strings.Compare(mysqlBits, strconv.Itoa(cst.OSBits)) != 0 { + if mysqlBits != cst.OSBits { return fmt.Errorf("mysql 安装包的和系统不匹配,当前系统是%d", cst.OSBits) } return nil @@ -505,8 +505,8 @@ func (i *InstallMySQLComp) DecompressMysqlPkg() (err error) { } } pkgAbPath := i.Params.Medium.GetAbsolutePath() - if output, err := osutil.ExecShellCommand(false, fmt.Sprintf("tar zxf %s", pkgAbPath)); err != nil { - logger.Error("tar zxf %s error:%s,%s", pkgAbPath, output, err.Error()) + if output, err := osutil.ExecShellCommand(false, fmt.Sprintf("tar -xf %s", pkgAbPath)); err != nil { + logger.Error("tar -xf %s error:%s,%s", pkgAbPath, output, err.Error()) return err } mysqlBinaryFile := i.Params.Medium.GePkgBaseName() @@ -867,6 +867,7 @@ func (i *InstallMySQLComp) InstallRplSemiSyncPlugin() (err error) { } // DecompressTdbctlPkg 针对mysql-tdbctl的场景,解压并生成新的目录作为tdbctl运行目录 +// mysql 安装包可能有 .tar.gz .tar.xz 两种格式 func (i *InstallMySQLComp) DecompressTdbctlPkg() (err error) { if err = os.Chdir(i.InstallDir); err != nil { return fmt.Errorf("cd to dir %s failed, err:%w", i.InstallDir, err) @@ -892,9 +893,9 @@ func (i *InstallMySQLComp) DecompressTdbctlPkg() (err error) { pkgAbPath := i.Params.Medium.GetAbsolutePath() if output, err := osutil.ExecShellCommand( false, - fmt.Sprintf("mkdir %s && tar zxf %s -C %s --strip-components 1 ", tdbctlBinaryFile, pkgAbPath, + fmt.Sprintf("mkdir %s && tar -xf %s -C %s --strip-components 1 ", tdbctlBinaryFile, pkgAbPath, tdbctlBinaryFile)); err != nil { - logger.Error("tar zxf %s error:%s,%s", pkgAbPath, output, err.Error()) + logger.Error("tar -xf %s error:%s,%s", pkgAbPath, output, err.Error()) return err } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_new_dbbackup.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_new_dbbackup.go index fe8f74ddff..319715835f 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_new_dbbackup.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_new_dbbackup.go @@ -5,11 +5,13 @@ import ( "os" "path" "path/filepath" + "sort" "strings" "text/template" "time" "dbm-services/common/go-pubpkg/logger" + "dbm-services/common/go-pubpkg/mysqlcomm" "dbm-services/mysql/db-tools/dbactuator/pkg/components" "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" "dbm-services/mysql/db-tools/dbactuator/pkg/native" @@ -261,8 +263,8 @@ func (i *InstallNewDbBackupComp) DecompressPkg() (err error) { return err } cmd := fmt.Sprintf( - "tar zxf %s -C %s && chown -R mysql %s", i.Params.Medium.GetAbsolutePath(), - path.Dir(i.installPath), i.installPath, + "tar zxf %s -C %s && mkdir -p %s && chown -R mysql %s", i.Params.Medium.GetAbsolutePath(), + path.Dir(i.installPath), filepath.Join(i.installPath, "logs"), i.installPath, ) output, err := osutil.ExecShellCommand(false, cmd) if err != nil { @@ -272,14 +274,34 @@ func (i *InstallNewDbBackupComp) DecompressPkg() (err error) { return nil } -// InitBackupUserPriv TODO +// InitBackupUserPriv 创建备份用户 +// TODO 用户初始化考虑在部署 mysqld 的时候进行 func (i *InstallNewDbBackupComp) InitBackupUserPriv() (err error) { + var tdbctlPort int + if i.Params.Role == cst.BackupRoleSpiderMaster { + if len(i.Params.Ports) != 2 { + return errors.Errorf("install dbbackup on %s expect spider and tdbctl port", cst.BackupRoleSpiderMaster) + } + sort.Ints(i.Params.Ports) + spiderPort := i.Params.Ports[0] + tdbctlPortExpect := mysqlcomm.GetTdbctlPortBySpider(spiderPort) + if i.Params.Ports[1] != tdbctlPortExpect { + return errors.Errorf("tdbctl port expect %d but got %d", tdbctlPortExpect, tdbctlPort) + } + tdbctlPort = i.Params.Ports[1] + } + for _, port := range i.Params.Ports { ver := i.versionMap[port] var isMysql80 = mysqlutil.MySQLVersionParse(ver) >= mysqlutil.MySQLVersionParse("8.0") && !strings.Contains(ver, "tspider") privs := i.GeneralParam.RuntimeAccountParam.MySQLDbBackupAccount.GetAccountPrivs(isMysql80, i.Params.Host) - sqls := privs.GenerateInitSql(ver) + var sqls []string + if port == tdbctlPort { + logger.Info("tdbctl port %d need tc_admin=0, binlog_format=off", port) + sqls = append(sqls, "set session tc_admin=0;", "set session binlog_format=off;") + } + sqls = append(sqls, privs.GenerateInitSql(ver)...) dc, ok := i.dbConn[port] if !ok { return fmt.Errorf("from dbConns 获取%d连接失败", port) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/os.go b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/os.go index 9164ef73b8..079d08d70a 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/os.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/os.go @@ -1,8 +1,17 @@ package cst +import "strconv" + // bits const ( - Bit64 = "64" - Bit32 = "32" - OSBits = 32 << uintptr(^uintptr(0)>>63) + // X64 x86_64 + X64 = "x86_64" + // X32 x86_32 + X32 = "i686" + // Arm64 aarch64 + Arm64 = "aarch64" + Bit64 = 64 + Bit32 = 32 + //OSBits = 32 << uintptr(^uintptr(0)>>63) + OSBits = strconv.IntSize ) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go b/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go index 0423705c8f..d0f2ea2d2f 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/native/dbworker.go @@ -102,15 +102,20 @@ func (h *DbWorker) ExecWithTimeout(dura time.Duration, query string, args ...int } // ExecMore 执行一堆sql +// 会在同一个连接里执行 func (h *DbWorker) ExecMore(sqls []string) (rowsAffectedCount int64, err error) { var c int64 - for _, args := range sqls { - ret, err := h.Db.Exec(args) + db, err := h.Db.Conn(context.Background()) + if err != nil { + return 0, err + } + for _, sqlStr := range sqls { + ret, err := db.ExecContext(context.Background(), sqlStr) if err != nil { - return rowsAffectedCount, fmt.Errorf("exec %s failed,err:%w", args, err) + return rowsAffectedCount, fmt.Errorf("exec %s failed,err:%w", sqlStr, err) } if c, err = ret.RowsAffected(); err != nil { - return rowsAffectedCount, fmt.Errorf("exec %s failed,err:%w", args, err) + return rowsAffectedCount, fmt.Errorf("exec %s failed,err:%w", sqlStr, err) } rowsAffectedCount += c } @@ -332,7 +337,7 @@ func (h *DbWorker) SelectVersion() (version string, err error) { // SelectNow 获取实例的当前时间。不是获取机器的,因为可能存在时区不一样 func (h *DbWorker) SelectNow() (nowTime string, err error) { - err = h.Queryxs(&nowTime, "select now() as not_time;") + err = h.Queryxs(&nowTime, "select now() as now_time;") return } diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/dbbackup_main.sh b/dbm-services/mysql/db-tools/mysql-dbbackup/dbbackup_main.sh index dd1749dd97..110ecac007 100755 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/dbbackup_main.sh +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/dbbackup_main.sh @@ -93,7 +93,7 @@ okPorts="" for conf_file in $configFiles do #port=`echo $conf_file |awk -F. '{print $(NF-1)}'` - port=`grep MysqlPort $conf_file |head -1|grep -v "#" |cut -d= -f2` + port=`grep MysqlPort $conf_file |grep -Ev "#|MysqlPort = 0" |head -1 | cut -d= -f2` echo "now doing dbbackup for config file=$conf_file port=$port" echo "${scriptDir}/dbbackup dumpbackup --config=$conf_file $dbbackupOpt 2>&1 >> $logfile" ${scriptDir}/dbbackup dumpbackup --config=$conf_file $dbbackupOpt 2>&1 >> $logfile diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/backup_result.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/backup_result.go index fd56437aac..d0a221bdb4 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/backup_result.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/backup_result.go @@ -108,7 +108,7 @@ func (b *BackupResult) PrepareXtraBackupInfo(cnf *config.BackupConfig) error { return err } exepath = filepath.Dir(exepath) - binpath := filepath.Join(exepath, "/bin/xtrabackup", "qpress") + binpath := filepath.Join(exepath, "/bin", "qpress") // parse xtrabackup_info if err := parseXtraInfo(b, binpath, xtrabackupInfoFileName, tmpFileName); err != nil { diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/prepareinfo.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/prepareinfo.go index d7d728b28b..5fc0740539 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/prepareinfo.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/prepareinfo.go @@ -177,9 +177,12 @@ func parseXtraTimestamp(backupResult *BackupResult, binpath string, fileName str } backupResult.ConsistentBackupTime = consistentTime.Format("2006-01-02 15:04:05") } - } /* else { - b.ConsistentBackupTime = startTime - } */ + } else { + // 此时刚备份完成,还没有开始打包,这里把当前时间认为是 consistent_time,不完善! + logger.Log.Warnf("xtrabackup_info file not found: %s, use current time as Consistent Time", fileName) + // TODO 时区问题,待处理 + backupResult.ConsistentBackupTime = time.Now().Format("2006-01-02 15:04:05") + } return nil } diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/mysqlconn/conn.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/mysqlconn/conn.go index 0f0f29c7a9..b7bf57765f 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/mysqlconn/conn.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/mysqlconn/conn.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cast" + "dbm-services/common/go-pubpkg/mysqlcomm" "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/config" "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/cst" "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/logger" @@ -217,7 +218,7 @@ func IsPrimarySpider(spiderInst InsObject) (bool, error) { func GetTdbctlInst(spiderInst InsObject) InsObject { ctlInst := InsObject{ Host: spiderInst.Host, - Port: spiderInst.Port + 1000, // tdbctl port = spider_port + 1000 + Port: mysqlcomm.GetTdbctlPortBySpider(spiderInst.Port), User: spiderInst.User, Pwd: spiderInst.Pwd, } From 5d262bb9a892fb118755d6c2de097329652d7882 Mon Sep 17 00:00:00 2001 From: xiepaup Date: Wed, 12 Jul 2023 16:36:23 +0800 Subject: [PATCH 131/476] =?UTF-8?q?fix(redis):=20=E4=BF=AE=E5=A4=8DRedis?= =?UTF-8?q?=20=E4=B8=BB=E4=BB=8E=E5=88=87=E6=8D=A2bug=20#461?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/flow/consts.py | 6 ++++++ .../scene/redis/atom_jobs/redis_switch.py | 20 +++++++++++-------- .../scene/redis/redis_cluster_scene_mss.py | 4 +++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index b1a2bcff63..ca2c069e25 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -701,6 +701,12 @@ class SyncType(str, StructuredEnum): SYNC_SMS = EnumField("msms", _("msms")) +class SwitchType(str, StructuredEnum): + "切换时是否需要,用户确认" + SWITCH_WITH_CONFIRM = "user_confirm" + SWITCH_WITHOUT_CONFIRM = "no_confirm" + + class RedisSlotSep(str, StructuredEnum): """ redis slot分隔符 diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_switch.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_switch.py index de4ef35521..eff1318f5c 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_switch.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_switch.py @@ -17,7 +17,7 @@ from backend.configuration.constants import DBType from backend.constants import IP_PORT_DIVIDER from backend.db_meta.api.cluster import nosqlcomm -from backend.flow.consts import SyncType +from backend.flow.consts import SwitchType, SyncType from backend.flow.engine.bamboo.scene.common.builder import SubBuilder from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList from backend.flow.plugins.components.collections.common.pause import PauseComponent @@ -70,13 +70,17 @@ def RedisClusterSwitchAtomJob(root_id, data, act_kwargs: ActKwargs, sync_params: } ) act_kwargs.cluster["meta_func_name"] = RedisDBMeta.redis_replace_pair.__name__ - if not SyncType.SYNC_MS.value == sync_host["sync_type"]: + if not SyncType.SYNC_MS.value == act_kwargs.cluster["switch_condition"]["sync_type"]: sub_pipeline.add_act( act_name=_("Redis-元数据加入集群"), act_component_code=RedisDBMetaComponent.code, kwargs=asdict(act_kwargs) ) - # # 人工确认 TODO 4 Test. - # sub_pipeline.add_act(act_name=_("Redis-人工确认"), act_component_code=PauseComponent.code, kwargs={}) + # # 人工确认 + # if ( + # act_kwargs.cluster.get("switch_option", SwitchType.SWITCH_WITH_CONFIRM.value) + # == SwitchType.SWITCH_WITH_CONFIRM.value + # ): + # sub_pipeline.add_act(act_name=_("Redis-人工确认"), act_component_code=PauseComponent.code, kwargs={}) # 下发介质包 act_kwargs.exec_ip = exec_ip @@ -97,11 +101,11 @@ def RedisClusterSwitchAtomJob(root_id, data, act_kwargs: ActKwargs, sync_params: { "master": { "ip": sync_host["origin_1"], - "port": sync_port["origin_1"], + "port": int(sync_port["origin_1"]), }, "slave": { "ip": sync_host["sync_dst1"], - "port": sync_port["sync_dst1"], + "port": int(sync_port["sync_dst1"]), }, } ) @@ -134,11 +138,11 @@ def RedisClusterSwitchAtomJob(root_id, data, act_kwargs: ActKwargs, sync_params: { "ejector": { "ip": sync_host["origin_1"], - "port": sync_port["origin_1"], + "port": int(sync_port["origin_1"]), }, "receiver": { "ip": sync_host["sync_dst1"], - "port": sync_port["sync_dst1"], + "port": int(sync_port["sync_dst1"]), }, } ) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py index 6d6c56573d..f40cb98201 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py @@ -53,6 +53,7 @@ class RedisClusterMSSSceneFlow(object): "infos": [ { "cluster_id": 1, + "online_switch_type":"user_confirm/no_confirm", "pairs": [ {"redis_master": "1.1.a.3", "redis_slave": "1.1.2.b"} ] @@ -134,6 +135,7 @@ def redis_ms_switch(self): for k, v in cluster_info.items(): cluster_kwargs.cluster[k] = v cluster_kwargs.cluster["created_by"] = self.data["created_by"] + cluster_kwargs.cluster["switch_option"] = ms_switch["online_switch_type"] flow_data["switch_input"] = ms_switch redis_pipeline.add_act( act_name=_("初始化配置-{}".format(cluster_info["immute_domain"])), @@ -166,7 +168,6 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch): master_ips.append(master_ip) slave_ips.append(slave_ip) sync_params = { - "sync_type": SyncType.SYNC_MS.value, "origin_1": master_ip, "origin_2": slave_ip, "sync_dst1": slave_ip, @@ -187,6 +188,7 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch): ) sync_relations.append(sync_params) act_kwargs.cluster["switch_condition"] = { + "sync_type": SyncType.SYNC_MS.value, "is_check_sync": ms_switch.get("force_switch", True), # 强制切换 "slave_master_diff_time": DEFAULT_MASTER_DIFF_TIME, "last_io_second_ago": DEFAULT_LAST_IO_SECOND_AGO, From ee996cb4945928bbba4f88f704a360e280e4be51 Mon Sep 17 00:00:00 2001 From: OMG-By <504094596@qq.com> Date: Wed, 12 Jul 2023 19:10:16 +0800 Subject: [PATCH 132/476] feat(redis): redis ssd scale #435 --- .../bamboo/scene/redis/atom_jobs/redis_makesync.py | 11 +++++++---- .../engine/bamboo/scene/redis/redis_backend_scale.py | 8 ++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py index c28852da2f..b8c7b66a8c 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_makesync.py @@ -85,7 +85,10 @@ def RedisMakeSyncAtomJob(root_id, ticket_data, sub_kwargs: ActKwargs, params: Di RedisCacheMakeSyncAtomJob(sub_pipeline=sub_pipeline, act_kwargs=act_kwargs, params=params) # sub_pipeline = RedisCacheMakeSyncAtomJob(sub_pipeline=sub_pipeline, act_kwargs=act_kwargs, params=params) elif act_kwargs.cluster["cluster_type"] == ClusterType.TwemproxyTendisSSDInstance: + # 备份这里act需要的是string, cluster里的参数会覆盖掉playload里的。所以这里需要转一下 + act_kwargs.cluster["bk_biz_id"] = str(act_kwargs.cluster["bk_biz_id"]) RedisSSDMakeSyncAtomJob(sub_pipeline=sub_pipeline, act_kwargs=act_kwargs, params=params) + act_kwargs.cluster["bk_biz_id"] = int(act_kwargs.cluster["bk_biz_id"]) else: raise Exception("unsupport cluster type 4 make sync {}".format(params["cluster_type"])) @@ -112,7 +115,7 @@ def RedisMakeSyncAtomJob(root_id, ticket_data, sub_kwargs: ActKwargs, params: Di act_kwargs.cluster["servers"][0]["meta_role"] = InstanceRole.REDIS_MASTER.value act_kwargs.get_redis_payload_func = RedisActPayload.bkdbmon_install.__name__ sub_pipeline.add_act( - act_name=_("Redis-{}-拉起dbmon").format(exec_ip), + act_name=_("RedisMaster-{}-拉起dbmon").format(exec_ip), act_component_code=ExecuteDBActuatorScriptComponent.code, kwargs=asdict(act_kwargs), ) @@ -127,7 +130,7 @@ def RedisMakeSyncAtomJob(root_id, ticket_data, sub_kwargs: ActKwargs, params: Di act_kwargs.cluster["servers"][0]["server_ip"] = params["sync_dst2"] act_kwargs.cluster["servers"][0]["server_ports"] = server_ports sub_pipeline.add_act( - act_name=_("Redis-{}-拉起dbmon").format(exec_ip), + act_name=_("RedisSlave-{}-拉起dbmon").format(exec_ip), act_component_code=ExecuteDBActuatorScriptComponent.code, kwargs=asdict(act_kwargs), ) @@ -258,8 +261,8 @@ def backup_and_restore( # 恢复备份 act_kwargs.cluster["master_ip"] = params[data_from] act_kwargs.cluster["slave_ip"] = params[data_to] - act_kwargs.cluster["slave_ports"] = [int(sync_direct[data_from]) for sync_direct in params["ins_link"]] - act_kwargs.cluster["master_ports"] = [int(sync_direct[data_to]) for sync_direct in params["ins_link"]] + act_kwargs.cluster["slave_ports"] = [int(sync_direct[data_to]) for sync_direct in params["ins_link"]] + act_kwargs.cluster["master_ports"] = [int(sync_direct[data_from]) for sync_direct in params["ins_link"]] act_kwargs.get_redis_payload_func = RedisActPayload.redis_tendisssd_dr_restore_4_scene.__name__ sub_pipeline.add_act( act_name=_("Redis-{}-恢复备份").format(params[data_to]), diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py index 32062bd247..b9f9638458 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py @@ -223,8 +223,8 @@ def redis_backend_scale_flow(self): new_slave_ips = [] new_ports = [] for group_info in info["backend_group"]: - new_master_ips.append(group_info["master"]) - new_slave_ips.append(group_info["slave"]) + new_master_ips.append(group_info["master"]["ip"]) + new_slave_ips.append(group_info["slave"]["ip"]) for i in range(0, ins_num): new_ports.append(DEFAULT_REDIS_START_PORT + i) @@ -235,8 +235,8 @@ def redis_backend_scale_flow(self): "start_port": DEFAULT_REDIS_START_PORT, "ports": new_ports, "instance_numb": ins_num, - "spec_id": info["resource_spec"]["id"], - "spec_config": info["resource_spec"], + "spec_id": info["resource_spec"]["backend_group"]["id"], + "spec_config": info["resource_spec"]["backend_group"], } for ip in new_master_ips: params["ip"] = ip From 08135f764c4dc5f0804b96cade01384986a8978b Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Thu, 13 Jul 2023 11:44:50 +0800 Subject: [PATCH 133/476] =?UTF-8?q?refactor(dbm-services):=20apigw/esb=20?= =?UTF-8?q?=E9=89=B4=E6=9D=83=E4=BF=A1=E6=81=AF=E6=94=BE=E5=88=B0header=20?= =?UTF-8?q?close=20#471?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db-resource/internal/svr/bk/job_v3.go | 13 +- dbm-services/common/go-pubpkg/cc.v3/client.go | 51 ++- .../common/go-pubpkg/cc.v3/list_agent_info.go | 11 +- dbm-services/common/go-pubpkg/cc.v3/schema.go | 97 ++--- .../common/go-pubpkg/cc.v3/utils/utils.go | 10 + .../go-pubpkg/cc.v3/utils/utils_test.go | 52 --- .../go-pubpkg/errno/50000_dbpriv_code.go | 8 - dbm-services/common/go-pubpkg/errno/code.go | 58 ++- .../db-partition/cron/cron_basic_func.go | 12 +- dbm-services/mysql/db-partition/errno/code.go | 361 ------------------ .../mysql/db-partition/errno/errno.go | 133 ------- .../mysql/db-partition/handler/handler.go | 2 +- .../db-partition/service/check_partition.go | 2 +- .../service/check_partition_base_func.go | 2 +- .../db-partition/service/db_meta_service.go | 12 +- .../db-partition/service/manage_config.go | 12 +- .../mysql/db-priv/handler/public_key.go | 12 +- 17 files changed, 185 insertions(+), 663 deletions(-) delete mode 100644 dbm-services/common/go-pubpkg/cc.v3/utils/utils_test.go delete mode 100644 dbm-services/mysql/db-partition/errno/code.go delete mode 100644 dbm-services/mysql/db-partition/errno/errno.go diff --git a/dbm-services/common/db-resource/internal/svr/bk/job_v3.go b/dbm-services/common/db-resource/internal/svr/bk/job_v3.go index 424dab9115..4603e0ed88 100644 --- a/dbm-services/common/db-resource/internal/svr/bk/job_v3.go +++ b/dbm-services/common/db-resource/internal/svr/bk/job_v3.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package bk import ( @@ -38,7 +48,6 @@ const ( // FastExecuteScriptParam TODO type FastExecuteScriptParam struct { - cc.BaseSecret BkBizID int `json:"bk_biz_id"` ScriptID int `json:"script_id,omitempty"` ScriptContent string `json:"script_content"` @@ -78,7 +87,6 @@ type TopoNodeList struct { // BatchGetJobInstanceIpLogParam TODO type BatchGetJobInstanceIpLogParam struct { - cc.BaseSecret `json:",inline"` BKBizId int `json:"bk_biz_id"` JobInstanceID int64 `json:"job_instance_id"` StepInstanceID int64 `json:"step_instance_id"` @@ -101,7 +109,6 @@ type ScriptTaskLog struct { // GetJobInstanceStatusParam TODO type GetJobInstanceStatusParam struct { - cc.BaseSecret `json:",inline"` BKBizId int `json:"bk_biz_id"` JobInstanceID int64 `json:"job_instance_id"` // 是否返回每个ip上的任务详情,对应返回结果中的step_ip_result_list。默认值为false。 diff --git a/dbm-services/common/go-pubpkg/cc.v3/client.go b/dbm-services/common/go-pubpkg/cc.v3/client.go index 606d3a83a2..ad4091c9ca 100644 --- a/dbm-services/common/go-pubpkg/cc.v3/client.go +++ b/dbm-services/common/go-pubpkg/cc.v3/client.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package cc import ( @@ -8,6 +18,7 @@ import ( "io" "log" "net/http" + "net/url" "time" "github.com/google/go-querystring/query" @@ -35,23 +46,29 @@ type Client struct { // client for apiservers client *http.Client // Blueking secret - secret Secret + secret Secret + secretHeader string timeout time.Duration } // Secret TODO type Secret struct { - BKAppCode string - BKAppSecret string - BKUsername string + BKAppCode string `json:"bk_app_code"` + BKAppSecret string `json:"bk_app_secret"` + BKUsername string `json:"bk_username"` } // NewClient return new client func NewClient(apiserver string, secret Secret) (*Client, error) { + b, err := json.Marshal(secret) + if err != nil { + return nil, err + } cli := &Client{ - apiserver: apiserver, - secret: secret, + apiserver: apiserver, + secret: secret, + secretHeader: string(b), } tr := &http.Transport{} cli.client = &http.Client{ @@ -66,19 +83,15 @@ func (c *Client) Timeout(duration time.Duration) { } // Do main handler -func (c *Client) Do(method, url string, params interface{}) (*Response, error) { - object, err := Accessor(params) - if err != nil { - return nil, err - } - // set auth... - object.SetSecret(c.secret) - - body, err := json.Marshal(object) +func (c *Client) Do(method, uri string, params interface{}) (result *Response, err error) { + var fullURL string + body, err := json.Marshal(params) if err != nil { return nil, fmt.Errorf("RequestErr - %v", err) } - fullURL := c.apiserver + url + if fullURL, err = url.JoinPath(c.apiserver, uri); err != nil { + return nil, err + } log.Println(fullURL, string(body)) req, err := http.NewRequest(method, fullURL, bytes.NewReader(body)) if err != nil { @@ -91,10 +104,12 @@ func (c *Client) Do(method, url string, params interface{}) (*Response, error) { req = req.WithContext(ctx) } // Set Header + req.Header.Set("X-Bkapi-Accept-Code-Type", "int") + req.Header.Set("X-Bkapi-Authorization", c.secretHeader) if method == "GET" { - q, _ := query.Values(object) + q, _ := query.Values(params) log.Println("encode: ", q.Encode()) req.URL.RawQuery = q.Encode() } @@ -112,7 +127,7 @@ func (c *Client) Do(method, url string, params interface{}) (*Response, error) { if err != nil { return nil, fmt.Errorf("HttpCodeErr - Code: %v, io read all failed %s", resp.StatusCode, err.Error()) } - result := &Response{} + result = &Response{} err = json.Unmarshal(b, result) if err != nil { return nil, err diff --git a/dbm-services/common/go-pubpkg/cc.v3/list_agent_info.go b/dbm-services/common/go-pubpkg/cc.v3/list_agent_info.go index c9df3978f0..838d9d96cf 100644 --- a/dbm-services/common/go-pubpkg/cc.v3/list_agent_info.go +++ b/dbm-services/common/go-pubpkg/cc.v3/list_agent_info.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package cc import ( @@ -22,7 +32,6 @@ func NewListAgentState(client *Client) *ListAgentState { // ListAgentInfoParam TODO type ListAgentInfoParam struct { - BaseSecret `json:",inline"` // 最大支持1000个ID的查询 AgentIdList []string `json:"agent_id_list"` } diff --git a/dbm-services/common/go-pubpkg/cc.v3/schema.go b/dbm-services/common/go-pubpkg/cc.v3/schema.go index 0f0d11bc7e..1c7eaaa61d 100644 --- a/dbm-services/common/go-pubpkg/cc.v3/schema.go +++ b/dbm-services/common/go-pubpkg/cc.v3/schema.go @@ -1,44 +1,19 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package cc import ( "encoding/json" - "fmt" ) -// SecretMeta 定义了SetSecret接口 -// 每个请求CC接口的struct都包括了BaseSecret信息 -// 所以这里在调用时统一设置 -type SecretMeta interface { - SetSecret(secret Secret) -} - -// Accessor 统一处理Secret信息 -func Accessor(obj interface{}) (SecretMeta, error) { - switch t := obj.(type) { - case SecretMeta: - return t, nil - default: - return nil, fmt.Errorf("TypeErr: %v", t) - } -} - -// BaseSecret TODO -// CC接口验证信息 -type BaseSecret struct { - BKAppCode string `json:"bk_app_code" url:"bk_app_code"` - BKAppSecret string `json:"bk_app_secret" url:"bk_app_secret"` - BKUsername string `json:"bk_username" url:"bk_username"` - BKSupplierAccount string `json:"bk_supplier_account" url:"bk_supplier_account"` -} - -// SetSecret 设置Secret信息 -func (s *BaseSecret) SetSecret(secret Secret) { - s.BKAppCode = secret.BKAppCode - s.BKAppSecret = secret.BKAppSecret - s.BKUsername = secret.BKUsername - s.BKSupplierAccount = "tencent" -} - // Host TODO // CC主机属性 // 字段名与CCDeviceInfo的一致,主要方便做映射 @@ -174,7 +149,6 @@ const ( // ResourceWatchParam 资源监听输入参数 type ResourceWatchParam struct { - BaseSecret `json:",inline"` // 事件类型: create(新增)/update(更新)/delete(删除) BKEventTypes []string `json:"bk_event_types"` // 返回的事件中需要返回的字段列表, 不能置空 @@ -207,7 +181,6 @@ type BKEvent struct { // ListHostRelationParam 主机拓扑信息查询输入参数 type ListHostRelationParam struct { - BaseSecret `json:",inline"` // 要查询的主机列表,最大长度为500,若不为空,则page字段不生效 BKHostIds []int `json:"bk_host_ids"` // 要返回的主机字段列表,不能为空 @@ -224,7 +197,6 @@ type ListHostRelationParam struct { // FindHostBizRelationParam 接口主机拓扑信息查询输入参数, BKHostIds的json为单数 type FindHostBizRelationParam struct { - BaseSecret `json:",inline"` // 要查询的主机列表,最大长度为500,若不为空,则page字段不生效 BKHostIds []int `json:"bk_host_id"` // 要返回的主机字段列表,不能为空 @@ -250,7 +222,6 @@ type FindHostBizRelationResp struct { // GetHostBaseInfoParam TODO type GetHostBaseInfoParam struct { - BaseSecret `json:",inline"` BkHostID int `json:"bk_host_id" url:"bk_host_id"` BkSupplierAccount string `json:"bk_supplier_account" url:"bk_supplier_account"` } @@ -297,9 +268,8 @@ type HostRelationInfo struct { // BizSetParam 业务与Set信息查询输入参数 type BizSetParam struct { - BaseSecret `json:",inline"` - BKBizId int `json:"bk_biz_id"` - Fields []string `json:"fields"` + BKBizId int `json:"bk_biz_id"` + Fields []string `json:"fields"` // 分页信息 Page BKPage `json:"page"` } @@ -312,9 +282,8 @@ type BizSetResponse struct { // BizModuleParam 业务与模块信息查询输入参数 type BizModuleParam struct { - BaseSecret `json:",inline"` - BKBizId int `json:"bk_biz_id"` - BKSetId int `json:"bk_set_id"` + BKBizId int `json:"bk_biz_id"` + BKSetId int `json:"bk_set_id"` // 模块属性列表,控制返回结果的模块信息里有哪些字段 Fields []string `json:"fields"` // 分页信息 @@ -397,8 +366,7 @@ type Biz struct { // BizParam 查询业务入参 type BizParam struct { - BaseSecret `json:",inline"` - Fields []string `json:"fields"` + Fields []string `json:"fields"` // 分页信息 Page BKPage `json:"page"` Condition map[string]interface{} `json:"condition"` @@ -436,7 +404,6 @@ type HostOri struct { // ListBizHostsParam TODO type ListBizHostsParam struct { - BaseSecret `json:",inline"` Page BKPage `json:"page"` BkBizId int `json:"bk_biz_id"` BkSetIds []int `json:"bk_set_ids"` @@ -458,14 +425,12 @@ type BizResponse struct { // TransferHostParam 转移主机模块输入参数 type TransferHostParam struct { - BaseSecret `json:",inline"` - From BKFrom `json:"bk_from"` - To BKTo `json:"bk_to"` + From BKFrom `json:"bk_from"` + To BKTo `json:"bk_to"` } // TransferHostModuleParam 同业务下转移模块,支持转移到多个模块 type TransferHostModuleParam struct { - BaseSecret `json:",inline"` BkBizID int `json:"bk_biz_id"` BkHostID []int `json:"bk_host_id"` BkModuleID []int `json:"bk_module_id"` @@ -474,7 +439,6 @@ type TransferHostModuleParam struct { // CloneHostPropertyParam 克隆主机属性输入参数 type CloneHostPropertyParam struct { - BaseSecret `json:",inline"` BkBizId int `json:"bk_biz_id"` BkOrgHostId int `json:"bk_org_id"` BkDstHostId int `json:"bk_dst_id"` @@ -482,7 +446,6 @@ type CloneHostPropertyParam struct { // CloneHostSvcInsParam 克隆实例信息输入参数 type CloneHostSvcInsParam struct { - BaseSecret `json:",inline"` BkBizId int `json:"bk_biz_id"` BkModuleIds []int `json:"bk_module_ids"` SrcHostId int `json:"src_host_id"` @@ -511,7 +474,6 @@ type BKTo struct { // UpdateHostParam 修改主机属性输入参数(例如主备负责人) type UpdateHostParam struct { - BaseSecret `json:",inline"` // 主机IP InnerIPs []string `json:"-"` // 主机固定号 @@ -524,7 +486,6 @@ type UpdateHostParam struct { // HostsWithoutBizListParam 根据过滤条件查询主机信息 type HostsWithoutBizListParam struct { - BaseSecret `json:",inline"` // 查询条件 HostPropertyFilter HostPropertyFilter `json:"host_property_filter"` // 分页 @@ -563,8 +524,7 @@ const ( // BizInternalModulesParam 查询业务的内置模块入参 type BizInternalModulesParam struct { - BaseSecret `json:",inline" url:",inline"` - BKBizId int `json:"bk_biz_id" url:"bk_biz_id"` + BKBizId int `json:"bk_biz_id" url:"bk_biz_id"` } // BizInternalModuleResponse 查询业务的内置模块返回值 @@ -581,8 +541,7 @@ type BizInternalModuleResponse struct { // BizTopoTreeParam 查询业务拓扑信息入参 type BizTopoTreeParam struct { - BaseSecret `json:",inline" url:",inline"` - BKBizId int `json:"bk_biz_id" url:"bk_biz_id"` + BKBizId int `json:"bk_biz_id" url:"bk_biz_id"` } // TopoTreeNode TODO @@ -599,13 +558,11 @@ type TopoTreeNode struct { // BizLocationParam TODO type BizLocationParam struct { - BaseSecret `json:",inline" url:",inline"` - BKBizIds []int `json:"bk_biz_ids" url:"bk_biz_ids"` + BKBizIds []int `json:"bk_biz_ids" url:"bk_biz_ids"` } // HostLocationParam TODO type HostLocationParam struct { - BaseSecret `json:",inline" url:",inline"` BkHostList []BkHostList `json:"bk_host_list"` } @@ -646,7 +603,6 @@ type FindHostBizRelationResponse struct { // DeptParam 部门信息 type DeptParam struct { - BaseSecret `json:",inline"` // 部门ID DeptId string `json:"dept_id"` } @@ -663,8 +619,7 @@ type DeptResponse struct { // BizCreateSetParam TODO type BizCreateSetParam struct { - BaseSecret `json:",inline"` - BkBizID int `json:"bk_biz_id"` + BkBizID int `json:"bk_biz_id"` Data struct { BkParentID int `json:"bk_parent_id"` @@ -675,7 +630,6 @@ type BizCreateSetParam struct { // BizDeleteSetParam TODO type BizDeleteSetParam struct { - BaseSecret `json:",inline"` BkBizID int `json:"bk_biz_id"` BkBizSetID int `json:"bk_set_id"` } @@ -694,8 +648,7 @@ type BizSensitive struct { // BizSensitiveParam 查询业务敏感信息入参 type BizSensitiveParam struct { - BaseSecret `json:",inline"` - Fields []string `json:"fields"` + Fields []string `json:"fields"` // 分页信息 Page BKPage `json:"page"` BkBizIds []int `json:"bk_biz_ids"` @@ -709,14 +662,12 @@ type BizSensitiveResponse struct { // SyncHostInfoFromCmpyParam 同步公司cmdb更新信息入参 type SyncHostInfoFromCmpyParam struct { - BaseSecret `json:",inline"` - BkHostIds []int `json:"bk_host_ids"` + BkHostIds []int `json:"bk_host_ids"` } // AddHostInfoFromCmpyParam 同步公司cmdb新增信息入参 type AddHostInfoFromCmpyParam struct { - BaseSecret `json:",inline"` - SvrIds []int `json:"svr_ids"` + SvrIds []int `json:"svr_ids"` } // CreateModuleParam 参数 diff --git a/dbm-services/common/go-pubpkg/cc.v3/utils/utils.go b/dbm-services/common/go-pubpkg/cc.v3/utils/utils.go index 8e95215f1a..00414f8001 100644 --- a/dbm-services/common/go-pubpkg/cc.v3/utils/utils.go +++ b/dbm-services/common/go-pubpkg/cc.v3/utils/utils.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package utils TODO package utils diff --git a/dbm-services/common/go-pubpkg/cc.v3/utils/utils_test.go b/dbm-services/common/go-pubpkg/cc.v3/utils/utils_test.go deleted file mode 100644 index 1357fe10f2..0000000000 --- a/dbm-services/common/go-pubpkg/cc.v3/utils/utils_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package utils - -import ( - "fmt" - "reflect" - "testing" - - "github.com/stretchr/testify/assert" -) - -type testObject struct { - c1 string `json:"c1,omitempty"` - c2 int `json:"c2"` - c3 *c3 `json:"c3,omitempty"` - c4 map[string]string `json:"c4"` - c5 []int `json:"c5"` -} - -type c3 struct { - x1 string `json:"x1"` - x2 []x2 `json:"x2,omitempty"` - x3 []string `json:"x3"` -} - -type x2 struct { - y1 string `json:"y1"` - y2 map[string]int `json:"y2,omitempty"` - y3 *int `json:"y3"` -} - -func TestGetStructTagName(t *testing.T) { - cases := []struct { - name string - object interface{} - expectedResult []string - }{ - { - name: "ptr", - object: &testObject{}, - expectedResult: []string{"c1", "c2", "x1", "y1", "y2", "y3", "x2", "x3", "c3", "c4", "c5"}, - }, - { - name: "struct", - object: testObject{}, - expectedResult: []string{"c1", "c2", "x1", "y1", "y2", "y3", "x2", "x3", "c3", "c4", "c5"}, - }, - } - for _, tc := range cases { - fields := GetStructTagName(reflect.TypeOf(tc.object)) - assert.Equal(t, tc.expectedResult, fields, fmt.Sprintf("case: %+v", tc.name)) - } -} diff --git a/dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go b/dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go index 2f39b5f23c..f8f54d3786 100644 --- a/dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go +++ b/dbm-services/common/go-pubpkg/errno/50000_dbpriv_code.go @@ -64,25 +64,17 @@ var ( // GenerateEncryptedPasswordErr TODO GenerateEncryptedPasswordErr = Errno{Code: 51007, Message: "Generate Encrypted Password Err", CNMessage: "创建账号,生成加密的密码时发生错误"} - // BkBizIdIsEmpty TODO - BkBizIdIsEmpty = Errno{Code: 51012, Message: "bk_biz_id can't be empty", CNMessage: "bk_biz_id不能为空"} // ClonePrivilegesFail TODO ClonePrivilegesFail = Errno{Code: 51013, Message: "Clone privileges fail", CNMessage: "克隆权限失败"} // ClonePrivilegesCheckFail TODO ClonePrivilegesCheckFail = Errno{Code: 51014, Message: "Clone privileges check fail", CNMessage: "克隆权限检查失败"} // NoPrivilegesNothingToDo TODO NoPrivilegesNothingToDo = Errno{Code: 51015, Message: "no privileges,nothing to do", CNMessage: "没有权限需要克隆"} - // DomainNotExists TODO - DomainNotExists = Errno{Code: 51016, Message: "domain not exists", CNMessage: "域名不存在"} // IpPortFormatError TODO IpPortFormatError = Errno{Code: 51017, Message: "format not in 'ip:port' format", CNMessage: "格式不是ip:port的格式"} - // InstanceNotExists TODO - InstanceNotExists = Errno{Code: 51018, Message: "instance not exists", CNMessage: "实例不存在"} // CloudIdRequired TODO CloudIdRequired = Errno{Code: 51019, Message: "bk_cloud_id is required", CNMessage: "bk_cloud_id不能为空"} - // NotSupportedClusterType TODO - NotSupportedClusterType = Errno{Code: 51020, Message: "not supported cluster type", CNMessage: "不支持此集群类型"} // ClusterTypeIsEmpty TODO ClusterTypeIsEmpty = Errno{Code: 51021, Message: "Cluster type can't be empty", CNMessage: "cluster type不能为空"} ) diff --git a/dbm-services/common/go-pubpkg/errno/code.go b/dbm-services/common/go-pubpkg/errno/code.go index 9ba7e02b06..d4db36dd7a 100644 --- a/dbm-services/common/go-pubpkg/errno/code.go +++ b/dbm-services/common/go-pubpkg/errno/code.go @@ -12,8 +12,6 @@ package errno var ( // OK TODO - // Common errors - // OK = Errno{Code: 0, Message: ""} OK = Errno{Code: 0, Message: "", CNMessage: ""} // InternalServerError TODO @@ -53,16 +51,12 @@ var ( ErrorJsonToMap = Errno{Code: 10114, Message: "Error occured while converting json to Map.", CNMessage: "Json 转为 Map 出现错误!"} - // [数据库类型错误] 10200 开始 - // ErrDBQuery TODO ErrDBQuery = Errno{Code: 10201, Message: "DB Query error.", CNMessage: "查询DB错误!"} // ErrModelFunction TODO ErrModelFunction = Err{Errno: Errno{Code: 10202, Message: "Error occured while invoking model function.", CNMessage: "调用 DB model 方法发生错误!"}, Err: nil} - // [用户权限类错误] 10300 开始 - // ErrDoNotHavePrivs TODO ErrDoNotHavePrivs = Errno{Code: 10301, Message: "User don't have Privs.", CNMessage: "此用户没有权限"} // ErrUserIsEmpty TODO @@ -75,6 +69,56 @@ var ( RepeatedIpExistSystem = Errno{Code: 10070, CNMessage: "存在重复IP", Message: "there is a duplicate ip"} // ErrInvokeAPI TODO - // call other service error ErrInvokeAPI = Errno{Code: 15000, Message: "Error occurred while invoking API", CNMessage: "调用 API 发生错误!"} + + // ErrRecordNotFound TODO + ErrRecordNotFound = Errno{Code: 404, Message: "There is no records in db.", CNMessage: "数据库未找到对应的记录!"} + + // ErrValidation TODO + ErrValidation = Errno{Code: 20001, Message: "Validation failed."} + // ErrDatabase TODO + ErrDatabase = Errno{Code: 20002, Message: "Database error."} + // ErrToken TODO + ErrToken = Errno{Code: 20003, Message: "Error occurred while signing the JSON web token."} + + // ErrEncrypt TODO + // user errors + ErrEncrypt = Errno{Code: 20101, Message: "Error occurred while encrypting the user password."} + // ErrUserNotFound TODO + ErrUserNotFound = Errno{Code: 20102, Message: "The user was not found."} + // ErrTokenInvalid TODO + ErrTokenInvalid = Errno{Code: 20103, Message: "The token was invalid."} + // ErrPasswordIncorrect TODO + ErrPasswordIncorrect = Errno{Code: 20104, Message: "The password was incorrect."} + + // BkBizIdIsEmpty TODO + BkBizIdIsEmpty = Errno{Code: 51012, Message: "bk_biz_id can't be empty", CNMessage: "bk_biz_id不能为空"} + // InstanceNotExists TODO + InstanceNotExists = Errno{Code: 51018, Message: "instance not exists", CNMessage: "实例不存在"} + // NoTableMatched TODO + NoTableMatched = Errno{Code: 51019, Message: "no table matched", CNMessage: "找不到匹配的表"} + // ClusterIdIsEmpty TODO + ClusterIdIsEmpty = Errno{Code: 51020, Message: "cluster_id can't be empty", + CNMessage: "cluster_id不能为空"} + // CheckPartitionFailed TODO + CheckPartitionFailed = Errno{Code: 51021, Message: "partition check failed", CNMessage: "分区检查失败"} + // PartitionConfigNotExisted TODO + PartitionConfigNotExisted = Errno{Code: 51022, Message: "Partition config not existed ", CNMessage: "分区配置不存在"} + // PartOfPartitionConfigsNotExisted TODO + PartOfPartitionConfigsNotExisted = Errno{Code: 51023, Message: "part of artition configs not existed ", + CNMessage: "部分分区配置不存在"} + // NotSupportedClusterType TODO + NotSupportedClusterType = Errno{Code: 51024, Message: "this instance type is not supportted by partition", + CNMessage: "不支持的实例类型"} + // ConfigIdIsEmpty TODO + ConfigIdIsEmpty = Errno{Code: 51025, Message: "partition config id can't be empty", + CNMessage: "partition config id 不能为空"} + // GetPartitionSqlFail TODO + GetPartitionSqlFail = Errno{Code: 51027, Message: "get partition sql failed", CNMessage: "获取分区语句失败"} + // ExecutePartitionFail TODO + ExecutePartitionFail = Errno{Code: 51028, Message: "execute partition failed", CNMessage: "执行分区失败"} + // NothingToDo TODO + NothingToDo = Errno{Code: 51029, Message: "nothing to do", CNMessage: "没有需要执行的操作"} + // DomainNotExists TODO + DomainNotExists = Errno{Code: 51030, Message: "domain not exists", CNMessage: "域名不存在"} ) diff --git a/dbm-services/mysql/db-partition/cron/cron_basic_func.go b/dbm-services/mysql/db-partition/cron/cron_basic_func.go index baa82bbc05..0d41fb9c04 100644 --- a/dbm-services/mysql/db-partition/cron/cron_basic_func.go +++ b/dbm-services/mysql/db-partition/cron/cron_basic_func.go @@ -1,9 +1,19 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package cron import ( "fmt" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/model" "dbm-services/mysql/db-partition/monitor" "dbm-services/mysql/db-partition/service" diff --git a/dbm-services/mysql/db-partition/errno/code.go b/dbm-services/mysql/db-partition/errno/code.go deleted file mode 100644 index abaa19d931..0000000000 --- a/dbm-services/mysql/db-partition/errno/code.go +++ /dev/null @@ -1,361 +0,0 @@ -package errno - -var ( - // OK TODO - // Common errors - // OK = Errno{Code: 0, Message: ""} - OK = Errno{Code: 0, Message: "", CNMessage: ""} - // SaveOK TODO - SaveOK = Errno{Code: 0, Message: "Bill save success!", CNMessage: "单据保存成功!"} - // CommitOK TODO - CommitOK = Errno{Code: 0, Message: "Bill commit success!", CNMessage: "单据提交成功!"} - // AuditOK TODO - AuditOK = Errno{Code: 0, Message: "Bill audit success!", CNMessage: "单据审核成功!"} - // RollbackOK TODO - RollbackOK = Errno{Code: 0, Message: "Bill rollback success!", CNMessage: "单据驳回成功!"} - // StopOK TODO - StopOK = Errno{Code: 0, Message: "Bill stop success!", CNMessage: "单据终止成功!"} - // ExecuteOK TODO - ExecuteOK = Errno{Code: 0, Message: "Bill execute success!", CNMessage: "单据执行成功!"} - // CommonOK TODO - CommonOK = Errno{Code: 0, Message: "", CNMessage: "通用成功描述"} - // JobUpdateOK TODO - JobUpdateOK = Errno{Code: 0, Message: "Job update success!", CNMessage: "Job 更新成功!"} - // SubjobUpdateOK TODO - SubjobUpdateOK = Errno{Code: 0, Message: "Subjob update success!", CNMessage: "Subjob 更新成功!"} - - // ErrRecordNotFound TODO - ErrRecordNotFound = Errno{Code: 404, Message: "There is no records in db.", CNMessage: "数据库未找到对应的记录!"} - - // CommonErr TODO - CommonErr = Errno{Code: 10000, Message: "common error!", CNMessage: "通用错误!"} - - // InternalServerError TODO - InternalServerError = Errno{Code: 10001, Message: "Internal server error", CNMessage: "服务器内部错误。"} - // ErrBind TODO - ErrBind = Errno{Code: 10002, Message: "Error occurred while binding the request body to the struct.", - CNMessage: "参数处理发生错误。"} - // ErrString2Int TODO - ErrString2Int = Errno{Code: 10010, Message: "Error occurred while convert string to int.", - CNMessage: "string 转化为 int 出错!"} - // ErrorJsonToMap TODO - ErrorJsonToMap = Errno{Code: 10030, Message: "Error occured while converting json to Map.", - CNMessage: "Json 转为 Map 出现错误!"} - // ErrorUIDBeZero TODO - ErrorUIDBeZero = Errno{Code: 10035, Message: "uid can not be 0!", CNMessage: "uid 不能为 0.!"} - // ErrRequestParam TODO - ErrRequestParam = Errno{Code: 10036, Message: "request parameter error!", CNMessage: "请求参数错误!"} - - // ErrTypeAssertion TODO - ErrTypeAssertion = Errno{Code: 10040, Message: "Error occurred while doing type assertion."} - // ErrParameterRequired TODO - ErrParameterRequired = Errno{Code: 10050, Message: "Input paramter required"} - // StartBiggerThanEndTime TODO - StartBiggerThanEndTime = Errno{Code: 10060, Message: "Start time is bigger than end time."} - - // ErrValidation TODO - ErrValidation = Errno{Code: 20001, Message: "Validation failed."} - // ErrDatabase TODO - ErrDatabase = Errno{Code: 20002, Message: "Database error."} - // ErrToken TODO - ErrToken = Errno{Code: 20003, Message: "Error occurred while signing the JSON web token."} - - // ErrEncrypt TODO - // user errors - ErrEncrypt = Errno{Code: 20101, Message: "Error occurred while encrypting the user password."} - // ErrUserNotFound TODO - ErrUserNotFound = Errno{Code: 20102, Message: "The user was not found."} - // ErrTokenInvalid TODO - ErrTokenInvalid = Errno{Code: 20103, Message: "The token was invalid."} - // ErrPasswordIncorrect TODO - ErrPasswordIncorrect = Errno{Code: 20104, Message: "The password was incorrect."} - // ErrDoNotHavePrivs TODO - ErrDoNotHavePrivs = Errno{Code: 20106, Message: "User don't have Privs."} - // ErrUserIsEmpty TODO - ErrUserIsEmpty = Errno{Code: 20110, Message: "User can't be empty.", CNMessage: "user 不能为空!"} - // ErrAppNameIsEmpty TODO - ErrAppNameIsEmpty = Errno{Code: 20115, Message: "App name can't be empty.", CNMessage: "业务名不能为空!"} - - // ErrCommonExecute TODO - ErrCommonExecute = Errno{Code: 20200, Message: "Error occured while invoking execute method.", - CNMessage: "调用 execute 出错!"} - - // ErrUserHaveNoProjectPriv TODO - ErrUserHaveNoProjectPriv = Errno{Code: 30000, Message: "User don't have project priv.", CNMessage: "没有 project 权限!"} - - // ErrGcsBillNotFound TODO - // gcsbill errors - ErrGcsBillNotFound = Errno{Code: 40000, Message: "Gcs bill was not found.", CNMessage: "单据不存在!"} - // ErrGCSBillTypeEmpty TODO - ErrGCSBillTypeEmpty = Errno{Code: 40001, Message: "Gcs bill type can not be empty.", CNMessage: "单据类型不能为空!"} - // InvalidGCSBillType TODO - InvalidGCSBillType = Errno{Code: 40002, Message: "Invalid Gcs bill type.", CNMessage: "无效的 GCS 单据类型!"} - // InvalidAuditLevel TODO - InvalidAuditLevel = Errno{Code: 40003, Message: "Invalid Bill Audit level.", CNMessage: "无效的单据审核级别!"} - - // CannotGetBillStatus TODO - CannotGetBillStatus = Errno{Code: 40004, Message: "Cann't get bill status.", CNMessage: `无法获取单据状态`} - // ErrGCSBillnotAuditable TODO - ErrGCSBillnotAuditable = Errno{Code: 40005, Message: "Current GCS bill is not in audit status now.", - CNMessage: `当前单据不在“待审核”状态!`} - // ErrGCSBillNotInExecute TODO - ErrGCSBillNotInExecute = Errno{Code: 40006, Message: "Bill is not in execute status.", CNMessage: `当前单据不在“待执行”状态!`} - // ErrGCSBillAudit TODO - ErrGCSBillAudit = Errno{Code: 40007, Message: "Audit bill error.", CNMessage: `审核单据出错。`} - - // ErrNotHaveBillCommitPriv TODO - ErrNotHaveBillCommitPriv = Errno{Code: 40008, Message: "user don't have bill commit priv", CNMessage: "用户没有提单权限!"} - - // ErrGetGCSDoneBills TODO - ErrGetGCSDoneBills = Errno{Code: 40009, Message: "Error occured while getting done bills.", - CNMessage: "获取个人已办事项出错!"} - // ErrBillAppIsEmpty TODO - ErrBillAppIsEmpty = Errno{Code: 40010, Message: "Gcs bill app can not be empty.", CNMessage: "单据的业务名不能为空!"} - // ErrGCSBillNoExecutePriv TODO - ErrGCSBillNoExecutePriv = Errno{Code: 40011, Message: "Only apply user and follower can execute the bill!", - CNMessage: "只有申请人或者关注人可以执行单据!"} - // ErrGetGCSBillModel TODO - ErrGetGCSBillModel = Errno{Code: 40012, Message: "Error occured while getting bill info", - CNMessage: "获取 Bill 详情出错"} - // ErrGetGCSBillTypes TODO - ErrGetGCSBillTypes = Errno{Code: 40014, Message: "Error occured while getting bill types", - CNMessage: "获取所有单据类型失败!"} - // ErrGCSBillCommit TODO - ErrGCSBillCommit = Err{Errno: Errno{Code: 40015, Message: "The bill can not be committed repeatly!", - CNMessage: "单据不能被重复提交!"}} - // ErrInvokeBillCommit TODO - ErrInvokeBillCommit = Err{Errno: Errno{Code: 40016, Message: "Error occured while committing gcs bills", - CNMessage: "单据提交时发生错误!"}} - // ErrInvokeBillExecute TODO - ErrInvokeBillExecute = Err{Errno: Errno{Code: 40017, Message: "Error occured while executing gcs bills", - CNMessage: "单据执行时发生错误!"}} - - // ErrGCSBillnotRollback TODO - ErrGCSBillnotRollback = Errno{Code: 40019, Message: "Bill is not auditable ,it can not be rollback.", - CNMessage: `非“待审核”单据不能被驳回!`} - // ErrGetGCSBills TODO - ErrGetGCSBills = Errno{Code: 40020, Message: "Error occured while getting gcs bills", CNMessage: "获取单据失败!"} - // ErrCloneUnfinishedBills TODO - ErrCloneUnfinishedBills = Errno{Code: 40022, Message: "Error occured while cloning unfinished gcs bills", - CNMessage: "不能克隆没有结束的单据!"} - // ErrFinishedBills TODO - ErrFinishedBills = Errno{Code: 40027, Message: "Error occured while finishing gcs bills", - CNMessage: `设置单据为“完成”状态时失败!`} - // ErrBillHaveTerminated TODO - ErrBillHaveTerminated = Errno{Code: 40028, Message: "Bill have terminated!", CNMessage: `单据已“终止”!`} - - // ErrNoStopPriv TODO - ErrNoStopPriv = Errno{Code: 40037, Message: "Don't have stop bill priv!", CNMessage: `用户没有“终止”单据权限!`} - // ErrGCSBillSave TODO - ErrGCSBillSave = Err{Errno: Errno{Code: 40042, Message: "Error occured while saving gcs bills!", - CNMessage: "单据保存失败!"}} - // ErrBillIsNotUncommit TODO - ErrBillIsNotUncommit = Err{Errno: Errno{Code: 40043, - Message: "Bill phase is not v_uncommit before committing the bill!", CNMessage: "单据提交之前,单据状态不是\"未提交\"!"}} - // ErrBillPreCommit TODO - ErrBillPreCommit = Err{Errno: Errno{Code: 40046, Message: "Error occured while invoking bill pre commit api:", - CNMessage: "调用单据的 PreCommit API 失败:"}} - // ErrBillAfterExecute TODO - ErrBillAfterExecute = Err{Errno: Errno{Code: 40050, Message: "Error occured while invoking after execute api!", - CNMessage: "调用单据的 AfterExecute API 失败!"}} - - // ErrTbBillInfoToBill TODO - ErrTbBillInfoToBill = Err{Errno: Errno{Code: 40055, Message: "Error occured while transfer TbBillInfo to Bill!", - CNMessage: "转换 Bill Model 失败"}} - - // ErrCreateGCSJob TODO - // job errors - ErrCreateGCSJob = Errno{Code: 40100, Message: "Error occured while creating the gcs job.", - CNMessage: "创建 GCS Job 失败!"} - // ErrGetJobQueue TODO - ErrGetJobQueue = Errno{Code: 40101, Message: "Error occured while get the gcs job queue.", - CNMessage: "获取 job 失败 !"} - // ErrGetJobQueueNotFound TODO - ErrGetJobQueueNotFound = Errno{Code: 40102, Message: "Job Queue Not Found.", CNMessage: "Job 不存在!"} - // ErrDeleteJobQueue TODO - ErrDeleteJobQueue = Errno{Code: 40103, Message: "Error occured while set the jobQueue to be deleted.", - CNMessage: "删除 Job 失败!"} - // ErrJobIDConvert2Int TODO - ErrJobIDConvert2Int = Errno{Code: 40104, Message: "Error occured while converting the jobID to int.", - CNMessage: "jobID 转换为int 出错!"} - // ErrSubjobIDConvert2Int TODO - ErrSubjobIDConvert2Int = Errno{Code: 40105, Message: "Error occured while converting the subjob_id to int.", - CNMessage: "subjobID 转换为int 出错!"} - - // ErrPutJobQueueParam TODO - ErrPutJobQueueParam = Errno{Code: 40106, Message: " param errors while puting a new JobQueue.", - CNMessage: "创建 Job 时参数错误!"} - // ErrJobQueueInputParam TODO - ErrJobQueueInputParam = Errno{Code: 40107, - Message: "Some parameters is required in EnJobQueue: app,name,input,tag_id", - CNMessage: "创建Job 时缺少下列参数:[app,name,input,tag_id]!"} - // ErrJobQueueV1InputParam TODO - ErrJobQueueV1InputParam = Errno{Code: 40107, - Message: "Some parameters is required in puting JobQueue: [app,name,distributions,payload,user]", - CNMessage: "创建/修改 Job 时缺少下列参数:[app,name,distributions,payload,user]!"} - // ErrJobQueueDistribution TODO - ErrJobQueueDistribution = Errno{Code: 40108, Message: "JobQueue distributions format is wrong.", - CNMessage: "创建 JobQueue 时 distributions 格式不正确!"} - // ErrCheckJobQueue TODO - ErrCheckJobQueue = Errno{Code: 40109, Message: "Error occured while checking JobQueue.", - CNMessage: "检查 JobQueue 出错!"} - // ErrJoqQueueIsNil TODO - ErrJoqQueueIsNil = Errno{Code: 40110, Message: "JobQueue is Nil", CNMessage: "返回的Job 内容为空!"} - // ErrCloneJoqQueues TODO - ErrCloneJoqQueues = Errno{Code: 40113, Message: "Error occured while cloning jobQueues", - CNMessage: "克隆 jobQueues 出错!"} - - // JobResultSuccess TODO - JobResultSuccess = Errno{Code: 0, Message: "success", CNMessage: "success"} - // JobResultRunning TODO - JobResultRunning = Errno{Code: 40114, Message: "running", CNMessage: "running"} - // JobResultFailed TODO - JobResultFailed = Errno{Code: 40115, Message: "fail", CNMessage: "fail"} - // JobResultOthers TODO - JobResultOthers = Errno{Code: 40116, Message: "other job status", CNMessage: "other job status"} - - // ErrGetJobFeedbacks TODO - // JobFeedback - ErrGetJobFeedbacks = Errno{Code: 40210, Message: "Error occured while getting the gcs job feedback.", - CNMessage: "获取 job feedback 信息失败!"} - // ErrCreateGCSJobFeedback TODO - ErrCreateGCSJobFeedback = Errno{Code: 40215, Message: "Error occured while creating the gcs jobFeedback.", - CNMessage: "创建 GCS jobFeedback 失败!"} - - // InvalidJobIDorSubjobID TODO - InvalidJobIDorSubjobID = Errno{Code: 40220, Message: "Invalid jobID or subJobID while getting the gcs job feedback.", - CNMessage: "jobID or subJobID 无效!"} - - // ErrorJobNameBeEmpty TODO - // JobDef errors - ErrorJobNameBeEmpty = Errno{Code: 40300, Message: "JobName can not be empty.", CNMessage: "JobName 不能为空!"} - // ErrorGetJobDef TODO - ErrorGetJobDef = Errno{Code: 40302, Message: "Error occured while getting the gcs job_def", - CNMessage: "获取 job_def 出现错误!"} - - // ErrorGetJobBlob TODO - // JobBlob errors - ErrorGetJobBlob = Errno{Code: 40302, Message: "Error occured while getting the gcs job_blob", - CNMessage: "获取 job_blob 出现错误!"} - - // ErrorGetSubJobQueue TODO - // subjob errors - ErrorGetSubJobQueue = Errno{Code: 40800, Message: "Error occured while getting the gcs subjob ", - CNMessage: "获取 subjob 出现错误!"} - // ErrCreateSubJobQueue TODO - ErrCreateSubJobQueue = Errno{Code: 40801, Message: "Error occured while creating the gcs subjobQueue.", - CNMessage: "创建 GCS subjobQueue 失败!"} - // ErrUpdateSubJobQueue TODO - ErrUpdateSubJobQueue = Errno{Code: 40802, Message: "Error occured while updating the gcs subjobQueue.", - CNMessage: "更新 GCS subjobQueue 失败!"} - - // SubJobUIDRequied TODO - SubJobUIDRequied = Errno{Code: 40804, Message: "Subjob uid is required!", CNMessage: "Subjob uid 是必填项.!"} - // ErrorUIDMustBeInt TODO - ErrorUIDMustBeInt = Errno{Code: 40808, Message: "Subjob uid must be int!", CNMessage: "Subjob uid 必须是 int 类型.!"} - // ErrSubjobQueueInputParam TODO - ErrSubjobQueueInputParam = Errno{Code: 40812, - Message: "Some parameters [JobID,Username,JobName,AtomjobList,JobInput] are not meet the demands in saving SubjobQueue", CNMessage: "保存 SubjobQueue 时缺少下列参数:[JobID,Username,JobName,AtomjobList,JobInput]!"} - // ErrJobFeedbackInputParam TODO - ErrJobFeedbackInputParam = Errno{Code: 40815, - Message: "Some parameters are not meet the demands in saving JobFeedback", CNMessage: "保存 JobFeedback 时参数不满足要求。"} - // ErrGetGCSApps TODO - // gcs app errors - ErrGetGCSApps = Errno{Code: 40900, Message: "Error occured while getting gcs apps", CNMessage: "获取 GCS App 出现错误!"} - // ErrGetCCApps TODO - ErrGetCCApps = Errno{Code: 40902, Message: "Error occured while getting cc apps", CNMessage: "获取 App 出现错误!"} - // ErrGetProjects TODO - ErrGetProjects = Errno{Code: 40905, Message: "Error occured while getting projects", CNMessage: "获取 projects 出现错误!"} - - // ErrDBTransaction TODO - // model operation errors - ErrDBTransaction = Errno{Code: 50200, Message: "DB Transaction error.", CNMessage: "DB 事务发生错误!"} - // ErrModelFunction TODO - ErrModelFunction = Err{Errno: Errno{Code: 50201, Message: "Error occured while invoking model function.", - CNMessage: "调用 DB model 方法发生错误!"}, Err: nil} - - // ErrSaveFlowAuditLog TODO - ErrSaveFlowAuditLog = Errno{Code: 50203, Message: "Error occured while saving Flow Audit Log.", - CNMessage: "存储单据审核日志记录出错!"} - - // ErrGetJSONArray TODO - // data handle error - ErrGetJSONArray = Errno{Code: 50300, Message: "Get simplejson Array error.", CNMessage: ""} - // ErrConvert2Map TODO - ErrConvert2Map = Errno{Code: 50301, Message: "Error occurred while converting the data to Map.", - CNMessage: "Error occurred while converting the data to Map."} - // ErrJSONMarshal TODO - ErrJSONMarshal = Errno{Code: 50302, Message: "Error occurred while marshaling the data to JSON.", - CNMessage: "Error occurred while marshaling the data to JSON."} - // ErrReadEntity TODO - ErrReadEntity = Errno{Code: 50303, Message: "Error occurred while parsing the request parameter.", - CNMessage: "Error occurred while parsing the request parameter."} - // ErrJSONUnmarshal TODO - ErrJSONUnmarshal = Errno{Code: 50304, Message: "Error occurred while Unmarshaling the JSON to data model.", - CNMessage: "Error occurred while Unmarshaling the JSON to data model."} - // ErrBytesToMap TODO - ErrBytesToMap = Errno{Code: 50307, Message: "Error occurred while converting bytes to map.", - CNMessage: "Error occurred while converting bytes to map."} - - // ErrUserIsNotDBA TODO - // user login and permission errors - ErrUserIsNotDBA = Errno{Code: 50500, Message: "User is not dba."} - // ErrNoSaveAndCommitPriv TODO - ErrNoSaveAndCommitPriv = Errno{Code: 50502, - Message: "User don't have gcs bill save and commit privs in this app.", CNMessage: "用户在当前 APP 上没有单据的保存和提交权限!"} - // ErrNoBillAduitPriv TODO - ErrNoBillAduitPriv = Errno{Code: 50504, Message: "User don't have gcs audit privs in this app.", - CNMessage: "用户在当前 APP 上没有单据的审核权限!"} - // ErrUserNotHaveBillRollbackPriv TODO - ErrUserNotHaveBillRollbackPriv = Errno{Code: 50506, Message: "User don't have gcs rollback privs in this app.", - CNMessage: "用户在当前 APP 上没有单据的驳回权限!"} - // ErrUserHasNoPermission TODO - ErrUserHasNoPermission = Errno{Code: 50508, Message: "User has no permission.", CNMessage: "当前用户没有权限!"} - // ErrUserNotHaveBillClonePriv TODO - ErrUserNotHaveBillClonePriv = Errno{Code: 50510, Message: "User don't have gcs bill clone privs in this app.", - CNMessage: "用户没有当前单据的克隆权限!"} - // ErrViewAppPriv TODO - ErrViewAppPriv = Errno{Code: 50515, Message: "User have no priv to view this app!", - CNMessage: "用户没有查看当前 APP 的权限!"} - - // ErrInvokeAPI TODO - ErrInvokeAPI = Errno{Code: 50601, Message: "Error occurred while invoking API", CNMessage: "调用 API 发生错误!"} - - // ErrSnedRTX TODO - // alarm errors - ErrSnedRTX = Errno{Code: 50800, Message: "Error occurred while sending RTX message to user.", - CNMessage: "发送 RTX 消息出现错误!"} - - // BkBizIdIsEmpty TODO - BkBizIdIsEmpty = Errno{Code: 51012, Message: "bk_biz_id can't be empty", CNMessage: "bk_biz_id不能为空"} - // InstanceNotExists TODO - InstanceNotExists = Errno{Code: 51018, Message: "instance not exists", CNMessage: "实例不存在"} - // NoTableMatched TODO - NoTableMatched = Errno{Code: 51019, Message: "no table matched", CNMessage: "找不到匹配的表"} - // ClusterIdIsEmpty TODO - ClusterIdIsEmpty = Errno{Code: 51020, Message: "cluster_id can't be empty", - CNMessage: "cluster_id不能为空"} - // CheckPartitionFailed TODO - CheckPartitionFailed = Errno{Code: 51021, Message: "partition check failed", CNMessage: "分区检查失败"} - // PartitionConfigNotExisted TODO - PartitionConfigNotExisted = Errno{Code: 51022, Message: "Partition config not existed ", CNMessage: "分区配置不存在"} - // PartOfPartitionConfigsNotExisted TODO - PartOfPartitionConfigsNotExisted = Errno{Code: 51023, Message: "part of artition configs not existed ", - CNMessage: "部分分区配置不存在"} - // NotSupportedClusterType TODO - NotSupportedClusterType = Errno{Code: 51024, Message: "this instance type is not supportted by partition", - CNMessage: "不支持的实例类型"} - // ConfigIdIsEmpty TODO - ConfigIdIsEmpty = Errno{Code: 51025, Message: "partition config id can't be empty", - CNMessage: "partition config id 不能为空"} - // CloudIdRequired TODO - CloudIdRequired = Errno{Code: 51026, Message: "bk_cloud_id is required", CNMessage: "bk_cloud_id不能为空"} - // GetPartitionSqlFail TODO - GetPartitionSqlFail = Errno{Code: 51027, Message: "get partition sql failed", CNMessage: "获取分区语句失败"} - // ExecutePartitionFail TODO - ExecutePartitionFail = Errno{Code: 51028, Message: "execute partition failed", CNMessage: "执行分区失败"} - // NothingToDo TODO - NothingToDo = Errno{Code: 51029, Message: "nothing to do", CNMessage: "没有需要执行的操作"} - // DomainNotExists TODO - DomainNotExists = Errno{Code: 51030, Message: "domain not exists", CNMessage: "域名不存在"} -) diff --git a/dbm-services/mysql/db-partition/errno/errno.go b/dbm-services/mysql/db-partition/errno/errno.go deleted file mode 100644 index fe2cf6d791..0000000000 --- a/dbm-services/mysql/db-partition/errno/errno.go +++ /dev/null @@ -1,133 +0,0 @@ -// Package errno TODO -package errno - -import ( - "fmt" - - "github.com/spf13/viper" -) - -// Errno TODO -type Errno struct { - Code int - Message string - CNMessage string -} - -var lang = viper.GetString("lang") - -// Error 用于错误处理 -func (err Errno) Error() string { - switch lang { - case "zh_CN": - return err.CNMessage - case "en_US": - return err.Message - default: - return err.CNMessage - } -} - -// Addf TODO -func (err Errno) Addf(format string, args ...interface{}) error { - return err.Add(fmt.Sprintf(format, args...)) -} - -// Add TODO -func (err Errno) Add(message string) error { - switch lang { - case "zh_CN": - err.CNMessage += message - return err - case "en_US": - err.Message += message - return err - default: - err.CNMessage += message - return err - } - return err -} - -// Err represents an error -type Err struct { - Errno - Err error -} - -// New TODO -func New(errno Errno, err error) *Err { - return &Err{Errno: errno, Err: err} -} - -// Add TODO -func (err Err) Add(message string) error { - switch lang { - case "zh_CN": - err.CNMessage += message - return err - case "en_US": - err.Message += message - return err - default: - err.CNMessage += message - return err - } - return err -} - -// SetMsg TODO -func (err Err) SetMsg(message string) error { - err.Message = message - return err -} - -// SetCNMsg TODO -func (err Err) SetCNMsg(cnMessage string) error { - err.CNMessage = cnMessage - return err -} - -// Addf TODO -func (err Err) Addf(format string, args ...interface{}) error { - return err.Add(fmt.Sprintf(format, args...)) -} - -// IsErrUserNotFound TODO -/* - func (err *Err) Error() string { - return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err) - } -*/ -func IsErrUserNotFound(err error) bool { - code, _ := DecodeErr(err) - return code == ErrUserNotFound.Code -} - -// DecodeErr TODO -func DecodeErr(err error) (int, string) { - - var CN bool = true - - if err == nil { - return OK.Code, OK.Message - } - - switch typed := err.(type) { - case Err: - if CN { - return typed.Code, typed.CNMessage - } else { - return typed.Code, typed.Message - } - case Errno: - if CN { - return typed.Code, typed.CNMessage - } else { - return typed.Code, typed.Message - } - default: - } - // lager.Logger.Errorf("%s", err) - return InternalServerError.Code, err.Error() -} diff --git a/dbm-services/mysql/db-partition/handler/handler.go b/dbm-services/mysql/db-partition/handler/handler.go index f28b63995c..2842fc845d 100644 --- a/dbm-services/mysql/db-partition/handler/handler.go +++ b/dbm-services/mysql/db-partition/handler/handler.go @@ -7,7 +7,7 @@ import ( "net/http" _ "runtime/debug" // debug TODO - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/service" "github.com/gin-gonic/gin" diff --git a/dbm-services/mysql/db-partition/service/check_partition.go b/dbm-services/mysql/db-partition/service/check_partition.go index 77e49b53cf..478c36b8e0 100644 --- a/dbm-services/mysql/db-partition/service/check_partition.go +++ b/dbm-services/mysql/db-partition/service/check_partition.go @@ -9,7 +9,7 @@ import ( "sync" "time" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/model" "golang.org/x/exp/slog" diff --git a/dbm-services/mysql/db-partition/service/check_partition_base_func.go b/dbm-services/mysql/db-partition/service/check_partition_base_func.go index 303d6ea603..cba3897b9f 100644 --- a/dbm-services/mysql/db-partition/service/check_partition_base_func.go +++ b/dbm-services/mysql/db-partition/service/check_partition_base_func.go @@ -12,7 +12,7 @@ import ( "golang.org/x/exp/slog" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/model" "dbm-services/mysql/db-partition/monitor" diff --git a/dbm-services/mysql/db-partition/service/db_meta_service.go b/dbm-services/mysql/db-partition/service/db_meta_service.go index b55c2a3f8d..e75afb9e82 100644 --- a/dbm-services/mysql/db-partition/service/db_meta_service.go +++ b/dbm-services/mysql/db-partition/service/db_meta_service.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package service import ( @@ -5,7 +15,7 @@ import ( "fmt" "net/http" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/util" "github.com/spf13/viper" diff --git a/dbm-services/mysql/db-partition/service/manage_config.go b/dbm-services/mysql/db-partition/service/manage_config.go index 3d4d96bd3c..825be6e829 100644 --- a/dbm-services/mysql/db-partition/service/manage_config.go +++ b/dbm-services/mysql/db-partition/service/manage_config.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package service import ( @@ -8,7 +18,7 @@ import ( "strings" "time" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "dbm-services/mysql/db-partition/model" "github.com/spf13/viper" diff --git a/dbm-services/mysql/db-priv/handler/public_key.go b/dbm-services/mysql/db-priv/handler/public_key.go index b17e14631e..3e18eec82e 100644 --- a/dbm-services/mysql/db-priv/handler/public_key.go +++ b/dbm-services/mysql/db-priv/handler/public_key.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package handler import ( @@ -5,7 +15,7 @@ import ( "net/http" "os" - "dbm-services/mysql/db-partition/errno" + "dbm-services/common/go-pubpkg/errno" "github.com/gin-gonic/gin" "golang.org/x/exp/slog" From eada004fb849a553845e5cbd994376ed2bebc439 Mon Sep 17 00:00:00 2001 From: OMG-By <504094596@qq.com> Date: Thu, 13 Jul 2023 14:37:30 +0800 Subject: [PATCH 134/476] =?UTF-8?q?fix(redis):=20redis=E6=89=A9=E7=BC=A9?= =?UTF-8?q?=E5=AE=B9=E5=8D=8F=E8=AE=AE=E5=8F=98=E6=9B=B4#453?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bamboo/scene/redis/redis_backend_scale.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py index b9f9638458..46f9af65d8 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_backend_scale.py @@ -235,15 +235,23 @@ def redis_backend_scale_flow(self): "start_port": DEFAULT_REDIS_START_PORT, "ports": new_ports, "instance_numb": ins_num, - "spec_id": info["resource_spec"]["backend_group"]["id"], - "spec_config": info["resource_spec"]["backend_group"], + "spec_id": info["resource_spec"]["master"]["id"], + "spec_config": info["resource_spec"]["master"], } for ip in new_master_ips: params["ip"] = ip redis_install_sub_pipelines.append( RedisBatchInstallAtomJob(self.root_id, self.data, act_kwargs, params) ) - params["meta_role"] = InstanceRole.REDIS_SLAVE.value + + params = { + "meta_role": InstanceRole.REDIS_SLAVE.value, + "start_port": DEFAULT_REDIS_START_PORT, + "ports": new_ports, + "instance_numb": ins_num, + "spec_id": info["resource_spec"]["slave"]["id"], + "spec_config": info["resource_spec"]["slave"], + } for ip in new_slave_ips: params["ip"] = ip redis_install_sub_pipelines.append( From 0b0b38aa684b49fe2f5afe8311d57faabde73b54 Mon Sep 17 00:00:00 2001 From: xiepaup Date: Thu, 13 Jul 2023 16:43:58 +0800 Subject: [PATCH 135/476] =?UTF-8?q?fix(redis):=20=E6=95=B4=E6=9C=BA?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=8D=8F=E8=AE=AE=E5=8F=98=E6=9B=B4=E3=80=81?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E8=B5=84=E6=BA=90=E8=A7=84=E6=A0=BC=20#479?= =?UTF-8?q?=20(#481)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../atom_jobs/redis_cluster_master_rep.py | 26 ++++---- .../atom_jobs/redis_cluster_slave_rep.py | 11 ++-- .../scene/redis/redis_cluster_scene_cmr.py | 60 +++++++++++++------ 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py index da21544c04..8aa06707db 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py @@ -34,30 +34,28 @@ logger = logging.getLogger("flow") -def RedisClusterMasterReplaceJob( - root_id, ticket_data, sub_kwargs: ActKwargs, master_replace_detail: Dict -) -> SubBuilder: +def RedisClusterMasterReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, master_replace_info: Dict) -> SubBuilder: """### 适用于 集群中Master 机房裁撤/迁移替换场景 (成对替换) 步骤: 获取变更锁--> 新实例部署--> 建Sync关系--> 检测同步状态 Kill Dead链接--> 下架旧实例 master_replace_detail:[{ - "old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - "new": [ - {"ip": "2.b.3.4", "bk_cloud_id": 0, "bk_host_id": 123}, - {"ip": "2.b.3.4", "bk_cloud_id": 0, "bk_host_id": 123} - ] - }] + {"ip": "1.1.1.c","spec_id": 17, + "target": { + "master": {"bk_cloud_id": 0,"bk_host_id": 195,"status": 1,"ip": "2.2.2.b"}, + "slave": {"bk_cloud_id": 0,"bk_host_id": 187,"status": 1,"ip": "3.3.3.x"}} + }] """ act_kwargs = deepcopy(sub_kwargs) redis_pipeline = SubBuilder(root_id=root_id, data=ticket_data) # ## 部署实例 ############################################################################# sub_pipelines = [] + master_replace_detail = master_replace_info["redis_master"] for replace_info in master_replace_detail: - old_master = replace_info["old"]["ip"] - new_host_master = replace_info["new"][0]["ip"] - new_host_slave = replace_info["new"][1]["ip"] + old_master = replace_info["ip"] + new_host_master = replace_info["target"]["master"]["ip"] + new_host_slave = replace_info["target"]["slave"]["ip"] # 安装Master params = { "ip": new_host_master, @@ -65,12 +63,16 @@ def RedisClusterMasterReplaceJob( "meta_role": InstanceRole.REDIS_MASTER.value, "start_port": DEFAULT_REDIS_START_PORT, "instance_numb": len(act_kwargs.cluster["master_ports"][old_master]), + "spec_id": master_replace_info["master_spec"].get("id", 0), + "spec_config": master_replace_info["master_spec"], } sub_pipelines.append(RedisBatchInstallAtomJob(root_id, ticket_data, act_kwargs, params)) # 安装slave params["ip"] = new_host_slave params["meta_role"] = InstanceRole.REDIS_SLAVE.value + params["spec_id"] = master_replace_info["slave_spec"].get("id", 0) + params["spec_config"] = master_replace_info["slave_spec"] sub_pipelines.append(RedisBatchInstallAtomJob(root_id, ticket_data, act_kwargs, params)) redis_pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) # ### 部署实例 ####################################################################### 完毕 ### diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py index d1c7bd1473..e123746eb5 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py @@ -35,7 +35,7 @@ logger = logging.getLogger("flow") -def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, slave_replace_detail: Dict) -> SubBuilder: +def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, slave_replace_info: Dict) -> SubBuilder: """适用于 集群中Slave 机房裁撤/迁移替换场景 步骤: 获取变更锁--> 新实例部署--> 重建热备--> 检测同步状态--> @@ -45,16 +45,19 @@ def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, sla redis_pipeline = SubBuilder(root_id=root_id, data=ticket_data) # ### 部署实例 ############################################################################### sub_pipelines = [] + slave_replace_detail = slave_replace_info["redis_slave"] for replace_link in slave_replace_detail: - # "Old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - old_slave = replace_link["old"]["ip"] - new_slave = replace_link["new"]["ip"] + # {"ip": "1.1.1.a","spec_id": 17,"target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"}} + old_slave = replace_link["ip"] + new_slave = replace_link["target"]["ip"] params = { "ip": new_slave, "meta_role": InstanceRole.REDIS_SLAVE.value, "start_port": DEFAULT_REDIS_START_PORT, "ports": act_kwargs.cluster["slave_ports"][old_slave], "instance_numb": len(act_kwargs.cluster["slave_ports"][old_slave]), + "spec_id": slave_replace_info["slave_spec"].get("id", 0), + "spec_config": slave_replace_info["slave_spec"], } sub_builder = RedisBatchInstallAtomJob(root_id, ticket_data, act_kwargs, params) sub_pipelines.append(sub_builder) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py index df1169cc6c..02a85080a0 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py @@ -57,20 +57,19 @@ class RedisClusterCMRSceneFlow(object): { "cluster_id": 1, "redis_proxy": [ - { - "old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - "new": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123} - }], + {"ip": "1.1.1.a","spec_id": 17, + "target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"} + }], "redis_slave": [ - { - "old": {"ip": "2.b.3.4", "bk_cloud_id": 0, "bk_host_id": 123}, - "new": {"ip": "2.b.3.4", "bk_cloud_id": 0, "bk_host_id": 123} - }], + {"ip": "1.1.1.a","spec_id": 17, + "target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"} + }], "redis_master": [ - { - "old": {"ip": "2.2.3.c", "bk_cloud_id": 0, "bk_host_id": 123}, - "new": [{"ip": "2.2.3.c", "bk_cloud_id": 0, "bk_host_id": 123},] - }] + {"ip": "1.1.1.c","spec_id": 17, + "target": { + "master": {"bk_cloud_id": 0,"bk_host_id": 195,"status": 1,"ip": "2.2.2.b"}, + "slave": {"bk_cloud_id": 0,"bk_host_id": 187,"status": 1,"ip": "3.3.3.x"}} + }] } ] } @@ -223,14 +222,27 @@ def generate_cluster_replacement(self, flow_data, act_kwargs, replacement_param) if replacement_param.get("redis_slave"): slave_kwargs = deepcopy(act_kwargs) slave_replace_pipe = RedisClusterSlaveReplaceJob( - self.root_id, flow_data, slave_kwargs, replacement_param.get("redis_slave") + self.root_id, + flow_data, + slave_kwargs, + { + "redis_slave": replacement_param.get("redis_slave"), + "slave_spec": replacement_param.get("resource_spec", {}).get("redis_slave", {}), + }, ) sub_pipeline.add_sub_pipeline(slave_replace_pipe) # 再添加Proxy替换流程 if replacement_param.get("redis_proxy"): proxy_kwargs = deepcopy(act_kwargs) - self.proxy_replacement(sub_pipeline, proxy_kwargs, replacement_param.get("redis_proxy")) + self.proxy_replacement( + sub_pipeline, + proxy_kwargs, + { + "redis_proxy": replacement_param.get("redis_proxy"), + "proxy_spec": replacement_param.get("resource_spec", {}).get("proxy", {}), + }, + ) # 最后添加Master替换流程 , reget proxy info. if replacement_param.get("redis_master"): @@ -243,18 +255,26 @@ def generate_cluster_replacement(self, flow_data, act_kwargs, replacement_param) ] master_kwargs.cluster["sync_type"] = flow_data["sync_type"] master_replace_pipe = RedisClusterMasterReplaceJob( - self.root_id, flow_data, master_kwargs, replacement_param.get("redis_master") + self.root_id, + flow_data, + master_kwargs, + { + "redis_master": replacement_param.get("redis_master"), + "master_spec": replacement_param.get("resource_spec", {}).get("master", {}), + "slave_spec": replacement_param.get("resource_spec", {}).get("slave", {}), + }, ) sub_pipeline.add_sub_pipeline(master_replace_pipe) return sub_pipeline.build_sub_process(sub_name=_("Redis-{}-整机替换").format(act_kwargs.cluster["immute_domain"])) - def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_details): + def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_info): old_proxies, new_proxies = [], [] + proxy_replace_details = proxy_replace_info["redis_proxy"] for replace_link in proxy_replace_details: - # "Old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - old_proxies.append(replace_link["old"]["ip"]) - new_proxies.append(replace_link["new"]["ip"]) + # {"ip": "1.1.1.a","spec_id": 17,"target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"}} + old_proxies.append(replace_link["ip"]) + new_proxies.append(replace_link["target"]["ip"]) # 第一步:安装Proxy sub_pipelines = [] @@ -280,6 +300,8 @@ def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_details): "proxy_pwd": config_info["password"], "proxy_port": int(config_info["port"]), "servers": act_kwargs.cluster["backend_servers"], + "spec_id": proxy_replace_info["proxy_spec"].get("id", 0), + "spec_config": proxy_replace_info["proxy_spec"], } sub_builder = ProxyBatchInstallAtomJob(self.root_id, self.data, act_kwargs, params) sub_pipelines.append(sub_builder) From 5bd40e34c0cac16139665560a6a91d954f288697 Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Thu, 13 Jul 2023 16:46:20 +0800 Subject: [PATCH 136/476] =?UTF-8?q?refactor(dbm-services):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96sql=E6=96=87=E4=BB=B6=E5=AF=BC=E5=85=A5=20close=20#482?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pkg/util/mysqlutil/hide_passowrd.go | 2 +- .../pkg/util/mysqlutil/mysqlclient_exec.go | 29 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/hide_passowrd.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/hide_passowrd.go index 3c72eb8844..cdd3d37482 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/hide_passowrd.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/hide_passowrd.go @@ -15,7 +15,7 @@ import ( ) var ( - mysqlRegex = regexp.MustCompile(`mysql.*-u\w+.*\s-p(\w+).*`) + mysqlRegex = regexp.MustCompile(`mysql.*-u(\s*)\w+.*\s-p(\w+).*`) mysqlAdminRegex = regexp.MustCompile(`mysqladmin.*-u\w+.*\s-p(\w+).*`) mysqlPasswordRegex = regexp.MustCompile(`\s-p[^\s]+`) masterPasswordRegexp = regexp.MustCompile(`master_password="[^\s]*"`) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go index 0786025961..f07865bd0d 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysqlutil import ( @@ -7,7 +17,6 @@ import ( "os" "os/exec" "path" - "regexp" "sync" "time" @@ -127,23 +136,15 @@ func (e ExecuteSqlAtLocal) ExcuteCommand(command string) (err error) { _, errStderr = io.Copy(stderr, stderrIn) wg.Wait() - if err = cmd.Wait(); err != nil { - logger.Error("cmd.wait failed:%s", err.Error()) - return - } - if errStdout != nil || errStderr != nil { logger.Error("failed to capture stdout or stderr\n") return } - outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) - re, err := regexp.Compile(`((?i)\s*error\s+\d+)|No such file or directory`) - if err != nil { - return err - } - logger.Info("outstr:%s,errstr:%s", outStr, errStr) - if re.MatchString(outStr + errStr) { // @todo 这里的写法不够细致,可能匹配表结构里的关键字 - return fmt.Errorf("执行sql的输出含有error") + + if err = cmd.Wait(); err != nil { + errStr := string(stderr.Bytes()) + logger.Error("exec failed:%s,stderr: %s", err.Error(), errStr) + return } return nil } From 05b9cec713ad551238ea4b92893fae2c677d32cb Mon Sep 17 00:00:00 2001 From: iSecloud <869820505@qq.com> Date: Thu, 13 Jul 2023 19:36:54 +0800 Subject: [PATCH 137/476] =?UTF-8?q?fix(backend):=20=E4=BF=AE=E5=A4=8Dflow?= =?UTF-8?q?=20info=E4=B8=BB=E6=9C=BA=E4=BF=A1=E6=81=AF=E7=9A=84=E8=A1=A5?= =?UTF-8?q?=E5=85=85=20#478?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db_services/dbresource/handlers.py | 4 +++- .../db_services/taskflow/views/flow.py | 21 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/dbm-ui/backend/db_services/dbresource/handlers.py b/dbm-ui/backend/db_services/dbresource/handlers.py index 7962c019d2..e54a413130 100644 --- a/dbm-ui/backend/db_services/dbresource/handlers.py +++ b/dbm-ui/backend/db_services/dbresource/handlers.py @@ -20,9 +20,11 @@ class ClusterSpecFilter(object): """集群规格的过滤器""" def __init__(self, capacity, future_capacity, qps, spec_cluster_type, spec_machine_type): + # 用户的当前容量,期望容量以及期望qps范围 self.capacity: int = capacity self.future_capacity: int = future_capacity self.qps: Dict = qps + # 当前集群的筛选规格 self.specs: List[Dict[str, Any]] = [ {**model_to_dict(spec), "capacity": spec.capacity} for spec in Spec.objects.filter(spec_machine_type=spec_machine_type, spec_cluster_type=spec_cluster_type) @@ -53,7 +55,7 @@ def qps_filter(self): "min": spec["machine_pair"] * spec["qps"]["min"], "max": spec["machine_pair"] * spec["qps"]["max"], } - if not self._qps_check(qps_range, self.qps): + if not self._qps_check(self.qps, qps_range): continue valid_specs.append(spec) diff --git a/dbm-ui/backend/db_services/taskflow/views/flow.py b/dbm-ui/backend/db_services/taskflow/views/flow.py index 7f1089b52b..7019387d90 100644 --- a/dbm-ui/backend/db_services/taskflow/views/flow.py +++ b/dbm-ui/backend/db_services/taskflow/views/flow.py @@ -24,7 +24,7 @@ VersionSerializer, ) from backend.flow.engine.bamboo.engine import BambooEngine -from backend.flow.models import FlowTree +from backend.flow.models import FlowNode, FlowTree from backend.iam_app.handlers.drf_perm import TaskFlowIAMPermission from backend.ticket.models import Flow from backend.utils.basic import get_target_items_from_details @@ -75,13 +75,20 @@ def retrieve(self, requests, *args, **kwargs): tree_states = BambooEngine(root_id=root_id).get_pipeline_tree_states() flow_info = super().retrieve(requests, *args, **kwargs) - ticket_flow = Flow.objects.get(flow_obj_id=root_id) - # 查询当前flow涉及的主机和业务信息 - bk_host_ids = get_target_items_from_details( - obj=ticket_flow.details, match_keys=["host_id", "bk_host_id", "bk_host_ids"] - ) - flow_info.data.update(bk_host_ids=bk_host_ids, bk_biz_id=ticket_flow.ticket.bk_biz_id) + try: + # 从pipeline的第一个节点获取任务的输入数据 + first_act_node_id = FlowNode.objects.filter(root_id=root_id).first().node_id + details = BambooEngine(root_id=root_id).get_node_input_data(node_id=first_act_node_id).data["global_data"] + # 递归遍历字典,获取主机ID + bk_host_ids = get_target_items_from_details( + obj=details, match_keys=["host_id", "bk_host_id", "bk_host_ids"] + ) + bk_biz_id = details["bk_biz_id"] + except KeyError: + # 如果pipeline还未构建,则先忽略 + bk_host_ids, bk_biz_id = [], "" + flow_info.data.update(bk_host_ids=bk_host_ids, bk_biz_id=bk_biz_id) return Response({"flow_info": flow_info.data, **tree_states}) @common_swagger_auto_schema( From e743df1cc637d127be55debefde101a35f76bd36 Mon Sep 17 00:00:00 2001 From: zfrendo <135297126+zfrendo@users.noreply.github.com> Date: Fri, 14 Jul 2023 10:22:41 +0800 Subject: [PATCH 138/476] =?UTF-8?q?feat:=20=E5=BC=80=E5=8F=91tendbcluster?= =?UTF-8?q?=20remote=E8=8A=82=E7=82=B9=E6=89=A9=E7=BC=A9=E5=AE=B9/remote?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=AE=9A=E7=82=B9=E5=9B=9E=E6=A1=A3=20#308?= =?UTF-8?q?=20(#464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tendbcluster/remotedb_node_migrate.py | 164 +++++++++ dbm-ui/backend/flow/consts.py | 5 + .../scene/mysql/common/common_sub_flow.py | 12 +- .../spider/spider_cluster_rollback_flow.py | 96 +++++ .../bamboo/scene/spider/spider_recover.py | 185 ++++++++++ .../spider/spider_remote_node_migrate.py | 346 ++++++++++++++++++ .../spider/spider_remotedb_migrate_flow.py | 194 ++++++++++ .../spider/spider_remotedb_rebalance_flow.py | 268 ++++++++++++++ .../backend/flow/engine/controller/spider.py | 24 ++ dbm-ui/backend/flow/urls.py | 5 + .../flow/utils/mysql/mysql_act_playload.py | 84 +++++ .../flow/utils/spider/spider_db_meta.py | 74 ++++ .../flow/utils/spider/tendb_cluster_info.py | 110 ++++++ .../flow/views/spider_migrage_remotedb.py | 25 ++ .../views/tendb_cluster_remote_rebalance.py | 32 ++ .../flow/views/tendb_cluster_rollback_data.py | 32 ++ 16 files changed, 1654 insertions(+), 2 deletions(-) create mode 100644 dbm-ui/backend/db_meta/api/cluster/tendbcluster/remotedb_node_migrate.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_rollback_flow.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_recover.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remote_node_migrate.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_migrate_flow.py create mode 100644 dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_rebalance_flow.py create mode 100644 dbm-ui/backend/flow/utils/spider/tendb_cluster_info.py create mode 100644 dbm-ui/backend/flow/views/spider_migrage_remotedb.py create mode 100644 dbm-ui/backend/flow/views/tendb_cluster_remote_rebalance.py create mode 100644 dbm-ui/backend/flow/views/tendb_cluster_rollback_data.py diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/remotedb_node_migrate.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/remotedb_node_migrate.py new file mode 100644 index 0000000000..2f73846cc0 --- /dev/null +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/remotedb_node_migrate.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.db import transaction + +from backend.configuration.constants import DBType +from backend.db_meta import api, request_validator +from backend.db_meta.api import common +from backend.db_meta.enums import ClusterType, InstanceRole, InstanceStatus, MachineType +from backend.db_meta.models import Cluster, StorageInstance, StorageInstanceTuple, TenDBClusterStorageSet +from backend.db_package.models import Package +from backend.flow.consts import MediumEnum +from backend.flow.engine.bamboo.scene.common.get_real_version import get_mysql_real_version + + +class TenDBClusterMigrateRemoteDb: + cluster_type = ClusterType.TenDBCluster + + @transaction.atomic + @classmethod + def storage_create( + cls, + cluster_id: int, + master_ip: str, + slave_ip: str, + ports: list, + creator: str, + mysql_version: str, + resource_spec: dict, + ): + """主从成对迁移初始化机器写入元数据""" + cluster = Cluster.objects.get(id=cluster_id) + bk_cloud_id = cluster.bk_cloud_id + bk_biz_id = cluster.bk_biz_id + time_zone = cluster.time_zone + mysql_pkg = Package.get_latest_package(version=mysql_version, pkg_type=MediumEnum.MySQL, db_type=DBType.MySQL) + machines = [ + { + "ip": master_ip, + "bk_biz_id": int(bk_biz_id), + "machine_type": MachineType.REMOTE.value, + "spec_id": resource_spec[MachineType.REMOTE.value]["id"], + "spec_config": resource_spec[MachineType.REMOTE.value], + }, + { + "ip": slave_ip, + "bk_biz_id": int(bk_biz_id), + "machine_type": MachineType.REMOTE.value, + "spec_id": resource_spec[MachineType.REMOTE.value]["id"], + "spec_config": resource_spec[MachineType.REMOTE.value], + }, + ] + api.machine.create(machines=machines, creator=creator, bk_cloud_id=bk_cloud_id) + storages = [] + for port in ports: + storages.append( + { + "ip": master_ip, + "port": port, + "instance_role": InstanceRole.REMOTE_MASTER.value, + "is_stand_by": True, # 标记实例属于切换组实例 + "db_version": get_mysql_real_version(mysql_pkg.name), # 存储真正的版本号信息 + }, + ) + storages.append( + { + "ip": slave_ip, + "port": port, + "instance_role": InstanceRole.REMOTE_SLAVE.value, + "is_stand_by": True, # 标记实例属于切换组实例 + "db_version": get_mysql_real_version(mysql_pkg.name), # 存储真正的版本号信息 + }, + ) + api.storage_instance.create( + instances=storages, creator=creator, time_zone=time_zone, status=InstanceStatus.RESTORING + ) + # cluster映射关系 + storages = request_validator.validated_storage_list(storages, allow_empty=False, allow_null=False) + storage_objs = common.filter_out_instance_obj(storages, StorageInstance.objects.all()) + cluster.storageinstance_set.add(*storage_objs) + api.machine.trans_module( + bk_cloud_id=bk_cloud_id, cluster_ids=[cluster_id], machines=[master_ip, slave_ip], idle=False + ) + + @classmethod + @transaction.atomic + def switch_remote_node(cls, cluster_id: int, source: dict, target: dict): + """ + remotedb 分片切换 + source:{master:{ip:xx,port:xx},slave:"ip:xx,port:xx"} + 修正storage的状态>映射分片 + """ + cluster = Cluster.objects.get(id=cluster_id) + bk_cloud_id = cluster.bk_cloud_id + # bk_biz_id = cluster.bk_biz_id + source_master_obj = StorageInstance.objects.get( + machine__ip=source["master"]["ip"], port=source["master"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + source_slave_obj = StorageInstance.objects.get( + machine__ip=source["slave"]["ip"], port=source["slave"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + target_master_obj = StorageInstance.objects.get( + machine__ip=target["master"]["ip"], port=target["master"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + target_slave_obj = StorageInstance.objects.get( + machine__ip=target["slave"]["ip"], port=target["slave"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + target_master_obj.status = InstanceStatus.RUNNING + target_slave_obj.status = InstanceStatus.RUNNING + target_master_obj.instance_role = InstanceRole.REMOTE_MASTER + target_slave_obj.instance_role = InstanceRole.REMOTE_SLAVE + target_master_obj.save() + target_slave_obj.save() + source_tuple = StorageInstanceTuple.objects.get(ejector=source_master_obj, receiver=source_slave_obj) + target_tuple = StorageInstanceTuple.objects.get(ejector=target_master_obj, receiver=target_slave_obj) + # 删除原本shard 新增shard + storage_shard = TenDBClusterStorageSet.objects.get( + cluster_id=cluster_id, storage_instance_tuple_id=source_tuple + ) + storage_shard.storage_instance_tuple = target_tuple + storage_shard.save() + # storage_shard.delete() + # TenDBClusterStorageSet.objects.create( + # storage_instance_tuple=target_tuple, shard_id=storage_shard.shard_key, cluster=cluster + # ) + + @classmethod + @transaction.atomic + def add_storage_tuple(cls, cluster_id: int, storage: dict): + """ + 添加成对迁移的主从映射关系 + storage:{master:{ip:xx,port:xx},slave:"ip:xx,port:xx"} + 新主库改为 storageinstance 角色为repeater + """ + cluster = Cluster.objects.get(id=cluster_id) + bk_cloud_id = cluster.bk_cloud_id + master_obj = StorageInstance.objects.get( + machine__ip=storage["master"]["ip"], port=storage["master"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + slave_obj = StorageInstance.objects.get( + machine__ip=storage["slave"]["ip"], port=storage["slave"]["port"], machine__bk_cloud_id=bk_cloud_id + ) + StorageInstanceTuple.objects.create(ejector=master_obj, receiver=slave_obj) + + @classmethod + @transaction.atomic + def uninstall_storage(cls, cluster_id: int, ip: str): + cluster = Cluster.objects.get(id=cluster_id) + bk_cloud_id = cluster.bk_cloud_id + cluster.storageinstance_set.remove() + storage_instances = StorageInstance.objects.filter(machine__ip=ip, machine__bk_cloud_id=bk_cloud_id) + for one in storage_instances: + StorageInstanceTuple.objects.filter(ejector=one.id).delete() + StorageInstanceTuple.objects.filter(receiver=one.id).delete() + StorageInstance.objects.filter(machine__ip=ip, machine__bk_cloud_id=bk_cloud_id).delete() + api.machine.trans_module(bk_cloud_id=bk_cloud_id, cluster_ids=[cluster_id], machines=[ip], idle=True) + api.machine.delete(bk_cloud_id=bk_cloud_id, machines=[ip]) diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index ca2c069e25..3dcc4ce8bb 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -784,3 +784,8 @@ class PrivRole(str, StructuredEnum): SPIDER = EnumField("spider", _("spider")) TDBCTL = EnumField("tdbctl", _("tdbctl")) MYSQL = EnumField("mysql", _("mysql")) + + +class MysqlChangeMasterType(str, StructuredEnum): + MASTERSTATUS = EnumField("MasterStatus", _("from show master status")) + BACKUPFILE = EnumField("BackFile", _("from backup file")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py index df62697537..daae490470 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/common/common_sub_flow.py @@ -336,10 +336,13 @@ def build_repl_by_manual_input_sub_flow( return sub_pipeline.build_sub_process(sub_name=_("建立主从同步[{}]".format(sub_flow_name))) -def install_mysql_in_cluster_sub_flow(root_id: str, cluster: Cluster, new_mysql_list: list, install_ports: list): +def install_mysql_in_cluster_sub_flow( + uid: str, root_id: str, cluster: Cluster, new_mysql_list: list, install_ports: list +): """ 设计基于某个cluster,以及计算好的实例安装端口列表,对新机器安装mysql实例的公共子流 子流程并不是提供给部署类单据的,目标是提供tendb_ha/tendb_cluster扩容类单据 + @param uid: 流程uid @param root_id: flow流程的root_id @param cluster: 关联的cluster对象 @param new_mysql_list: 新机器列表,每个元素是ip @@ -360,7 +363,12 @@ def install_mysql_in_cluster_sub_flow(root_id: str, cluster: Cluster, new_mysql_ } )["content"] - parent_global_data = {"charset": data["charset"], "db_version": data["db_version"], "mysql_ports": install_ports} + parent_global_data = { + "uid": uid, + "charset": data["charset"], + "db_version": data["db_version"], + "mysql_ports": install_ports, + } sub_pipeline = SubBuilder(root_id=root_id, data=parent_global_data) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_rollback_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_rollback_flow.py new file mode 100644 index 0000000000..587c789126 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_rollback_flow.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.db_services.mysql.fixpoint_rollback.handlers import FixPointRollbackHandler +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.spider.spider_recover import remote_node_rollback, spider_recover_sub_flow +from backend.flow.utils.spider.tendb_cluster_info import get_rollback_clusters_info +from backend.utils import time + +logger = logging.getLogger("flow") + + +class TenDBRollBackDataFlow(object): + """ + TenDB 后端节点主从成对迁移 + """ + + def __init__(self, root_id: str, data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param data : 单据传递参数 + """ + self.root_id = root_id + self.data = data + + def tendb_rollback_data(self): + """ + tendb rollback data + """ + tendb_rollback_pipeline = Builder(root_id=self.root_id, data=copy.deepcopy(self.data)) + clusters_info = get_rollback_clusters_info( + source_cluster_id=self.data["source_cluster_id"], target_cluster_id=self.data["target_cluster_id"] + ) + rollback_time = time.strptime(self.data["rollback_time"], "%Y-%m-%d %H:%M:%S") + rollback_handler = FixPointRollbackHandler(self.data["source_cluster_id"]) + backupinfo = rollback_handler.query_latest_backup_log(rollback_time) + ins_sub_pipeline_list = [] + for spider_node in clusters_info["target_spiders"]: + spd_cluster = { + "total_backupinfo": backupinfo["spider_node"], + "file_target_path": "/data/dbbak/{}/{}".format(self.root_id, spider_node["port"]), + "ip": spider_node["ip"], + "port": spider_node["port"], + "bk_cloud_id": self.data["bk_cloud_id"], + } + spd_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + spd_sub_pipeline.add_sub_pipeline( + sub_flow=spider_recover_sub_flow( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), cluster_info=spd_cluster + ) + ) + ins_sub_pipeline_list.append(spd_sub_pipeline.build_sub_process(sub_name=_("恢复spider节点数据"))) + + for shard_id, remote_node in clusters_info["shards"].items(): + shd_cluster = { + "new_master_ip": remote_node["new_master"]["ip"], + "new_master_port": remote_node["new_master"]["port"], + "new_slave_ip": remote_node["new_slave"]["ip"], + "new_master": remote_node["new_master"], + "new_slave": remote_node["new_slave"], + "new_slave_port": remote_node["new_slave"]["port"], + "master_ip": remote_node["master"]["ip"], + "master_port": remote_node["master"]["port"], + "slave_ip": remote_node["slave"]["ip"], + "slave_port": remote_node["slave"]["port"], + "master": remote_node["master"], + "slave": remote_node["slave"], + "backup_target_path": "/data/dbbak/{}/{}".format(self.root_id, remote_node["new_master"]["port"]), + "cluster_id": self.data["source_cluster_id"], + "bk_cloud_id": self.data["bk_cloud_id"], + "total_backupinfo": backupinfo["remote_node"][shard_id], + "rollback_time": self.data["rollback_time"], + } + + ins_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + ins_sub_pipeline.add_sub_pipeline( + sub_flow=remote_node_rollback( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), cluster_info=shd_cluster + ) + ) + ins_sub_pipeline_list.append(ins_sub_pipeline.build_sub_process(sub_name=_("恢复remote节点数据"))) + tendb_rollback_pipeline.add_parallel_sub_pipeline(sub_flow_list=ins_sub_pipeline_list) + tendb_rollback_pipeline.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_recover.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_recover.py new file mode 100644 index 0000000000..9ca1101855 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_recover.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import datetime +from dataclasses import asdict + +from django.utils.translation import ugettext as _ + +from backend.db_meta.enums import ClusterType +from backend.flow.engine.bamboo.scene.common.builder import SubBuilder +from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent +from backend.flow.plugins.components.collections.mysql.mysql_download_backupfile import ( + MySQLDownloadBackupfileComponent, +) +from backend.flow.utils.mysql.mysql_act_dataclass import DownloadBackupFileKwargs, ExecActuatorKwargs +from backend.flow.utils.mysql.mysql_act_playload import MysqlActPayload +from backend.utils import time + + +def spider_recover_sub_flow(root_id: str, ticket_data: dict, cluster_info: dict): + """ + spider 恢复表结构 + 从指定spider列表获取备份介质恢复至指定的spider + 1 获取介质>判断介质来源>恢复数据 + @param root_id: flow流程root_id + @param ticket_data: 单据 data + @param cluster_info: 关联的cluster对象 + """ + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + cluster = copy.deepcopy(cluster_info) + exec_act_kwargs = ExecActuatorKwargs( + bk_cloud_id=int(cluster["bk_cloud_id"]), + cluster_type=ClusterType.TenDBCluster, + ) + + cluster["rollback_ip"] = cluster["ip"] + cluster["rollback_port"] = cluster["port"] + cluster["master_ip"] = cluster["total_backupinfo"]["host"] + cluster["master_port"] = cluster["total_backupinfo"]["port"] + + backupinfo = cluster["total_backupinfo"] + task_ids = [i["task_id"] for i in backupinfo["file_list_details"]] + # 是否回档从库? + download_kwargs = DownloadBackupFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + task_ids=task_ids, + dest_ip=cluster["rollback_ip"], + login_user="mysql", + desc_dir=cluster["file_target_path"], + reason="spider node rollback data", + ) + sub_pipeline.add_act( + act_name=_("下载定点恢复的全库备份介质到{}".format(cluster["rollback_ip"])), + act_component_code=MySQLDownloadBackupfileComponent.code, + kwargs=asdict(download_kwargs), + ) + # todo 注意payload信息 确定indexfile + exec_act_kwargs.exec_ip = cluster_info["rollback_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_rollback_data_restore_payload.__name__ + sub_pipeline.add_act( + act_name=_("定点恢复之恢复数据{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="change_master_info", + ) + + # 恢复binlog 构造出时间 backup_consistent_time rollback_time binlog_begin_time binlog_end_time binlog源为master_ip + # 下载binlog的时间段: 开始为备份一致性时间点前半小时,结束为回滚目标时间点后半小时。以确保能下载到对应binlog + rollback_time = time.strptime(cluster["rollback_time"], "%Y-%m-%d %H:%M:%S") + backup_time = time.strptime(backupinfo["backup_consistent_time"], "%Y-%m-%d %H:%M:%S") + cluster["binlog_begin_time"] = (backup_time - datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") + cluster["binlog_end_time"] = (rollback_time + datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") + + # todo 通过接口插到binlog的备份列表 + task_ids = [] + download_kwargs = DownloadBackupFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + task_ids=task_ids, + dest_ip=cluster["rollback_ip"], + login_user="mysql", + desc_dir=cluster["file_target_path"], + reason="spider node rollback binlog", + ) + sub_pipeline.add_act( + act_name=_("下载定点恢复的binlog到{}").format(cluster["rollback_ip"]), + act_component_code=MySQLDownloadBackupfileComponent.code, + kwargs=asdict(download_kwargs), + ) + + exec_act_kwargs.exec_ip = cluster_info["rollback_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_rollback_data_recover_binlog_payload.__name__ + sub_pipeline.add_act( + act_name=_("定点恢复之前滚binlog{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + return sub_pipeline + + +def remote_node_rollback(root_id: str, ticket_data: dict, cluster_info: dict): + """ + remote node 主从节点数据恢复+binlog前滚 + @param root_id: flow 流程 root_id + @param ticket_data: 关联单据 ticket对象 + @param cluster_info: 关联的cluster对象 + """ + cluster = copy.deepcopy(cluster_info) + sub_pipeline_all = SubBuilder(root_id=root_id, data=ticket_data) + sub_pipeline_all_list = [] + for node in [cluster["new_master"], cluster["new_slave"]]: + cluster["rollback_ip"] = node["ip"] + cluster["rollback_port"] = node["port"] + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + exec_act_kwargs = ExecActuatorKwargs( + bk_cloud_id=int(cluster["bk_cloud_id"]), + cluster_type=ClusterType.TenDBCluster, + ) + backup_info = cluster["total_backupinfo"] + task_ids = [i["task_id"] for i in backup_info["file_list_details"]] + # 是否回档从库? + download_kwargs = DownloadBackupFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + task_ids=task_ids, + dest_ip=cluster["rollback_ip"], + login_user="mysql", + desc_dir=cluster["file_target_path"], + reason="spider remote node rollback data", + ) + sub_pipeline.add_act( + act_name=_("下载定点恢复的全库备份介质到{}".format(cluster["rollback_ip"])), + act_component_code=MySQLDownloadBackupfileComponent.code, + kwargs=asdict(download_kwargs), + ) + # todo 注意payload信息 确定indexfile + exec_act_kwargs.exec_ip = cluster_info["rollback_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_rollback_data_restore_payload.__name__ + sub_pipeline.add_act( + act_name=_("定点恢复之恢复数据{}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="change_master_info", + ) + + # todo 恢复binlog 构造出时间 backup_consistent_time rollback_time binlog_begin_time binlog_end_time binlog源为master_ip + # 下载binlog的时间段: 开始为备份一致性时间点前半小时,结束为回滚目标时间点后半小时。以确保能下载到对应binlog + rollback_time = time.strptime(cluster["rollback_time"], "%Y-%m-%d %H:%M:%S") + backup_time = time.strptime(backup_info["backup_consistent_time"], "%Y-%m-%d %H:%M:%S") + cluster["binlog_begin_time"] = (backup_time - datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") + cluster["binlog_end_time"] = (rollback_time + datetime.timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") + + # todo 通过接口插到binlog的备份列表 + task_ids = [] + download_kwargs = DownloadBackupFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + task_ids=task_ids, + dest_ip=cluster["rollback_ip"], + login_user="mysql", + desc_dir=cluster["file_target_path"], + reason="spider node rollback binlog", + ) + sub_pipeline.add_act( + act_name=_("下载定点恢复的binlog到{}".format(cluster["rollback_ip"])), + act_component_code=MySQLDownloadBackupfileComponent.code, + kwargs=asdict(download_kwargs), + ) + exec_act_kwargs.exec_ip = cluster_info["rollback_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_rollback_data_recover_binlog_payload.__name__ + sub_pipeline.add_act( + act_name=_("定点恢复之前滚binlog{}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + sub_pipeline_all_list.append( + sub_pipeline.build_sub_process(sub_name=_("定点恢复 {}:{}".format(node["ip"], node["port"]))) + ) + sub_pipeline_all.add_parallel_acts(sub_pipeline_all_list) + return sub_pipeline_all diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remote_node_migrate.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remote_node_migrate.py new file mode 100644 index 0000000000..16adb47643 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remote_node_migrate.py @@ -0,0 +1,346 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +from dataclasses import asdict + +from django.utils.translation import ugettext as _ + +from backend.configuration.constants import DBType +from backend.db_meta.enums import ClusterType +from backend.flow.consts import MysqlChangeMasterType +from backend.flow.engine.bamboo.scene.common.builder import SubBuilder +from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList +from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent +from backend.flow.plugins.components.collections.mysql.mysql_download_backupfile import ( + MySQLDownloadBackupfileComponent, +) +from backend.flow.plugins.components.collections.mysql.slave_trans_flies import SlaveTransFileComponent +from backend.flow.plugins.components.collections.mysql.trans_flies import TransFileComponent +from backend.flow.utils.mysql.mysql_act_dataclass import ( + DownloadBackupFileKwargs, + DownloadMediaKwargs, + ExecActuatorKwargs, + P2PFileKwargs, +) +from backend.flow.utils.mysql.mysql_act_playload import MysqlActPayload +from backend.flow.utils.spider.tendb_cluster_info import get_remotedb_info + + +def remote_node_migrate_sub_flow(root_id: str, ticket_data: dict, cluster_info: dict): + """ + 主从成对迁移子流程。(只做流程,元数据请在主流程控制) + @param root_id: flow 流程的root_id + @param ticket_data: 单据传输过来的data数据 + @param cluster_info: 关联集群的信息 + """ + + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + # 已经安装好的2个ip,需要导入同步数据 + # 下发dbactor》通过master/slave 获取备份的文件》判断备份文件》恢复数据》change master + cluster = { + "master_ip": cluster_info["master_ip"], + "slave_ip": cluster_info["slave_ip"], + "master_port": cluster_info["master_port"], + "new_master_ip": cluster_info["new_master_ip"], + "new_slave_ip": cluster_info["new_slave_ip"], + "new_master_port": cluster_info["new_master_port"], + "bk_cloud_id": cluster_info["bk_cloud_id"], + "backup_target_path": cluster_info["backup_target_path"], + } + exec_act_kwargs = ExecActuatorKwargs( + bk_cloud_id=int(cluster["bk_cloud_id"]), + cluster_type=ClusterType.TenDBCluster, + ) + # 阶段1 传输工具 + exec_ip = [cluster["master_ip"], cluster["slave_ip"], cluster["new_master_ip"], cluster["new_slave_ip"]] + sub_pipeline.add_act( + act_name=_("下发db-actor: {}".format(exec_ip)), + act_component_code=TransFileComponent.code, + kwargs=asdict( + DownloadMediaKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + exec_ip=exec_ip, + file_list=GetFileList(db_type=DBType.MySQL).get_db_actuator_package(), + ) + ), + ) + # 阶段2 + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_find_local_backup_payload.__name__ + exec_act_kwargs.exec_ip = cluster["master_ip"] + sub_pipeline.add_act( + act_name=_("获取master节点备份介质{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="master_backup_file", + ) + exec_act_kwargs.exec_ip = cluster["slave_ip"] + sub_pipeline.add_act( + act_name=_("获取slave节点备份介质{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="slave_backup_file", + ) + # 阶段3 判断备份介质,并传输备份介质 + sub_pipeline.add_act( + act_name=_("判断备份文件来源,并传输备份文件新机器"), + act_component_code=SlaveTransFileComponent.code, + kwargs=asdict( + P2PFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + file_list=[], + file_target_path=cluster["backup_target_path"], + source_ip_list=[], + exec_ip=[cluster["new_slave_ip"], cluster["new_master_ip"]], + ) + ), + ) + # 阶段4 恢复数据 todo payload 需要注意新实例端口可能与旧实例不一样 + restore_list = [] + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_mysql_restore_slave_payload.__name__ + restore_list.append( + { + "act_name": _("恢复新主节点数据{}:{}").format(exec_act_kwargs.exec_ip, cluster["new_master_port"]), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + "write_payload_var": "change_master_info", + } + ) + + exec_act_kwargs.exec_ip = cluster["new_slave_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_mysql_restore_slave_payload.__name__ + restore_list.append( + { + "act_name": _("恢复新从节点数据{}:{}").format(exec_act_kwargs.exec_ip, cluster["new_master_port"]), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + } + ) + sub_pipeline.add_parallel_acts(acts_list=restore_list) + + # 阶段5 change master: 新从库指向新主库 todo 注意端口 + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_grant_mysql_repl_user_payload.__name__ + sub_pipeline.add_act( + act_name=_("新增repl帐户{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="master_ip_sync_info", + ) + + exec_act_kwargs.exec_ip = cluster["new_slave_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_change_master_payload.__name__ + sub_pipeline.add_act( + act_name=_("建立主从关系:新从库指向新主库 {}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + + # 阶段6 change master: 新主库指向旧主库 todo 注意端口 + exec_act_kwargs.exec_ip = cluster["master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_grant_repl_for_migrate_cluster.__name__ + sub_pipeline.add_act( + act_name=_("新增repl帐户{}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.get_change_master_payload_for_migrate_cluster.__name__ + sub_pipeline.add_act( + act_name=_("建立主从关系:新主库指向旧主库 {}").format(exec_act_kwargs.exec_ip), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + + return sub_pipeline.build_sub_process(sub_name=_("RemoteDB主从节点成对迁移子流程{}".format(exec_ip))) + + +def remote_instance_migrate_sub_flow(root_id: str, ticket_data: dict, cluster_info: dict): + """ + 主从成对迁移子流程。实例级别迁移。(只做流程,元数据请在主流程控制) + @param root_id: flow流程的root_id + @param ticket_data: 关联单据 ticket对象 + @param cluster_info: 关联的cluster对象 + """ + + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + # 已经安装好的2个ip,需要导入同步数据 + # 下发dbactor》通过master/slave 获取备份的文件》判断备份文件》恢复数据》change master + cluster = { + "master_ip": cluster_info["master_ip"], + "slave_ip": cluster_info["slave_ip"], + "master_port": cluster_info["master_port"], + "new_master_ip": cluster_info["new_master_ip"], + "new_slave_ip": cluster_info["new_slave_ip"], + "new_slave_port": cluster_info["new_slave_port"], + "new_master_port": cluster_info["new_master_port"], + "bk_cloud_id": cluster_info["bk_cloud_id"], + "backup_target_path": cluster_info["backup_target_path"], + "change_master_force": cluster_info["change_master_force"], + } + exec_act_kwargs = ExecActuatorKwargs( + bk_cloud_id=int(cluster["bk_cloud_id"]), + cluster_type=ClusterType.TenDBCluster, + ) + + backup_info = cluster["total_backupinfo"] + + # 并发下载 + task_ids = [i["task_id"] for i in backup_info["file_list_details"]] + # 是否回档从库? + download_sub_pipeline_list = [] + download_kwargs = DownloadBackupFileKwargs( + bk_cloud_id=cluster["bk_cloud_id"], + task_ids=task_ids, + dest_ip=cluster["new_master_ip"], + login_user="mysql", + desc_dir=cluster["file_target_path"], + reason="spider remote node sync data", + ) + download_sub_pipeline_list.append( + { + "act_name": _("下载全库备份介质到{}".format(cluster["new_master_ip"])), + "act_component_code": MySQLDownloadBackupfileComponent.code, + "kwargs": asdict(download_kwargs), + } + ) + download_kwargs.dest_ip = cluster["new_slave_ip"] + download_sub_pipeline_list.append( + { + "act_name": _("下载全库备份介质到{}".format(cluster["new_slave_ip"])), + "act_component_code": MySQLDownloadBackupfileComponent.code, + "kwargs": asdict(download_kwargs), + } + ) + sub_pipeline.add_parallel_acts(download_sub_pipeline_list) + + # 阶段4 恢复数据 + restore_list = [] + cluster["restore_ip"] = cluster["new_master_ip"] + cluster["restore_port"] = cluster["new_master_port"] + cluster["source_ip"] = cluster["master_ip"] + cluster["source_port"] = cluster["master_port"] + cluster["change_master"] = False + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_restore_remotedb_payload.__name__ + restore_list.append( + { + "act_name": _("恢复新主节点数据{}:{}".format(exec_act_kwargs.exec_ip, cluster["restore_ip"])), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + "write_payload_var": "change_master_info", + } + ) + + cluster["restore_ip"] = cluster["new_slave_ip"] + cluster["restore_port"] = cluster["new_slave_port"] + cluster["source_ip"] = cluster["master_ip"] + cluster["source_port"] = cluster["master_port"] + cluster["change_master"] = False + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.exec_ip = cluster["new_slave_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_restore_remotedb_payload.__name__ + restore_list.append( + { + "act_name": _("恢复新从节点数据{}:{}".format(exec_act_kwargs.exec_ip, cluster["restore_ip"])), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict(exec_act_kwargs), + } + ) + sub_pipeline.add_parallel_acts(acts_list=restore_list) + + # 阶段5 change master: 新从库指向新主库 + cluster["target_ip"] = cluster["new_master_ip"] + cluster["target_port"] = cluster["new_master_port"] + cluster["repl_ip"] = cluster["new_slave_ip"] + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_grant_remotedb_repl_user.__name__ + sub_pipeline.add_act( + act_name=_("新增repl帐户{}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + write_payload_var="show_master_status_info", + ) + + cluster["repl_ip"] = cluster["new_slave_ip"] + cluster["repl_port"] = cluster["new_slave_port"] + cluster["target_ip"] = cluster["new_master_ip"] + cluster["target_port"] = cluster["new_master_port"] + cluster["change_master_type"] = MysqlChangeMasterType.MASTERSTATUS.value + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.exec_ip = cluster["new_slave_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_remotedb_change_master.__name__ + sub_pipeline.add_act( + act_name=_("建立主从关系:新从库指向新主库 {}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + + # 阶段6 change master: 新主库指向旧主库 + cluster["target_ip"] = cluster["master_ip"] + cluster["target_port"] = cluster["master_port"] + cluster["repl_ip"] = cluster["new_master_ip"] + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.exec_ip = cluster["master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_grant_remotedb_repl_user.__name__ + sub_pipeline.add_act( + act_name=_("新增repl帐户{}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + + cluster["repl_ip"] = cluster["new_master_ip"] + cluster["repl_port"] = cluster["new_master_port"] + cluster["target_ip"] = cluster["master_ip"] + cluster["target_port"] = cluster["master_port"] + cluster["change_master_type"] = MysqlChangeMasterType.BACKUPFILE.value + exec_act_kwargs.cluster = copy.deepcopy(cluster) + exec_act_kwargs.exec_ip = cluster["new_master_ip"] + exec_act_kwargs.get_mysql_payload_func = MysqlActPayload.tendb_remotedb_change_master.__name__ + sub_pipeline.add_act( + act_name=_("建立主从关系:新主库指向旧主库 {}".format(exec_act_kwargs.exec_ip)), + act_component_code=ExecuteDBActuatorScriptComponent.code, + kwargs=asdict(exec_act_kwargs), + ) + return sub_pipeline.build_sub_process(sub_name=_("RemoteDB主从节点成对迁移子流程{}".format(exec_act_kwargs.exec_ip))) + + +def remote_node_uninstall_sub_flow(root_id: str, ticket_data: dict, ip: str): + """ + 卸载remotedb 节点下的所有实例 + @param root_id: flow流程的root_id + @param ticket_data: 单据 data 对象 + @param ip: 指定卸载的ip + """ + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + cluster = {"uninstall_ip": ip, "bk_cloud_id": ticket_data["bk_cloud_id"]} + instances = get_remotedb_info(cluster["uninstall_ip"], cluster["bk_cloud_id"]) + sub_pipeline_list = [] + for instance in instances: + cluster["backend_port"] = instance["port"] + sub_pipeline_list.append( + { + "act_name": _("卸载MySQL实例:{}:{}".format(cluster["uninstall_ip"], cluster["backend_port"])), + "act_component_code": ExecuteDBActuatorScriptComponent.code, + "kwargs": asdict( + ExecActuatorKwargs( + exec_ip=cluster["uninstall_ip"], + bk_cloud_id=cluster["bk_cloud_id"], + cluster=cluster, + get_mysql_payload_func=MysqlActPayload.get_uninstall_mysql_payload.__name__, + ) + ), + } + ) + sub_pipeline.add_parallel_acts(sub_pipeline_list) + return sub_pipeline.build_sub_process(sub_name=_("Remote node {} 卸载整机实例".format(cluster["uninstall_ip"]))) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_migrate_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_migrate_flow.py new file mode 100644 index 0000000000..df0a89d5d2 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_migrate_flow.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging +from dataclasses import asdict +from typing import Dict, List, Optional + +from django.utils.translation import ugettext as _ + +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.spider.spider_remote_node_migrate import ( + remote_node_migrate_sub_flow, + remote_node_uninstall_sub_flow, +) +from backend.flow.plugins.components.collections.common.pause import PauseComponent +from backend.flow.plugins.components.collections.mysql.clear_machine import MySQLClearMachineComponent +from backend.flow.plugins.components.collections.mysql.mysql_db_meta import MySQLDBMetaComponent +from backend.flow.utils.mysql.mysql_act_dataclass import ClearMachineKwargs, DBMetaOPKwargs +from backend.flow.utils.spider.spider_db_meta import SpiderDBMeta +from backend.flow.utils.spider.tendb_cluster_info import get_remotedb_info + +logger = logging.getLogger("flow") + + +class TenDBMigrateFlow(object): + """ + TenDB 后端节点主从成对迁移 + """ + + def __init__(self, root_id: str, data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param data : 单据传递参数 + """ + self.root_id = root_id + self.data = data + # todo 初始化数据 + + def tendb_migrate(self): + """ + tendb 迁移 + """ + # 根据已有的实例计算出端口。nodes 中的每一个ip对应一个流程。 + # 根据集群获取版本。 + tendb_migrate_pipeline = Builder(root_id=self.root_id, data=copy.deepcopy(self.data)) + svr_sub_pipeline_list = [] + for node in self.data["nodes"]: + svr_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + node_cluster = { + "cluster_id": node["cluster_id"], + "bk_cloud_id": self.data["bk_cloud_id"], + "bk_biz_id": self.data["bk_biz_id"], + "master_ip": node["master"]["ip"], + "slave_ip": node["slave"]["ip"], + "new_master_ip": node["new_master"]["ip"], + "new_slave_ip": node["new_slave"]["ip"], + } + instances = get_remotedb_info(node["master"]["ip"], node["master"]["bk_cloud_id"]) + ports = [one["port"] for one in instances] + node_cluster["ports"] = ports + # todo 是使用实例的版本,还是集群的版本 + node_cluster["version"] = instances[0]["version"] + install_sub_pipeline_list = [] + install_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + # 阶段1 安装主从库 + # todo 并发调起安装子流程 + install_sub_pipeline.add_act( + act_name=_("写入初始化实例的db_meta元信息"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_add_install_nodes.__name__, + cluster=node_cluster, + is_update_trans_data=True, + ) + ), + ) + install_sub_pipeline_list.append(install_sub_pipeline.build_sub_process(sub_name=_("恢复实例数据 "))) + + # 阶段2 同步数据到新主从库 + sync_data_sub_pipeline_list = [] + for cluster_info in instances: + ins_cluster = copy.deepcopy(cluster_info) + ins_cluster["new_master_ip"] = node["new_master"]["ip"] + ins_cluster["new_slave_ip"] = node["new_slave"]["ip"] + ins_cluster["new_master_port"] = ins_cluster["port"] + ins_cluster["new_slave_port"] = ins_cluster["port"] + ins_cluster["master_ip"] = node["master"]["ip"] + ins_cluster["slave_ip"] = node["slave"]["ip"] + ins_cluster["master_port"] = ins_cluster["port"] + ins_cluster["slave_port"] = ins_cluster["port"] + ins_cluster["backup_target_path"] = "/data/dbbak/{}/{}".format(self.root_id, ins_cluster["port"]) + ins_cluster["cluster_id"] = node["cluster_id"] + ins_cluster["bk_cloud_id"] = self.data["bk_cloud_id"] + + sync_data_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + sync_data_sub_pipeline.add_sub_pipeline( + sub_flow=remote_node_migrate_sub_flow( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), cluster_info=ins_cluster + ) + ) + sync_data_sub_pipeline.add_act( + act_name=_("同步数据完毕,写入数据节点的主从关系相关元数据"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_add_storage_tuple.__name__, + cluster=node_cluster, + is_update_trans_data=True, + ) + ), + ) + sync_data_sub_pipeline_list.append(sync_data_sub_pipeline.build_sub_process(sub_name=_("恢复实例数据 "))) + + # 阶段3 todo 整机切换实例 + switch_sub_pipeline_list = [] + switch_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + switch_sub_pipeline.add_sub_pipeline(sub_flow=_("切换子流程")) + switch_sub_pipeline.add_act( + act_name=_("整机切换完毕后修改元数据指向"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_switch.__name__, + cluster=node_cluster, + is_update_trans_data=True, + ) + ), + ) + switch_sub_pipeline_list.append(switch_sub_pipeline.build_sub_process(sub_name=_("切换remote node 节点"))) + + # 阶段4 主机级别卸载实例,卸载指定ip下的所有实例 + uninstall_db_sub_pipeline_list = [] + for ip in [node["master_ip"], node["slave_ip"]]: + node_cluster["uninstall_ip"] = ip + uninstall_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + uninstall_sub_pipeline.add_sub_pipeline( + sub_flow=remote_node_uninstall_sub_flow( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), ip=ip + ) + ) + # 卸载完毕后修改删除实例信息(整机) 删除元数据 + uninstall_sub_pipeline.add_act( + act_name=_("整机卸载成功后删除元数据"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_remove_storage.__name__, + cluster=node_cluster, + is_update_trans_data=True, + ) + ), + ) + # 下线机器 + uninstall_sub_pipeline.add_act( + act_name=_("清理机器配置"), + act_component_code=MySQLClearMachineComponent.code, + kwargs=asdict( + ClearMachineKwargs( + exec_ip=ip, + bk_cloud_id=self.data["bk_cloud_id"], + ) + ), + ) + uninstall_db_sub_pipeline_list.append( + uninstall_sub_pipeline.build_sub_process(sub_name=_("卸载节点实例{}".format(ip))) + ) + + # 安装实例 + svr_sub_pipeline.add_parallel_acts(install_sub_pipeline_list) + # 同步数据 + svr_sub_pipeline.add_parallel_acts(sync_data_sub_pipeline_list) + # 人工确认切换 + svr_sub_pipeline.add_act(act_name=_("人工确认切换remote节点"), act_component_code=PauseComponent.code, kwargs={}) + svr_sub_pipeline.add_parallel_acts(switch_sub_pipeline_list) + # 人工确认卸载实例 + svr_sub_pipeline.add_act(act_name=_("人工确认卸载实例"), act_component_code=PauseComponent.code, kwargs={}) + svr_sub_pipeline.add_parallel_acts(uninstall_db_sub_pipeline_list) + # 加入并发列表 + svr_sub_pipeline_list.append( + svr_sub_pipeline.build_sub_process( + sub_name=_("成对迁移remote 节点主从实例 {} {}".format(node["master"]["ip"], node["slave"]["ip"])) + ) + ) + tendb_migrate_pipeline.add_parallel_sub_pipeline(sub_flow_list=svr_sub_pipeline_list) + tendb_migrate_pipeline.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_rebalance_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_rebalance_flow.py new file mode 100644 index 0000000000..4eba7c2340 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_remotedb_rebalance_flow.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +import logging +from dataclasses import asdict +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.constants import IP_PORT_DIVIDER +from backend.db_meta.models import Cluster +from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder +from backend.flow.engine.bamboo.scene.mysql.common.common_sub_flow import install_mysql_in_cluster_sub_flow +from backend.flow.engine.bamboo.scene.spider.common.common_sub_flow import remote_migrate_switch_sub_flow +from backend.flow.engine.bamboo.scene.spider.spider_remote_node_migrate import ( + remote_instance_migrate_sub_flow, + remote_node_uninstall_sub_flow, +) +from backend.flow.plugins.components.collections.common.pause import PauseComponent +from backend.flow.plugins.components.collections.mysql.clear_machine import MySQLClearMachineComponent +from backend.flow.plugins.components.collections.mysql.mysql_db_meta import MySQLDBMetaComponent +from backend.flow.utils.mysql.mysql_act_dataclass import ClearMachineKwargs, DBMetaOPKwargs +from backend.flow.utils.spider.spider_db_meta import SpiderDBMeta +from backend.flow.utils.spider.tendb_cluster_info import get_cluster_info + +logger = logging.getLogger("flow") + + +class TenDBRemoteRebalanceFlow(object): + """ + TenDB 后端节点主从成对迁移 + """ + + def __init__(self, root_id: str, ticket_data: Optional[Dict]): + """ + @param root_id : 任务流程定义的root_id + @param ticket_data : 单据传递参数 + """ + self.root_id = root_id + self.ticket_data = ticket_data + self.data = {} + + def tendb_migrate(self): + """ + tendb 迁移 + """ + # 根据已有的实例计算出端口。nodes 中的每一个ip对应一个流程。 + tendb_migrate_pipeline_all = Builder(root_id=self.root_id, data=copy.deepcopy(self.data)) + # 阶段1 获取集群所有信息。计算端口,构建数据。 + tendb_migrate_pipeline_all_list = [] + for info in self.data["infos"]: + self.data = {} + self.data = copy.deepcopy(info) + self.data["bk_cloud_id"] = self.ticket_data["bk_cloud_id"] + self.data["start_port"] = 20000 + self.data["uid"] = self.ticket_data["uid"] + self.data["ticket_type"] = self.ticket_data["ticket_type"] + self.data["bk_biz_id"] = self.ticket_data["bk_biz_id"] + self.data["created_by"] = self.ticket_data["created_by"] + self.data["module"] = self.ticket_data["db_module_id"] + + tendb_migrate_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + + cluster_info = get_cluster_info(self.data["cluster_id"]) + cluster_class = Cluster( + name=cluster_info["cluster"]["name"], + alias=cluster_info["cluster"]["alias"], + immute_domain=cluster_info["cluster"]["immute_domain"], + major_version=cluster_info["cluster"]["major_version"], + status=cluster_info["cluster"]["status"], + region=cluster_info["cluster"]["region"], + phase=cluster_info["cluster"]["phase"], + bk_biz_id=cluster_info["cluster"]["bk_biz_id"], + bk_cloud_id=cluster_info["cluster"]["bk_cloud_id"], + db_module_id=cluster_info["cluster"]["db_module_id"], + cluster_type=cluster_info["cluster"]["cluster_type"], + time_zone=cluster_info["cluster"]["time_zone"], + creator=self.data["created_by"], + updater=self.data["created_by"], + ) + shards = len(cluster_info["shards"]) + if self.data["remote_shard_num"] * len(self.data["remote_group"]) != shards: + return + cluster_info["ports"] = [] + for port in range(self.data["start_port"], self.data["start_port"] + self.data["remote_shard_num"]): + cluster_info["ports"].append(port) + + shard_ids = copy.deepcopy(cluster_info["shard_ids"]) + for node in self.data["remote_group"]: + for port in cluster_info["ports"]: + master = { + "ip": node["master"]["ip"], + "port": port, + "bk_cloud_id": self.data["bk_cloud_id"], + "instance": "{}{}{}".format(node["master"]["ip"], IP_PORT_DIVIDER, port), + } + slave = { + "ip": node["slave"]["ip"], + "port": port, + "bk_cloud_id": self.data["bk_cloud_id"], + "instance": "{}{}{}".format(node["slave"]["ip"], IP_PORT_DIVIDER, port), + } + shard_id = shard_ids.pop(0) + cluster_info["shards"][shard_id]["new_master"] = master + cluster_info["shards"][shard_id]["new_slave"] = slave + + # 阶段2 安装实例并写入数据 + install_sub_pipeline_list = [] + for node in self.data["remote_group"]: + install_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + install_sub_pipeline.add_sub_pipeline( + sub_flow=install_mysql_in_cluster_sub_flow( + uid=self.data["uid"], + root_id=self.root_id, + cluster=cluster_class, + new_mysql_list=[node["master"]["ip"], node["slave"]["ip"]], + install_ports=cluster_info["ports"], + ) + ) + cluster = { + "new_master_ip": node["master"]["ip"], + "new_slave_ip": node["slave"]["ip"], + "cluster_id": cluster_info["cluster_id"], + "bk_cloud_id": cluster_info["bk_cloud_id"], + "bk_biz_id": cluster_info["bk_biz_id"], + "ports": cluster_info["ports"], + "version": cluster_info["cluster"]["major_version"], + } + install_sub_pipeline.add_act( + act_name=_("写入初始化实例的db_meta元信息"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_add_install_nodes.__name__, + cluster=cluster, + is_update_trans_data=True, + ) + ), + ) + install_sub_pipeline_list.append(install_sub_pipeline.build_sub_process(sub_name=_("安装remote主从节点"))) + + # 阶段3 逐个实例同步数据到新主从库 + sync_data_sub_pipeline_list = [] + for shard_id, node in cluster_info["shards"]: + ins_cluster = copy.deepcopy(cluster_info["cluster"]) + ins_cluster["new_master_ip"] = node["new_master"]["ip"] + ins_cluster["new_slave_ip"] = node["new_slave"]["ip"] + ins_cluster["new_master_port"] = node["new_master"]["port"] + ins_cluster["new_slave_port"] = node["new_slave"]["port"] + ins_cluster["master_ip"] = node["master"]["ip"] + ins_cluster["slave_ip"] = node["slave"]["ip"] + ins_cluster["master_port"] = node["master"]["port"] + ins_cluster["slave_port"] = node["slave"]["port"] + ins_cluster["backup_target_path"] = "/data/dbbak/{}/{}".format(self.root_id, ins_cluster["port"]) + ins_cluster["shard_id"] = shard_id + ins_cluster["change_master_force"] = False + sync_data_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + sync_data_sub_pipeline.add_sub_pipeline( + sub_flow=remote_instance_migrate_sub_flow( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), cluster_info=ins_cluster + ) + ) + sync_data_sub_pipeline.add_act( + act_name=_("同步数据完毕,写入数据节点的主从关系相关元数据"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_add_storage_tuple.__name__, + cluster=ins_cluster, + is_update_trans_data=True, + ) + ), + ) + sync_data_sub_pipeline_list.append(sync_data_sub_pipeline.build_sub_process(sub_name=_("恢复实例数据"))) + + # 阶段4 切换 + switch_sub_pipeline_list = [] + shard_list = [] + for shard_id, node in cluster_info["shards"]: + shard_cluster = { + "old_master": node["master"]["instance"], + "old_slave": node["slave"]["instance"], + "new_master": node["master"]["instance"], + "new_slave": node["slave"]["instance"], + } + shard_list.append(shard_cluster) + switch_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + switch_sub_pipeline.add_sub_pipeline( + sub_flow=remote_migrate_switch_sub_flow( + uid=self.data["uid"], + root_id=self.data["root_id"], + cluster=cluster_class, + migrate_tuples=shard_list, + ) + ) + switch_sub_pipeline.add_act( + act_name=_("整集群切换完毕后修改元数据指向"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.tendb_remotedb_rebalance_switch.__name__, + cluster=cluster_info, + is_update_trans_data=True, + ) + ), + ) + switch_sub_pipeline_list.append(switch_sub_pipeline.build_sub_process(sub_name=_("切换remote node 节点"))) + + # 阶段5: 主机级别卸载实例,卸载指定ip下的所有实例 + uninstall_svr_sub_pipeline_list = [] + machines = cluster_info["masters"] + cluster_info["slaves"] + for ip in machines: + uninstall_svr_sub_pipeline = SubBuilder(root_id=self.root_id, data=copy.deepcopy(self.data)) + ins_cluster = {"uninstall_ip": ip} + uninstall_svr_sub_pipeline.add_sub_pipeline( + sub_flow=remote_node_uninstall_sub_flow( + root_id=self.root_id, ticket_data=copy.deepcopy(self.data), ip=ip + ) + ) + uninstall_svr_sub_pipeline.add_act( + act_name=_("整机卸载成功后删除元数据"), + act_component_code=MySQLDBMetaComponent.code, + kwargs=asdict( + DBMetaOPKwargs( + db_meta_class_func=SpiderDBMeta.remotedb_migrate_remove_storage.__name__, + cluster=ins_cluster, + is_update_trans_data=True, + ) + ), + ) + uninstall_svr_sub_pipeline.add_act( + act_name=_("清理机器配置"), + act_component_code=MySQLClearMachineComponent.code, + kwargs=asdict( + ClearMachineKwargs( + exec_ip=ip, + bk_cloud_id=self.data["bk_cloud_id"], + ) + ), + ) + uninstall_svr_sub_pipeline_list.append( + uninstall_svr_sub_pipeline.add_sub_pipeline(_("卸载remote节点{}".format(ip))) + ) + # 安装实例 + tendb_migrate_pipeline.add_parallel_sub_pipeline(sub_flow_list=install_sub_pipeline_list) + # 数据同步 + tendb_migrate_pipeline.add_parallel_sub_pipeline(sub_flow_list=sync_data_sub_pipeline_list) + # 人工确认切换迁移实例 + tendb_migrate_pipeline.add_act(act_name=_("人工确认切换"), act_component_code=PauseComponent.code, kwargs={}) + # 切换迁移实例 + tendb_migrate_pipeline.add_parallel_sub_pipeline(sub_flow_list=switch_sub_pipeline_list) + # 卸载流程人工确认 + tendb_migrate_pipeline.add_act(act_name=_("人工确认卸载实例"), act_component_code=PauseComponent.code, kwargs={}) + # 卸载remote节点 + tendb_migrate_pipeline.add_parallel_sub_pipeline(uninstall_svr_sub_pipeline_list) + tendb_migrate_pipeline_all_list.append( + tendb_migrate_pipeline.build_sub_process(_("集群迁移{}").format(self.data["cluster_"])) + ) + # 运行流程 + tendb_migrate_pipeline_all.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/controller/spider.py b/dbm-ui/backend/flow/engine/controller/spider.py index 960fdf3e44..76779c87c8 100644 --- a/dbm-ui/backend/flow/engine/controller/spider.py +++ b/dbm-ui/backend/flow/engine/controller/spider.py @@ -22,9 +22,12 @@ from backend.flow.engine.bamboo.scene.spider.spider_cluster_enable_deploy import SpiderClusterEnableFlow from backend.flow.engine.bamboo.scene.spider.spider_cluster_flashback import TenDBClusterFlashbackFlow from backend.flow.engine.bamboo.scene.spider.spider_cluster_full_backup import TenDBClusterFullBackupFlow +from backend.flow.engine.bamboo.scene.spider.spider_cluster_rollback_flow import TenDBRollBackDataFlow from backend.flow.engine.bamboo.scene.spider.spider_cluster_truncate_database import SpiderTruncateDatabaseFlow from backend.flow.engine.bamboo.scene.spider.spider_partition import SpiderPartitionFlow from backend.flow.engine.bamboo.scene.spider.spider_reduce_nodes import TenDBClusterReduceNodesFlow +from backend.flow.engine.bamboo.scene.spider.spider_remotedb_migrate_flow import TenDBMigrateFlow +from backend.flow.engine.bamboo.scene.spider.spider_remotedb_rebalance_flow import TenDBRemoteRebalanceFlow from backend.flow.engine.bamboo.scene.spider.spider_rename_database_flow import SpiderRenameDatabaseFlow from backend.flow.engine.bamboo.scene.spider.spider_slave_cluster_deploy import TenDBSlaveClusterApplyFlow from backend.flow.engine.controller.base import BaseController @@ -152,3 +155,24 @@ def tendbcluster_remote_fail_over_scene(self): """ flow = RemoteMasterFailOverFlow(root_id=self.root_id, data=self.ticket_data) flow.remote_fail_over() + + def migrate_remotedb(self): + """ + remote 节点1:1迁移 + """ + flow = TenDBMigrateFlow(root_id=self.root_id, data=self.ticket_data) + flow.tendb_migrate() + + def tendb_cluster_remote_rebalance(self): + """ + remote 节点扩缩容同步数据(重均衡) + """ + flow = TenDBRemoteRebalanceFlow(root_id=self.root_id, ticket_data=self.ticket_data) + flow.tendb_migrate() + + def tendb_cluster_rollback_data(self): + """ + tendb cluster 定点回档 + """ + flow = TenDBRollBackDataFlow(root_id=self.root_id, data=self.ticket_data) + flow.tendb_rollback_data() diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index cb26dd96d4..7121b68806 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -141,7 +141,9 @@ from backend.flow.views.spider_sql_import import SpiderSqlImportSceneApiView from backend.flow.views.sql_semantic_check import SqlSemanticCheckSceneApiView from backend.flow.views.tendb_cluster_remote_fail_over import RemoteFailOverSceneApiView +from backend.flow.views.tendb_cluster_remote_rebalance import RemoteRebalanceSceneApiView from backend.flow.views.tendb_cluster_remote_switch import RemoteSwitchSceneApiView +from backend.flow.views.tendb_cluster_rollback_data import TendbClusterRollbackDataSceneApiView urlpatterns = [ url(r"^scene/rollback$", RollbackPipelineApiView.as_view()), @@ -293,4 +295,7 @@ # tendbcluster 切换类 url(r"^scene/tendb_cluster_remote_switch$", RemoteSwitchSceneApiView.as_view()), url(r"^scene/tendb_cluster_remote_fail_over$", RemoteFailOverSceneApiView.as_view()), + # remote 节点扩缩容 + url(r"^scene/tendb_cluster_remote_rebalance$", RemoteRebalanceSceneApiView.as_view()), + url(r"^scene/tendb_cluster_rollback_data$", TendbClusterRollbackDataSceneApiView.as_view()), ] diff --git a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py index 2d828421c1..9cfcd5128c 100644 --- a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py +++ b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py @@ -43,6 +43,7 @@ DBActuatorActionEnum, DBActuatorTypeEnum, MediumEnum, + MysqlChangeMasterType, NameSpaceEnum, ) from backend.flow.engine.bamboo.scene.common.get_real_version import get_mysql_real_version, get_spider_real_version @@ -1888,3 +1889,86 @@ def tendb_cluster_remote_migrate(self, **kwargs): }, }, } + + def tendb_restore_remotedb_payload(self, **kwargs): + """ + tendb 恢复remote实例 + """ + index_file = os.path.basename(kwargs["trans_data"]["backupinfo"]["index_file"]) + payload = { + "db_type": DBActuatorTypeEnum.MySQL.value, + "action": DBActuatorActionEnum.RestoreSlave.value, + "payload": { + "general": {"runtime_account": self.account}, + "extend": { + "work_dir": self.cluster["file_target_path"], + "backup_dir": self.cluster["file_target_path"], + "backup_files": { + # "full": None, + "index": [index_file], + # "priv": None, + }, + "tgt_instance": { + # "host": self.cluster["new_slave_ip"], + "host": self.cluster["restore_ip"], + "port": self.cluster["restore_port"], + "user": self.account["admin_user"], + "pwd": self.account["admin_pwd"], + "socket": None, + "charset": self.cluster["charset"], + "options": "", + }, + "src_instance": {"host": self.cluster["source_ip"], "port": self.cluster["source_port"]}, + "change_master": self.cluster["change_master"], + "work_id": "", + }, + }, + } + return payload + + def tendb_grant_remotedb_repl_user(self, **kwargs) -> dict: + """ + 拼接创建repl账号的payload参数(在master节点执行) + """ + return { + "db_type": DBActuatorTypeEnum.MySQL.value, + "action": DBActuatorActionEnum.GrantRepl.value, + "payload": { + "general": {"runtime_account": self.account}, + "extend": { + "host": self.cluster["target_ip"], + "port": self.cluster["target_port"], + "repl_hosts": [self.cluster["repl_ip"]], + }, + }, + } + + def tendb_remotedb_change_master(self, **kwargs) -> dict: + """ + 拼接同步主从的payload参数(在slave节点执行), 获取master的位点信息的场景通过上下文获取 + todo 后续可能支持多角度传入master的位点信息的拼接 + """ + if self.cluster["change_master_type"] == MysqlChangeMasterType.MASTERSTATUS.value: + bin_file = kwargs["trans_data"]["show_master_status_info"]["bin_file"] + bin_position = kwargs["trans_data"]["show_master_status_info"]["bin_position"] + else: + bin_file = kwargs["trans_data"]["change_master_info"]["master_log_file"] + bin_position = kwargs["trans_data"]["change_master_info"]["master_log_pos"] + return { + "db_type": DBActuatorTypeEnum.MySQL.value, + "action": DBActuatorActionEnum.ChangeMaster.value, + "payload": { + "general": {"runtime_account": self.account}, + "extend": { + "host": self.cluster["repl_ip"], + "port": self.cluster["repl_port"], + "master_host": self.cluster["target_ip"], + "master_port": self.cluster["target_port"], + "is_gtid": False, + "max_tolerate_delay": 0, + "force": self.cluster["change_master_force"], + "bin_file": bin_file, + "bin_position": bin_position, + }, + }, + } diff --git a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py index 9c5c14d15c..e57d02dfe3 100644 --- a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py +++ b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py @@ -9,7 +9,10 @@ """ import logging +from django.db import transaction + from backend.db_meta.api.cluster.tendbcluster.handler import TenDBClusterClusterHandler +from backend.db_meta.api.cluster.tendbcluster.remotedb_node_migrate import TenDBClusterMigrateRemoteDb from backend.db_meta.enums import ClusterEntryRole from backend.db_meta.models import Cluster from backend.flow.utils.dict_to_dataclass import dict_to_dataclass @@ -145,3 +148,74 @@ def remote_switch(self): switch_tuples=self.global_data["switch_tuples"], ) return True + + def remotedb_migrate_add_install_nodes(self): + """ + remotedb 成对迁移添加初始化节点元数据 + """ + TenDBClusterMigrateRemoteDb.storage_create( + cluster_id=self.cluster["cluster_id"], + master_ip=self.cluster["new_master_ip"], + slave_ip=self.cluster["new_slave_ip"], + ports=self.cluster["ports"], + creator=self.global_data["created_by"], + mysql_version=self.cluster["version"], + resource_spec=self.global_data["resource_spec"], + ) + return True + + def remotedb_migrate_add_storage_tuple(self): + """ + 写入真实的主从对应关系 + 新从库->新主库 + 新主库->旧主库(这条关系链在切换完毕后需要断开) + """ + new_slave_to_new_master = { + "master": {"ip": self.cluster["new_master_ip"], "port": self.cluster["new_master_port"]}, + "slave": {"ip": self.cluster["new_slave_ip"], "port": self.cluster["new_slave_port"]}, + } + TenDBClusterMigrateRemoteDb.add_storage_tuple( + cluster_id=self.cluster["cluster_id"], storage=new_slave_to_new_master + ) + new_master_to_old_master = { + "slave": {"ip": self.cluster["new_master_ip"], "port": self.cluster["new_master_port"]}, + "master": {"ip": self.cluster["master_ip"], "port": self.cluster["master_port"]}, + } + TenDBClusterMigrateRemoteDb.add_storage_tuple( + cluster_id=self.cluster["cluster_id"], storage=new_master_to_old_master + ) + # todo 是否修改new_master角色为中继状态 + + def remotedb_migrate_switch(self): + for port in self.cluster["ports"]: + source = { + "master": {"ip": self.cluster["master_ip"], "port": port}, + "slave": {"ip": self.cluster["slave_ip"], "port": port}, + } + target = { + "master": {"ip": self.cluster["new_master_ip"], "port": port}, + "slave": {"ip": self.cluster["new_slave_ip"], "port": port}, + } + TenDBClusterMigrateRemoteDb.switch_remote_node( + cluster_id=self.cluster["cluster_id"], source=source, target=target + ) + + def remotedb_migrate_remove_storage(self): + TenDBClusterMigrateRemoteDb.uninstall_storage( + cluster_id=self.cluster["cluster_id"], ip=self.cluster["uninstall_ip"] + ) + + @transaction.atomic + def tendb_remotedb_rebalance_switch(self): + for node in self.cluster["shards"]: + source = { + "master": {"ip": node["master"]["ip"], "port": node["master"]["port"]}, + "slave": {"ip": node["slave"]["ip"], "port": node["slave"]["port"]}, + } + target = { + "master": {"ip": node["new_master"]["ip"], "port": node["new_master"]["port"]}, + "slave": {"ip": node["new_slave"]["ip"], "port": node["new_slave"]["port"]}, + } + TenDBClusterMigrateRemoteDb.switch_remote_node( + cluster_id=self.cluster["cluster_id"], source=source, target=target + ) diff --git a/dbm-ui/backend/flow/utils/spider/tendb_cluster_info.py b/dbm-ui/backend/flow/utils/spider/tendb_cluster_info.py new file mode 100644 index 0000000000..571a87aec4 --- /dev/null +++ b/dbm-ui/backend/flow/utils/spider/tendb_cluster_info.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy + +from backend.db_meta.models import Cluster, StorageInstance + + +def get_remotedb_info(ip: str, bk_cloud_id: int) -> list: + nodes = [] + storage_instances = StorageInstance.objects.filter(machine__ip=ip, machine__bk_cloud_id=bk_cloud_id) + for one in storage_instances: + # storage = one.__dict__ + storage = { + "version": one.version, + "port": one.port, + "bk_biz_id": one.bk_biz_id, + "status": one.status, + "instance_role": one.instance_role, + "phase": one.phase, + "bk_instance_id": one.bk_instance_id, + "db_module_id": one.db_module_id, + "ip": ip, + "bk_cloud_id": bk_cloud_id, + } + nodes.append(storage) + return nodes + + +def get_rollback_clusters_info( + source_cluster_id: int, + target_cluster_id: int, +): + cluster_info = {"shards": {}, "source_spiders": [], "target_spiders": []} + source_obj = Cluster.objects.get(id=source_cluster_id) + target_obj = Cluster.objects.get(id=target_cluster_id) + source_spiders = source_obj.proxyinstance_set.filter() + target_spiders = target_obj.proxyinstance_set.filter() + for spider in source_spiders: + cluster_info["source_spiders"].append(spider.simple_desc) + for spider in target_spiders: + cluster_info["target_spiders"].append(spider.simple_desc) + + cluster_info["source"] = source_obj.to_dict() + cluster_info["target"] = target_obj.to_dict() + shards = source_obj.tendbclusterstorageset_set.filter() + new_shards = target_obj.tendbclusterstorageset_set.filter() + if len(shards) != len(new_shards): + return None + for shard in shards: + master_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.ejector_id) + slave_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.receiver_id) + shards_info = {"master": master_obj.simple_desc, "slave": slave_obj.simple_desc} + cluster_info["shards"][shard.shard_id] = shards_info + + for shard in new_shards: + master_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.ejector_id) + slave_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.receiver_id) + shards_info = {"new_master": master_obj.simple_desc, "new_slave": slave_obj.simple_desc} + if shard.shard_id in cluster_info["shards"]: + cluster_info["shards"][shard.shard_id] = shards_info + else: + return None + return cluster_info + + +def get_cluster_info(cluster_id: int): + """ + 获取集群相关信息 + """ + cluster_info = { + "shards": {}, + "spiders": [], + "shard_ids": [], + "masters": [], + "slaves": [], + "master_slave_map": {}, + } + source_obj = Cluster.objects.get(id=cluster_id) + source_spiders = source_obj.proxyinstance_set.filter() + for spider in source_spiders: + cluster_info["spiders"].append(spider.simple_desc) + cluster_info["cluster"] = source_obj.to_dict() + cluster_info["cluster"]["cluster_id"] = source_obj.id + cluster_info["cluster_id"] = source_obj.id + cluster_info["bk_cloud_id"] = source_obj.bk_cloud_id + cluster_info["bk_biz_id"] = source_obj.bk_biz_id + shards = source_obj.tendbclusterstorageset_set.filter() + for shard in shards: + master_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.ejector_id) + slave_obj = StorageInstance.objects.get(id=shard.storage_instance_tuple.receiver_id) + shards_info = {"master": master_obj.simple_desc, "slave": slave_obj.simple_desc} + cluster_info["shards"][shard.shard_id] = shards_info + cluster_info["shard_ids"].append(shard.shard_id) + cluster_info["masters"].append(master_obj.machine.ip) + cluster_info["slaves"].append(slave_obj.machine.ip) + cluster_info["master_slave_map"][master_obj.machine.ip] = slave_obj.machine.ip + cluster_info["shard_ids"].sort() + cluster_info["masters"] = list(set(copy.deepcopy(cluster_info["masters"]))) + cluster_info["slaves"] = list(set(copy.deepcopy(cluster_info["slaves"]))) + cluster_info["masters"].sort() + cluster_info["slaves"].sort() + return cluster_info diff --git a/dbm-ui/backend/flow/views/spider_migrage_remotedb.py b/dbm-ui/backend/flow/views/spider_migrage_remotedb.py new file mode 100644 index 0000000000..632fcb97af --- /dev/null +++ b/dbm-ui/backend/flow/views/spider_migrage_remotedb.py @@ -0,0 +1,25 @@ +import logging +import uuid + +from rest_framework.response import Response + +from backend.flow.engine.controller.spider import SpiderController +from backend.flow.views.base import FlowTestView + +logger = logging.getLogger("root") + + +class SpiderMigrateRemoteDbSceneApiView(FlowTestView): + """ + api: /apis/v1/flow/scene/install_spider_cluster + params: + } + """ + + @staticmethod + def post(request): + # logger.info("spider remotedb 成对迁移") + root_id = uuid.uuid1().hex + test = SpiderController(root_id=root_id, ticket_data=request.data) + test.migrate_remotedb() + return Response({"root_id": root_id}) diff --git a/dbm-ui/backend/flow/views/tendb_cluster_remote_rebalance.py b/dbm-ui/backend/flow/views/tendb_cluster_remote_rebalance.py new file mode 100644 index 0000000000..791d5b65b8 --- /dev/null +++ b/dbm-ui/backend/flow/views/tendb_cluster_remote_rebalance.py @@ -0,0 +1,32 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import logging +import uuid + +from rest_framework.response import Response + +from backend.flow.engine.controller.spider import SpiderController +from backend.flow.views.base import FlowTestView + +logger = logging.getLogger("root") + + +class RemoteRebalanceSceneApiView(FlowTestView): + """ + api: /apis/v1/flow/scene/tendb_cluster_rollback_data + params: + """ + + def post(self, request): + root_id = uuid.uuid1().hex + test = SpiderController(root_id=root_id, ticket_data=request.data) + test.tendb_cluster_remote_rebalance() + return Response({"root_id": root_id}) diff --git a/dbm-ui/backend/flow/views/tendb_cluster_rollback_data.py b/dbm-ui/backend/flow/views/tendb_cluster_rollback_data.py new file mode 100644 index 0000000000..112645ca64 --- /dev/null +++ b/dbm-ui/backend/flow/views/tendb_cluster_rollback_data.py @@ -0,0 +1,32 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import logging +import uuid + +from rest_framework.response import Response + +from backend.flow.engine.controller.spider import SpiderController +from backend.flow.views.base import FlowTestView + +logger = logging.getLogger("root") + + +class TendbClusterRollbackDataSceneApiView(FlowTestView): + """ + api: /apis/v1/flow/scene/tendb_cluster_rollback_data + params: + """ + + def post(self, request): + root_id = uuid.uuid1().hex + test = SpiderController(root_id=root_id, ticket_data=request.data) + test.tendb_cluster_rollback_data() + return Response({"root_id": root_id}) From bdc457cb21152caf470892f7bc497613df2cd174 Mon Sep 17 00:00:00 2001 From: xfwduke Date: Thu, 13 Jul 2023 14:29:12 +0800 Subject: [PATCH 139/476] =?UTF-8?q?feat(mysql):=20=E7=94=A8=E7=A1=AC?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E7=9A=84=E6=96=B9=E5=BC=8F=20drop=20table=20?= =?UTF-8?q?close=20#445?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mysql/db-tools/dbactuator/.gitignore | 3 +- dbm-services/mysql/db-tools/dbactuator/go.mod | 1 + dbm-services/mysql/db-tools/dbactuator/go.sum | 2 + .../internal/subcmd/mysqlcmd/cmd.go | 1 + .../internal/subcmd/mysqlcmd/drop_table.go | 100 +++ .../pkg/components/mysql/drop_large_table.go | 70 -- .../pkg/components/mysql/drop_table.go | 531 ++++++++++++++ .../identifiertrans/filename_to_tablename.go | 68 ++ .../internal/tables/0C00_05FF.go | 161 +++++ .../internal/tables/1E00_1FFF.go | 68 ++ .../internal/tables/2160_217F.go | 15 + .../internal/tables/24B0_24EF.go | 19 + .../internal/tables/FF20_FF5F.go | 19 + .../internal/tables/Hex_Lo_Digit.go | 48 ++ .../identifiertrans/internal/tables/To_UNI.go | 677 ++++++++++++++++++ .../identifiertrans/internal/tables/init.go | 32 + .../internal/tables/safe_char.go | 20 + .../identifiertrans/tablename_to_filename.go | 50 ++ .../ibdstatistic/ibd_statistic.go | 2 +- 19 files changed, 1815 insertions(+), 72 deletions(-) create mode 100644 dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/drop_table.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_large_table.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_table.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/filename_to_tablename.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/0C00_05FF.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/1E00_1FFF.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/2160_217F.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/24B0_24EF.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/FF20_FF5F.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/Hex_Lo_Digit.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/To_UNI.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/init.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/safe_char.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/tablename_to_filename.go diff --git a/dbm-services/mysql/db-tools/dbactuator/.gitignore b/dbm-services/mysql/db-tools/dbactuator/.gitignore index 1a34a6ea74..01b81f4b16 100644 --- a/dbm-services/mysql/db-tools/dbactuator/.gitignore +++ b/dbm-services/mysql/db-tools/dbactuator/.gitignore @@ -24,4 +24,5 @@ conf/ sync_test.sh .vscode/ scripts/upload_media.sh -scripts/upload.sh \ No newline at end of file +scripts/upload.sh +localtest/ \ No newline at end of file diff --git a/dbm-services/mysql/db-tools/dbactuator/go.mod b/dbm-services/mysql/db-tools/dbactuator/go.mod index 6dec465d9e..3f8483c119 100644 --- a/dbm-services/mysql/db-tools/dbactuator/go.mod +++ b/dbm-services/mysql/db-tools/dbactuator/go.mod @@ -11,6 +11,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/shirou/gopsutil/v3 v3.23.2 github.com/spf13/cobra v1.7.0 + golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb gopkg.in/ini.v1 v1.67.0 ) diff --git a/dbm-services/mysql/db-tools/dbactuator/go.sum b/dbm-services/mysql/db-tools/dbactuator/go.sum index 37021fa587..5f61c466e9 100644 --- a/dbm-services/mysql/db-tools/dbactuator/go.sum +++ b/dbm-services/mysql/db-tools/dbactuator/go.sum @@ -119,6 +119,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb h1:xIApU0ow1zwMa2uL1VDNeQlNVFTWMQxZUZCMDy0Q4Us= +golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go index cefa08d6a3..fb238ae709 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go @@ -45,6 +45,7 @@ func NewMysqlCommand() *cobra.Command { NewInstallMySQLMonitorCommand(), NewExecPartitionSQLCommand(), NewBackupDemandCommand(), + NewDropTableCommand(), }, }, { diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/drop_table.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/drop_table.go new file mode 100644 index 0000000000..b3212f42e4 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/drop_table.go @@ -0,0 +1,100 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package mysqlcmd + +import ( + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/internal/subcmd" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql" + "dbm-services/mysql/db-tools/dbactuator/pkg/util" + "fmt" + + "github.com/spf13/cobra" +) + +type DropTableAct struct { + *subcmd.BaseOptions + Service mysql.DropTableComp +} + +const ( + DropTable = "drop-table" +) + +func NewDropTableCommand() *cobra.Command { + act := DropTableAct{ + BaseOptions: subcmd.GBaseOptions, + } + + cmd := &cobra.Command{ + Use: DropTable, + Short: "删除表", + Example: fmt.Sprintf( + `dbactuator mysql %s %s %s`, + DropTable, subcmd.CmdBaseExampleStr, subcmd.ToPrettyJson(act.Service.Example())), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(act.Validate()) + util.CheckErr(act.Init()) + util.CheckErr(act.Run()) + }, + } + return cmd +} + +func (c *DropTableAct) Validate() (err error) { + return c.BaseOptions.Validate() +} + +func (c *DropTableAct) Init() (err error) { + if err = c.Deserialize(&c.Service.Params); err != nil { + logger.Error("DeserializeAndValidate err %s", err.Error()) + return err + } + c.Service.GeneralParam = subcmd.GeneralRuntimeParam + logger.Info("extend params: %s", c.Service.Params) + return nil +} + +func (c *DropTableAct) Run() (err error) { + steps := subcmd.Steps{ + { + FunName: "初始化", + Func: c.Service.Init, + }, + { + FunName: "执行前检查", + Func: c.Service.PreCheck, + }, + { + FunName: "查找数据文件", + Func: c.Service.FindDatafiles, + }, + { + FunName: "建立硬连接", + Func: c.Service.MakeHardlink, + }, + { + FunName: "删除表", + Func: c.Service.DropTable, + }, + { + FunName: "查找遗留硬连接", + Func: c.Service.FindLegacyHardlink, + }, + { + FunName: "删除硬连接", + Func: c.Service.DeleteHardlink, + }, + } + if err := steps.Run(); err != nil { + return err + } + logger.Info("删表完成") + return nil +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_large_table.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_large_table.go deleted file mode 100644 index 3eb388313c..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_large_table.go +++ /dev/null @@ -1,70 +0,0 @@ -package mysql - -import ( - "fmt" - - "dbm-services/mysql/db-tools/dbactuator/pkg/components" -) - -// DropLargeTableComp TODO -type DropLargeTableComp struct { - GeneralParam *components.GeneralParam `json:"general"` - Params DropTableParam `json:"extend"` -} - -// DropTableParam godoc -// 1. show create table -// 2. rename table, create table -// 3. 做硬链接 -// 4. drop table -// 5. 删除硬链和原始文件 -type DropTableParam struct { - Database string `json:"database" validate:"required"` - Tables []string `json:"tables" validate:"required"` - LargeTable bool `json:"large_table"` - // 每秒删除速度 MB/s - BWLimitMB int `json:"bwlimit_mb"` - // 超过多少 MB 算大文件,大文件采用 trunc 限速删除 - LargeTableSizeMB int `json:"large_table_size_mb"` - // 是否保留表结构,相当于 truncate table - KeepSchema bool `json:"keep_schema"` - - // "table1" - fileList map[string][]*linkFiles -} - -type linkFiles struct { - srcFile string - destFile string -} - -// select @@datadir -// select SPACE,NAME,FILE_SIZE from INNODB_SYS_TABLESPACES where NAME like 'query_analyzer/%' -// query_analyzer/query_history#P#p202206 .ibd -// - -func (d *DropTableParam) dropInnodbTable() error { - // innodb_file_per_table - - for _, fileList := range d.fileList { - for _, file := range fileList { - file.destFile = fmt.Sprintf("%s.__drop__", file.srcFile) - // osutil.MakeHardLink(file.srcFile, file.destFile) - // osutil.TruncateFile(file.srcFile, d.BWLimit) - } - } - - return nil -} - -func dropTokudbTable() error { - return nil -} - -func dropMyisamTable() error { - return nil -} - -func dropRocksdbTable() error { - return nil -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_table.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_table.go new file mode 100644 index 0000000000..3e9aacd1d6 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/drop_table.go @@ -0,0 +1,531 @@ +package mysql + +import ( + "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/pkg/components" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/common" + "dbm-services/mysql/db-tools/dbactuator/pkg/native" + "dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans" + "dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil" + "fmt" + "io/fs" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/jmoiron/sqlx" + "github.com/pkg/errors" + "golang.org/x/exp/slices" +) + +// DropTableComp 删表 +type DropTableComp struct { + GeneralParam *components.GeneralParam `json:"general"` + Params *DropTableParam `json:"extend"` + DropTableContext +} + +// DropTableParam 删表参数 +/* +Init->PreCheck->FindDatafiles->MakeHardLink->DropTable->FindLegacyHardlink->DeleteHardlink +代替 mysql 的 drop table +当 LimitSpeed == True 时 +DeleteHardlink 会按 BWLimitMB 的速度限制删除文件 +*/ +type DropTableParam struct { + Database string `json:"database" validate:"required"` + Tables []string `json:"tables" validate:"required"` + LimitSpeed bool `json:"limit_speed"` + BWLimitMB int `json:"bw_limit_mb"` + Host string `json:"host"` + Port int `json:"port"` +} + +type tableInfo struct { + tableName string + tableSchema string + engine string + tableIds []int + spaces []int + datafiles []string // 带库表路径的文件名,完整路径还需要加上 $datadir + linkfiles []string // 带库表路径的文件名,完整路径还需要加上 $datadir +} + +type DropTableContext struct { + db *sqlx.DB + dataDir string + tableInfos map[string]*tableInfo + innodbSysTables string + innodbSysDatafiles string +} + +func (d *DropTableComp) Init() (err error) { + d.tableInfos = make(map[string]*tableInfo) + + instObj := &native.InsObject{ + Host: d.Params.Host, + Port: d.Params.Port, + User: d.GeneralParam.RuntimeAccountParam.AdminUser, + Pwd: d.GeneralParam.RuntimeAccountParam.AdminPwd, + } + dbWorker, err := instObj.Conn() + if err != nil { + return err + } + d.db = dbWorker.GetSqlxDb() + + err = d.db.Get(&d.dataDir, `SELECT @@datadir`) + if err != nil { + return err + } + + var versionStr string + err = d.db.Get(&versionStr, `SELECT @@VERSION`) + if err != nil { + return err + } + + mysqlVersion := cmutil.MySQLVersionParse(versionStr) + if mysqlVersion < 5007000 { + return fmt.Errorf("%s not support", versionStr) + } + + if mysqlVersion < 8000000 { + d.innodbSysTables = `INNODB_SYS_TABLES` + d.innodbSysDatafiles = `INNODB_SYS_DATAFILES` + } else { + d.innodbSysTables = `INNODB_TABLES` + d.innodbSysDatafiles = `INNODB_DATAFILES` + } + + q, args, err := sqlx.In( + `SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA=? AND TABLE_NAME IN (?)`, + d.Params.Database, + d.Params.Tables) + if err != nil { + return err + } + + /* + 不存在的表不会写入 tableInfos + 所以整个过程是幂等的 + */ + var res []struct { + TableSchema string `db:"TABLE_SCHEMA"` + TableName string `db:"TABLE_NAME"` + Engine string `db:"ENGINE"` + } + err = d.db.Select(&res, d.db.Rebind(q), args...) + if err != nil { + return err + } + + for _, ele := range res { + innerName := fmt.Sprintf("%s/%s", ele.TableSchema, ele.TableName) + engine := strings.ToLower(ele.Engine) + d.tableInfos[innerName] = &tableInfo{ + tableName: ele.TableName, + tableSchema: ele.TableSchema, + engine: engine, + tableIds: []int{}, + spaces: []int{}, + datafiles: []string{}, + linkfiles: []string{}, + } + } + return nil +} + +func (d *DropTableComp) PreCheck() (err error) { + for innerName, info := range d.tableInfos { + switch info.engine { + case "innodb": + err = d.preCheckInnodb(innerName, info) + if err != nil { + return err + } + case "myisam": + err = d.preCheckMyIsam(innerName, info) + if err != nil { + return err + } + default: + return fmt.Errorf("engine %s not support", info.engine) + } + } + + return nil +} + +func (d *DropTableComp) preCheckInnodb(innerName string, info *tableInfo) (err error) { + var res []*struct { + TableId int `db:"TABLE_ID"` + Name string `db:"NAME"` + Space int `db:"SPACE"` + SpaceType string `db:"SPACE_TYPE"` + IdentifierName string + /* + Name 是 filename set 格式,比如库表 `db-a.tb-b` 的 Name 是 db@002da/tb@002db + IdentifierName 是还原成 `db-a/tb-a` + */ + } + err = d.db.Select( + &res, + fmt.Sprintf( + `SELECT TABLE_ID, NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.%s WHERE NAME LIKE ?`, + d.innodbSysTables), + fmt.Sprintf("%s/%s%%", + identifiertrans.TablenameToFilename(info.tableSchema), + identifiertrans.TablenameToFilename(info.tableName)), + ) + if err != nil { + return err + } + + for _, row := range res { + s := strings.Split(row.Name, "/") + d0, err := identifiertrans.FilenameToTableName(s[0]) + if err != nil { + return err + } + + var d1 string + // 分区表的 #p.. 部分要去掉才能合法转换 + partitionPattern := regexp.MustCompile(`^(.*)(#[pP]#.*)$`) + match := partitionPattern.FindStringSubmatch(s[1]) + if match != nil { + d1, err = identifiertrans.FilenameToTableName(match[1]) + if err != nil { + return err + } + d1 = fmt.Sprintf("%s%s", d1, match[2]) + } else { + d1, err = identifiertrans.FilenameToTableName(s[1]) + if err != nil { + return err + } + } + + row.IdentifierName = fmt.Sprintf("%s/%s", d0, d1) + } + + if len(res) == 1 && res[0].IdentifierName == innerName { + /* + 普通的 innodb 表 + */ + row := res[0] + if row.Space == 0 || strings.ToLower(row.SpaceType) == "system" { + return fmt.Errorf("%s not in single table space", innerName) + } + + info.tableIds = append(info.tableIds, row.TableId) + info.spaces = append(info.spaces, row.Space) + } else if (len(res) > 1) || (len(res) == 1 && res[0].IdentifierName != innerName) { + /* + innodb 分区表 + */ + partitionPattern := regexp.MustCompile(fmt.Sprintf(`^%s#[pP]#.*$`, innerName)) + for _, row := range res { + if partitionPattern.MatchString(row.IdentifierName) { + info.tableIds = append(info.tableIds, row.TableId) + info.spaces = append(info.spaces, row.Space) + } + } + } else { + return fmt.Errorf("%s table detail not found", innerName) + } + + if len(info.spaces) == 0 || len(info.tableIds) == 0 { + return fmt.Errorf("%s table detail not found", innerName) + } + + return nil +} + +// 不知道需要检查些什么 +func (d *DropTableComp) preCheckMyIsam(innerName string, info *tableInfo) (err error) { + return nil +} + +func (d *DropTableComp) FindDatafiles() (err error) { + for innerName, info := range d.tableInfos { + switch info.engine { + case "innodb": + err = d.innodbFindDatafiles(innerName, info) + if err != nil { + return err + } + case "myisam": + err = d.myisamFindDatafiles(innerName, info) + if err != nil { + return err + } + default: + return fmt.Errorf("engine %s not support", info.engine) + } + } + + return nil +} + +func (d *DropTableComp) innodbFindDatafiles(innerName string, info *tableInfo) (err error) { + q, args, err := sqlx.In( + fmt.Sprintf( + `SELECT SPACE, PATH FROM INFORMATION_SCHEMA.%s WHERE SPACE IN (?)`, + d.innodbSysDatafiles, + ), + info.spaces) + if err != nil { + return err + } + + var res []struct { + Space int `db:"SPACE"` + Path string `db:"PATH"` + } + err = d.db.Select(&res, d.db.Rebind(q), args...) + if err != nil { + return err + } + + if len(res) != len(info.spaces) { + var missingSpaces []int + for _, space := range info.spaces { + i := slices.IndexFunc(res, func(s struct { + Space int `db:"SPACE"` + Path string `db:"PATH"` + }) bool { + return s.Space == space + }) + if i < 0 { + missingSpaces = append(missingSpaces, space) + } + } + + return fmt.Errorf("%v space not found", missingSpaces) + } + + for _, row := range res { + info.datafiles = append(info.datafiles, row.Path) + } + + return nil +} + +func (d *DropTableComp) myisamFindDatafiles(innerName string, info *tableInfo) (err error) { + dbDiskName := identifiertrans.TablenameToFilename(info.tableSchema) + tableDiskName := identifiertrans.TablenameToFilename(info.tableName) + + partitionPattern := regexp.MustCompile(fmt.Sprintf(`^%s#P#.*$`, tableDiskName)) + + err = filepath.WalkDir( + filepath.Join(d.dataDir, dbDiskName), + func(path string, de fs.DirEntry, err error) error { + if err != nil { + return fs.SkipDir + } + + /* + myisam 表有 MYD 和 MYI 两个文件 + 这里只遍历 MYD 找到后再去看 MYI,可以避免重复文件 + */ + if !de.IsDir() && filepath.Ext(de.Name()) == ".MYD" { + diskfilePrefix := strings.TrimSuffix(de.Name(), ".MYD") + + // 普通表或者分区表 + if diskfilePrefix == tableDiskName || partitionPattern.MatchString(diskfilePrefix) { + myiDiskfileName := fmt.Sprintf("%s.MYI", diskfilePrefix) + + // 获取 MYI 信息的任何错误都不能容忍 + if _, err := os.Stat(filepath.Join(d.dataDir, dbDiskName, myiDiskfileName)); err != nil { + return err + } + + info.datafiles = append(info.datafiles, + filepath.Join(dbDiskName, de.Name()), + filepath.Join(dbDiskName, myiDiskfileName)) + } + } + return nil + }) + + if err != nil { + return err + } + + return nil +} + +func (d *DropTableComp) MakeHardlink() (err error) { + for _, info := range d.tableInfos { + + for _, datafile := range info.datafiles { + datafilePath := filepath.Join(d.dataDir, datafile) + linkfile := fmt.Sprintf("%s.__HARDLINK__", datafile) + linkpath := filepath.Join(d.dataDir, linkfile) + + _, err := os.Stat(linkpath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + err = os.Link(datafilePath, linkpath) + if err != nil { + return err + } + } else { + return err + } + } + info.linkfiles = append(info.linkfiles, linkfile) + } + } + return nil +} + +func (d *DropTableComp) DropTable() (err error) { + for _, info := range d.tableInfos { + _, err := d.db.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`.`%s`", info.tableSchema, info.tableName)) + if err != nil { + return err + } + } + + return nil +} + +func (d *DropTableComp) FindLegacyHardlink() (err error) { + /* + 在某些未知的情况下可能存在 + 表已经没了,但是残留了没删除的硬连接 + 所以需要找出来保证幂等 + 在 tableInfos 中不存在的表需要扫描 + */ + for _, tableName := range d.Params.Tables { + innerName := fmt.Sprintf("%s/%s", d.Params.Database, tableName) + if _, ok := d.tableInfos[innerName]; ok { + continue + } + + // 在 Param.Tables, 但是不在 tableInfos 的表会走到这里 + dbDiskName := identifiertrans.TablenameToFilename(d.Params.Database) + tableDiskName := identifiertrans.TablenameToFilename(tableName) + + partitionPattern := regexp.MustCompile(fmt.Sprintf(`^%s#P#.*$`, tableDiskName)) + + linkFilepaths, err := filepath.Glob( + filepath.Join( + d.dataDir, + dbDiskName, + fmt.Sprintf(`%s*.*.__HARDLINK__`, tableDiskName))) + if err != nil { + return err + } + + /* + 只有 linkfiles 是重要的 + tableName 和 tableSchema 也就拿来打日志 + */ + legacyInfo := tableInfo{ + tableName: tableName, + tableSchema: d.Params.Database, + engine: "", + tableIds: nil, + spaces: nil, + datafiles: []string{}, + linkfiles: []string{}, + } + for _, linkFilepath := range linkFilepaths { + linkFilename := filepath.Base(linkFilepath) + + originalName := strings.TrimSuffix(linkFilename, ".__HARDLINK__") + + ext := filepath.Ext(originalName) + originalPrefix := strings.TrimSuffix(originalName, ext) + + // 确定是 tableName 的硬连接文件了 + if originalPrefix == tableDiskName || partitionPattern.MatchString(originalPrefix) { + + _, err := os.Stat( + filepath.Join( + d.dataDir, + dbDiskName, + originalName)) + + // 如果是获得文件状态的其他错误 + if err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + if err == nil { + /* + 表不存在 + 有硬连接文件 + 表的数据文件还存在 + 这应该是不正常的 + */ + return fmt.Errorf( + "table %s.%s: %s original file %s still exists", + d.Params.Database, tableName, linkFilename, originalName) + } + + legacyInfo.linkfiles = append(legacyInfo.linkfiles, filepath.Join(dbDiskName, linkFilename)) + } + } + d.tableInfos[innerName] = &legacyInfo + } + return nil +} + +func (d *DropTableComp) DeleteHardlink() (err error) { + /* + 该做的检查前面都做了 + 这里只需要无脑删除文件 + */ + for _, info := range d.tableInfos { + for _, filename := range info.linkfiles { + if d.Params.LimitSpeed { + done := make(chan int, 1) + go func(chan int) { + osutil.PrintFileSizeIncr( + filepath.Join(d.dataDir, filename), + 1, + 10, + logger.Info, + done) + }(done) + + err = cmutil.TruncateFile( + filepath.Join(d.dataDir, filename), + d.Params.BWLimitMB) + + close(done) + } else { + err = os.Remove(filepath.Join(d.dataDir, filename)) + } + if err != nil { + return err + } + } + } + return nil +} + +func (d *DropTableComp) Example() interface{} { + comp := DropTableComp{ + GeneralParam: &components.GeneralParam{ + RuntimeAccountParam: components.RuntimeAccountParam{ + MySQLAccountParam: common.AccountAdminExample, + }}, + Params: &DropTableParam{ + Database: "test", + Tables: []string{"table1", "table2"}, + LimitSpeed: false, + BWLimitMB: 0, + Host: "x.x.x.x", + Port: 12345, + }, + } + return comp +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/filename_to_tablename.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/filename_to_tablename.go new file mode 100644 index 0000000000..c81d6cf2e3 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/filename_to_tablename.go @@ -0,0 +1,68 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package identifiertrans + +import ( + "dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables" + "fmt" +) + +func FilenameToTableName(filename string) (tablename string, err error) { + for idx := 0; idx < len(filename); { + if filename[idx] < 128 && tables.SafeChar[filename[idx]] { + tablename += string(filename[idx]) + idx += 1 + continue + } + + if filename[idx] != '@' { + return "", fmt.Errorf("invalid char filename[%d]=%c", idx, filename[idx]) + } + + if idx+3 > len(filename) { + return "", fmt.Errorf("invalid sequence filename[%d:]=%s", idx, filename[idx:]) + } + + c1 := filename[idx+1] + c2 := filename[idx+2] + + if c1 >= 0x30 && c1 <= 0x7F && c2 >= 0x30 && c2 <= 0x7F { + code := (int(c1)-0x30)*80 + int(c2) - 0x30 + if code < 5994 && tables.ToUni[code] > 0 { + tablename += string(tables.ToUni[code]) + idx += 3 + continue + } + + if c1 == '@' && c2 == '@' { + tablename += string(rune(0)) + idx += 3 + continue + } + } + + if idx+4 > len(filename) { + return "", fmt.Errorf("invalid sequence filename[%d:]=%s", idx, filename[idx:]) + } + + h1 := tables.HexLo(c1) + h2 := tables.HexLo(c2) + if h1 >= 0 && h2 >= 0 { + h3 := tables.HexLo(filename[idx+3]) + h4 := tables.HexLo(filename[idx+4]) + if h3 >= 0 && h4 >= 0 { + code := (h1 << 12) + (h2 << 8) + (h3 << 4) + h4 + tablename += string(rune(code)) + idx += 5 + continue + } + } + } + return tablename, nil +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/0C00_05FF.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/0C00_05FF.go new file mode 100644 index 0000000000..4e13563612 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/0C00_05FF.go @@ -0,0 +1,161 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var Uni0c0005ff = []rune{ + 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002A, 0x0067, 0x0068, 0x0069, 0x0000, 0x006B, 0x006C, 0x006D, + 0x006E, 0x006F, 0x0070, 0x0071, 0x008A, 0x0037, 0x0038, 0x0039, 0x003A, + 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, + 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x0087, 0x0088, + 0x0089, 0x0000, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, + 0x0092, 0x0073, 0x0093, 0x0074, 0x0094, 0x0075, 0x0095, 0x0076, 0x0096, + 0x0077, 0x0097, 0x0078, 0x0098, 0x0079, 0x0099, 0x007A, 0x009A, 0x00B7, + 0x00D7, 0x00B8, 0x00D8, 0x00B9, 0x00D9, 0x00BA, 0x00DA, 0x00BB, 0x00DB, + 0x00BC, 0x00DC, 0x00BD, 0x00DD, 0x00BE, 0x00DE, 0x00BF, 0x00DF, 0x00C0, + 0x00E0, 0x00C1, 0x00E1, 0x00C2, 0x00E2, 0x00C3, 0x00E3, 0x00C4, 0x00E4, + 0x00C5, 0x00E5, 0x00C6, 0x00E6, 0x0000, 0x00E7, 0x00C8, 0x00E8, 0x00C9, + 0x00E9, 0x00CA, 0x00EA, 0x0127, 0x0108, 0x0128, 0x0109, 0x0129, 0x010A, + 0x012A, 0x010B, 0x012B, 0x010C, 0x012C, 0x010D, 0x012D, 0x010E, 0x012E, + 0x010F, 0x012F, 0x0130, 0x0111, 0x0131, 0x0112, 0x0132, 0x0113, 0x0133, + 0x0114, 0x0134, 0x0115, 0x0135, 0x0116, 0x0136, 0x0117, 0x0137, 0x0118, + 0x0138, 0x0119, 0x0139, 0x011A, 0x013A, 0x0157, 0x0177, 0x0158, 0x0178, + 0x0159, 0x0179, 0x015A, 0x017A, 0x015B, 0x017B, 0x015C, 0x017C, 0x015D, + 0x017D, 0x015E, 0x017E, 0x015F, 0x017F, 0x0160, 0x0180, 0x0161, 0x0181, + 0x0162, 0x0182, 0x0163, 0x0183, 0x0072, 0x0164, 0x0184, 0x0165, 0x0185, + 0x0166, 0x0186, 0x0187, 0x1161, 0x0A86, 0x07B1, 0x11B1, 0x0801, 0x1201, + 0x0AD6, 0x0851, 0x1251, 0x0B76, 0x0BC6, 0x08A1, 0x12A1, 0x12F1, 0x0D52, + 0x0C66, 0x0D06, 0x0941, 0x1341, 0x0857, 0x0947, 0x1391, 0x0B27, 0x0AD7, + 0x09E1, 0x13E1, 0x1431, 0x1481, 0x0D07, 0x07B8, 0x14D1, 0x08A8, 0x0B21, + 0x1521, 0x0B71, 0x1571, 0x0BC1, 0x15C1, 0x0C18, 0x0C11, 0x1611, 0x0D08, + 0x1661, 0x16B1, 0x0D01, 0x1701, 0x0859, 0x0D51, 0x1751, 0x08F9, 0x0949, + 0x0762, 0x1162, 0x07B2, 0x11B2, 0x0B79, 0x0802, 0x1202, 0x1252, 0x12A2, + 0x0992, 0x1392, 0x1342, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x09E2, + 0x0000, 0x13E2, 0x0A32, 0x0000, 0x1432, 0x0A82, 0x0000, 0x1482, 0x0AD2, + 0x14D2, 0x0B22, 0x1522, 0x0B72, 0x1572, 0x0BC2, 0x15C2, 0x0C12, 0x1612, + 0x0C62, 0x1662, 0x0CB2, 0x16B2, 0x0D02, 0x1702, 0x1752, 0x0763, 0x1163, + 0x07B3, 0x11B3, 0x0803, 0x1203, 0x0853, 0x1253, 0x08A3, 0x12A3, 0x08F3, + 0x12F3, 0x0943, 0x1343, 0x0993, 0x1393, 0x09E3, 0x13E3, 0x1433, 0x0A83, + 0x0000, 0x1483, 0x0AD3, 0x14D3, 0x0991, 0x0000, 0x0B23, 0x1523, 0x0B73, + 0x1573, 0x0BC3, 0x15C3, 0x0C13, 0x1613, 0x0C63, 0x1663, 0x0CB3, 0x16B3, + 0x0D03, 0x1703, 0x0D53, 0x1753, 0x0764, 0x1164, 0x07B4, 0x11B4, 0x0804, + 0x1204, 0x0854, 0x1254, 0x08A4, 0x12A4, 0x08F4, 0x12F4, 0x0944, 0x1344, + 0x0994, 0x1394, 0x09E4, 0x13E4, 0x0A34, 0x1434, 0x0A84, 0x1484, 0x0AD4, + 0x14D4, 0x0AD1, 0x1524, 0x0B74, 0x1574, 0x0BC4, 0x15C4, 0x0C14, 0x1614, + 0x0C64, 0x1664, 0x0CB4, 0x16B4, 0x0D04, 0x1704, 0x0D54, 0x1754, 0x0765, + 0x1165, 0x07B5, 0x11B5, 0x1205, 0x1255, 0x12A5, 0x12F5, 0x1345, 0x1395, + 0x09E5, 0x0A35, 0x1435, 0x0A31, 0x0A85, 0x14D5, 0x1525, 0x0C19, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1396, 0x13E6, 0x1436, 0x1486, 0x14D6, + 0x1526, 0x1576, 0x15C6, 0x1616, 0x1666, 0x16B6, 0x1706, 0x1756, 0x1167, + 0x11B7, 0x1207, 0x1257, 0x12A7, 0x12F7, 0x1347, 0x1397, 0x13E7, 0x1437, + 0x1487, 0x14D7, 0x1527, 0x1577, 0x15C7, 0x1617, 0x1667, 0x16B7, 0x1707, + 0x1757, 0x1168, 0x11B8, 0x1208, 0x1258, 0x12A8, 0x12F8, 0x1348, 0x1398, + 0x13E8, 0x1438, 0x1488, 0x14D8, 0x1528, 0x1578, 0x15C8, 0x1618, 0x1668, + 0x16B8, 0x1708, 0x1758, 0x1169, 0x11B9, 0x1209, 0x1259, 0x12A9, 0x12F9, + 0x1349, 0x1399, 0x13E9, 0x1439, 0x1489, 0x14D9, 0x1529, 0x1579, 0x15C9, + 0x1619, 0x1669, 0x16B9, 0x1709, 0x1759, 0x116A, 0x11BA, 0x120A, 0x125A, + 0x12AA, 0x12FA, 0x134A, 0x139A, 0x13EA, 0x143A, 0x148A, 0x14DA, 0x152A, + 0x157A, 0x15CA, 0x161A, 0x166A, 0x16BA, 0x170A, 0x175A, 0x116B, 0x11BB, + 0x120B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01F7, + 0x0000, 0x01F8, 0x01F9, 0x01FA, 0x0000, 0x0253, 0x0000, 0x0254, 0x0255, + 0x01D9, 0x01FC, 0x0257, 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0258, + 0x0204, 0x02A7, 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x0299, 0x0248, + 0x0000, 0x02A9, 0x024B, 0x024C, 0x0298, 0x024E, 0x024F, 0x0250, 0x0251, + 0x0252, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, + 0x021F, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, + 0x0228, 0x0229, 0x022A, 0x0267, 0x0268, 0x0269, 0x026A, 0x026B, 0x026C, + 0x026D, 0x026E, 0x026F, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, + 0x0000, 0x0277, 0x0278, 0x0259, 0x025A, 0x0297, 0x02B8, 0x02B9, 0x02BA, + 0x0000, 0x02BB, 0x029C, 0x02BC, 0x029D, 0x02BD, 0x029E, 0x02BE, 0x029F, + 0x02BF, 0x02A0, 0x02C0, 0x02A1, 0x02C1, 0x02A2, 0x02C2, 0x02A3, 0x02C3, + 0x02A4, 0x02C4, 0x02A5, 0x02C5, 0x02A6, 0x02C6, 0x02C7, 0x02C8, 0x02C9, + 0x02CA, 0x0000, 0x0307, 0x0308, 0x0000, 0x0309, 0x0000, 0x0000, 0x030A, + 0x030B, 0x02EC, 0x02ED, 0x02EE, 0x0AF1, 0x0B41, 0x0B91, 0x0BE1, 0x0C31, + 0x0C81, 0x0CD1, 0x0D21, 0x0732, 0x0782, 0x07D2, 0x0822, 0x0872, 0x08C2, + 0x0912, 0x0962, 0x0730, 0x0780, 0x07D0, 0x0820, 0x0870, 0x08C0, 0x0910, + 0x0960, 0x09B0, 0x0A00, 0x0A50, 0x0AA0, 0x0AF0, 0x0B40, 0x0B90, 0x0BE0, + 0x0C30, 0x0C80, 0x0CD0, 0x0D20, 0x0731, 0x0781, 0x07D1, 0x0821, 0x0871, + 0x08C1, 0x0911, 0x0961, 0x09B1, 0x0A01, 0x0A51, 0x0AA1, 0x1130, 0x1180, + 0x11D0, 0x1220, 0x1270, 0x12C0, 0x1310, 0x1360, 0x13B0, 0x1400, 0x1450, + 0x14A0, 0x14F0, 0x1540, 0x1590, 0x15E0, 0x1630, 0x1680, 0x16D0, 0x1720, + 0x1131, 0x1181, 0x11D1, 0x1221, 0x1271, 0x12C1, 0x1311, 0x1361, 0x13B1, + 0x1401, 0x1451, 0x14A1, 0x14F1, 0x1541, 0x1591, 0x15E1, 0x1631, 0x1681, + 0x16D1, 0x1721, 0x1132, 0x1182, 0x11D2, 0x1222, 0x1272, 0x12C2, 0x1312, + 0x1362, 0x09B2, 0x13B2, 0x0A02, 0x1402, 0x0A52, 0x1452, 0x0AA2, 0x14A2, + 0x0AF2, 0x14F2, 0x0B42, 0x1542, 0x0B92, 0x1592, 0x0BE2, 0x15E2, 0x0C32, + 0x1632, 0x0C82, 0x1682, 0x0CD2, 0x16D2, 0x0D22, 0x1722, 0x0733, 0x1133, + 0x0783, 0x1183, 0x07D3, 0x11D3, 0x0823, 0x1223, 0x0873, 0x1273, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0913, 0x1313, + 0x0963, 0x1363, 0x09B3, 0x13B3, 0x0A03, 0x1403, 0x0A53, 0x1453, 0x0AA3, + 0x14A3, 0x0AF3, 0x14F3, 0x0B43, 0x1543, 0x0B93, 0x1593, 0x0BE3, 0x15E3, + 0x0C33, 0x1633, 0x0C83, 0x1683, 0x0CD3, 0x16D3, 0x0D23, 0x1723, 0x0734, + 0x1134, 0x0784, 0x1184, 0x07D4, 0x11D4, 0x0824, 0x1224, 0x0874, 0x1274, + 0x08C4, 0x12C4, 0x0914, 0x1314, 0x0964, 0x1364, 0x09B4, 0x13B4, 0x0A04, + 0x1404, 0x0A54, 0x1454, 0x0AA4, 0x14A4, 0x0AF4, 0x14F4, 0x0B44, 0x0B94, + 0x1594, 0x0BE4, 0x15E4, 0x0C34, 0x1634, 0x0C84, 0x1684, 0x0CD4, 0x16D4, + 0x0D24, 0x1724, 0x0735, 0x1135, 0x0000, 0x07D5, 0x11D5, 0x0825, 0x1225, + 0x0875, 0x1275, 0x08C5, 0x12C5, 0x0915, 0x1315, 0x0965, 0x1365, 0x09B5, + 0x13B5, 0x0A05, 0x1405, 0x0A55, 0x1455, 0x0AA5, 0x14A5, 0x0AF5, 0x14F5, + 0x0B45, 0x1545, 0x0B95, 0x1595, 0x0BE5, 0x15E5, 0x0C35, 0x1635, 0x0C85, + 0x1685, 0x0CD5, 0x16D5, 0x0D25, 0x1725, 0x0736, 0x1136, 0x0786, 0x1186, + 0x07D6, 0x11D6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0A06, + 0x1406, 0x0A56, 0x1456, 0x0AA6, 0x14A6, 0x0AF6, 0x14F6, 0x0B46, 0x1546, + 0x0B96, 0x1596, 0x0BE6, 0x15E6, 0x0C36, 0x1636, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0787, 0x07D7, 0x0827, 0x0877, 0x08C7, 0x0917, + 0x0967, 0x09B7, 0x0A07, 0x0A57, 0x0AA7, 0x0AF7, 0x0B47, 0x0B97, 0x0BE7, + 0x0C37, 0x0C87, 0x0CD7, 0x0D27, 0x0738, 0x0788, 0x07D8, 0x0828, 0x0878, + 0x08C8, 0x0918, 0x0968, 0x09B8, 0x0A08, 0x0A58, 0x0AA8, 0x0AF8, 0x0B48, + 0x0B98, 0x0BE8, 0x0C38, 0x0C88, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1187, 0x11D7, 0x1227, + 0x1277, 0x12C7, 0x1317, 0x1367, 0x13B7, 0x1407, 0x1457, 0x14A7, 0x14F7, + 0x1547, 0x1597, 0x15E7, 0x1637, 0x1687, 0x16D7, 0x1727, 0x1138, 0x1188, + 0x11D8, 0x1228, 0x1278, 0x12C8, 0x1318, 0x1368, 0x13B8, 0x1408, 0x1458, + 0x14A8, 0x14F8, 0x1548, 0x1598, 0x15E8, 0x1638, 0x1688, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/1E00_1FFF.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/1E00_1FFF.go new file mode 100644 index 0000000000..5523351398 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/1E00_1FFF.go @@ -0,0 +1,68 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var Uni1e001fff = []rune{ + 0x076C, 0x116C, 0x07BC, 0x11BC, 0x080C, 0x120C, 0x085C, 0x125C, 0x08AC, + 0x12AC, 0x08FC, 0x12FC, 0x094C, 0x134C, 0x099C, 0x139C, 0x09EC, 0x13EC, + 0x0A3C, 0x143C, 0x0A8C, 0x148C, 0x0ADC, 0x14DC, 0x0B2C, 0x152C, 0x0B7C, + 0x157C, 0x0BCC, 0x15CC, 0x0C1C, 0x161C, 0x0C6C, 0x166C, 0x0CBC, 0x16BC, + 0x0D0C, 0x170C, 0x0D5C, 0x175C, 0x076D, 0x116D, 0x07BD, 0x11BD, 0x080D, + 0x120D, 0x085D, 0x125D, 0x08AD, 0x12AD, 0x08FD, 0x12FD, 0x094D, 0x134D, + 0x099D, 0x139D, 0x09ED, 0x13ED, 0x0A3D, 0x143D, 0x0A8D, 0x148D, 0x0ADD, + 0x14DD, 0x0B2D, 0x152D, 0x0B7D, 0x157D, 0x0BCD, 0x15CD, 0x0C1D, 0x161D, + 0x0C6D, 0x166D, 0x0CBD, 0x16BD, 0x0D0D, 0x170D, 0x0D5D, 0x175D, 0x076E, + 0x116E, 0x07BE, 0x11BE, 0x080E, 0x120E, 0x085E, 0x125E, 0x08AE, 0x12AE, + 0x08FE, 0x12FE, 0x094E, 0x134E, 0x099E, 0x139E, 0x0770, 0x13EE, 0x0A3E, + 0x143E, 0x0A8E, 0x148E, 0x0ADE, 0x14DE, 0x0B2E, 0x152E, 0x0B7E, 0x157E, + 0x0BCE, 0x15CE, 0x0C1E, 0x161E, 0x0C6E, 0x166E, 0x0CBE, 0x16BE, 0x0D0E, + 0x170E, 0x0D5E, 0x175E, 0x076F, 0x116F, 0x07BF, 0x11BF, 0x080F, 0x120F, + 0x085F, 0x125F, 0x08AF, 0x12AF, 0x08FF, 0x12FF, 0x094F, 0x134F, 0x099F, + 0x139F, 0x09EF, 0x13EF, 0x0A3F, 0x143F, 0x0A8F, 0x148F, 0x0ADF, 0x14DF, + 0x0B2F, 0x152F, 0x0B7F, 0x157F, 0x0BCF, 0x15CF, 0x161F, 0x166F, 0x16BF, + 0x170F, 0x175F, 0x1170, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x1300, + 0x0950, 0x1350, 0x09A0, 0x13A0, 0x09F0, 0x13F0, 0x0A40, 0x1440, 0x0A90, + 0x1490, 0x0AE0, 0x14E0, 0x0B30, 0x1530, 0x0B80, 0x1580, 0x0BD0, 0x15D0, + 0x0C20, 0x1620, 0x0C70, 0x1670, 0x0CC0, 0x16C0, 0x0D10, 0x1710, 0x0D60, + 0x1760, 0x0771, 0x1171, 0x07C1, 0x11C1, 0x0811, 0x1211, 0x0861, 0x1261, + 0x08B1, 0x12B1, 0x0901, 0x1301, 0x0951, 0x1351, 0x09A1, 0x13A1, 0x09F1, + 0x13F1, 0x0A41, 0x1441, 0x0A91, 0x1491, 0x0AE1, 0x14E1, 0x0B31, 0x1531, + 0x0B81, 0x1581, 0x0BD1, 0x15D1, 0x0C21, 0x1621, 0x0C71, 0x1671, 0x0CC1, + 0x16C1, 0x0D11, 0x1711, 0x0D61, 0x1761, 0x0772, 0x1172, 0x07C2, 0x11C2, + 0x0812, 0x1212, 0x0862, 0x1262, 0x08B2, 0x12B2, 0x0902, 0x1302, 0x0952, + 0x1352, 0x09A2, 0x13A2, 0x09F2, 0x13F2, 0x0A42, 0x1442, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1173, 0x11C3, 0x1213, 0x1263, 0x12B3, + 0x1303, 0x1353, 0x13A3, 0x0773, 0x07C3, 0x0813, 0x0863, 0x08B3, 0x0903, + 0x0953, 0x09A3, 0x13F3, 0x1443, 0x1493, 0x14E3, 0x1533, 0x1583, 0x0000, + 0x0000, 0x09F3, 0x0A43, 0x0A93, 0x0AE3, 0x0B33, 0x0B83, 0x0000, 0x0000, + 0x1713, 0x1763, 0x1174, 0x11C4, 0x1214, 0x1264, 0x12B4, 0x1304, 0x0D13, + 0x0D63, 0x0774, 0x07C4, 0x0814, 0x0864, 0x08B4, 0x0904, 0x1354, 0x13A4, + 0x13F4, 0x1444, 0x1494, 0x14E4, 0x1534, 0x1584, 0x0954, 0x09A4, 0x09F4, + 0x0A44, 0x0A94, 0x0AE4, 0x0B34, 0x0B84, 0x15D4, 0x1624, 0x1674, 0x16C4, + 0x1714, 0x1764, 0x0000, 0x0000, 0x0BD4, 0x0C24, 0x0C74, 0x0CC4, 0x0D14, + 0x0D64, 0x0000, 0x0000, 0x12B5, 0x1305, 0x1355, 0x13A5, 0x13F5, 0x1445, + 0x1495, 0x14E5, 0x0000, 0x0905, 0x0000, 0x09A5, 0x0000, 0x0A45, 0x0000, + 0x0AE5, 0x1675, 0x16C5, 0x1715, 0x1765, 0x1176, 0x11C6, 0x1216, 0x1266, + 0x0C75, 0x0CC5, 0x0D15, 0x0D65, 0x0776, 0x07C6, 0x0816, 0x0866, 0x12B6, + 0x1306, 0x1356, 0x13A6, 0x13F6, 0x1446, 0x1496, 0x14E6, 0x1536, 0x1586, + 0x15D6, 0x1626, 0x1676, 0x16C6, 0x0000, 0x0000, 0x1177, 0x11C7, 0x1217, + 0x1267, 0x12B7, 0x1307, 0x1357, 0x13A7, 0x0777, 0x07C7, 0x0817, 0x0867, + 0x08B7, 0x0907, 0x0957, 0x09A7, 0x13F7, 0x1447, 0x1497, 0x14E7, 0x1537, + 0x1587, 0x15D7, 0x1627, 0x09F7, 0x0A47, 0x0A97, 0x0AE7, 0x0B37, 0x0B87, + 0x0BD7, 0x0C27, 0x1677, 0x16C7, 0x1717, 0x1767, 0x1178, 0x11C8, 0x1218, + 0x1268, 0x0C77, 0x0CC7, 0x0D17, 0x0D67, 0x0778, 0x07C8, 0x0818, 0x0868, + 0x12B8, 0x1308, 0x1358, 0x13A8, 0x13F8, 0x0000, 0x1498, 0x14E8, 0x08B8, + 0x0908, 0x08B6, 0x0906, 0x09A8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1538, 0x1588, 0x15D8, 0x0000, 0x1678, 0x16C8, 0x0956, 0x09A6, 0x09F6, + 0x0A46, 0x0B88, 0x0000, 0x0000, 0x0000, 0x1718, 0x1768, 0x1179, 0x11C9, + 0x0000, 0x0000, 0x12B9, 0x1309, 0x0D18, 0x0D68, 0x0A96, 0x0AE6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x13A9, 0x13F9, 0x1449, 0x1499, 0x14E9, 0x1539, + 0x1589, 0x15D9, 0x09A9, 0x09F9, 0x0BD6, 0x0C26, 0x0B39, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x16C9, 0x1719, 0x0000, 0x0000, 0x11CA, 0x121A, + 0x0B36, 0x0B86, 0x0C76, 0x0CC6, 0x0D19, 0x0000, 0x0000, 0x0000} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/2160_217F.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/2160_217F.go new file mode 100644 index 0000000000..2349e38c1f --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/2160_217F.go @@ -0,0 +1,15 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var Uni2160217f = []rune{ + 0x0739, 0x0789, 0x07D9, 0x0829, 0x0879, 0x08C9, 0x0919, 0x0969, + 0x09B9, 0x0A09, 0x0A59, 0x0AA9, 0x0AF9, 0x0B49, 0x0B99, 0x0BE9, + 0x1139, 0x1189, 0x11D9, 0x1229, 0x1279, 0x12C9, 0x1319, 0x1369, + 0x13B9, 0x1409, 0x1459, 0x14A9, 0x14F9, 0x1549, 0x1599, 0x15E9} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/24B0_24EF.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/24B0_24EF.go new file mode 100644 index 0000000000..ea6ccc9a30 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/24B0_24EF.go @@ -0,0 +1,19 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var Uni24b024ef = []rune{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0511, 0x0512, + 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, 0x0518, 0x0519, 0x051A, + 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, 0x0520, 0x0521, 0x0522, + 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, 0x0528, 0x0529, 0x052A, + 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538, + 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F, 0x0540, + 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, + 0x0549, 0x054A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/FF20_FF5F.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/FF20_FF5F.go new file mode 100644 index 0000000000..7e69caa9e8 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/FF20_FF5F.go @@ -0,0 +1,19 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var UniFf20Ff5f = []rune{ + 0x0000, 0x0560, 0x05B0, 0x0600, 0x0650, 0x06A0, 0x06F0, 0x0740, + 0x0790, 0x07E0, 0x0830, 0x0880, 0x08D0, 0x0920, 0x0970, 0x09C0, + 0x0A10, 0x0A60, 0x0AB0, 0x0B00, 0x0B50, 0x0BA0, 0x0BF0, 0x0C40, + 0x0C90, 0x0CE0, 0x0D30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0F60, 0x0FB0, 0x1000, 0x1050, 0x10A0, 0x10F0, 0x1140, + 0x1190, 0x11E0, 0x1230, 0x1280, 0x12D0, 0x1320, 0x1370, 0x13C0, + 0x1410, 0x1460, 0x14B0, 0x1500, 0x1550, 0x15A0, 0x15F0, 0x1640, + 0x1690, 0x16E0, 0x1730, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/Hex_Lo_Digit.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/Hex_Lo_Digit.go new file mode 100644 index 0000000000..d00f0ca63d --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/Hex_Lo_Digit.go @@ -0,0 +1,48 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var hexLoDigit = []int{ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* !"#$%&'()*+,-./ */ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, /* 0123456789:;<=>? */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* @ABCDEFGHIJKLMNO */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* PQRSTUVWXYZ[\]^_ */ + -1, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* `abcdefghijklmno */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* pqrstuvwxyz{|}~. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* ................ */ +} + +func HexLo(x uint8) int { + return hexLoDigit[x] +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/To_UNI.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/To_UNI.go new file mode 100644 index 0000000000..003e047d4d --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/To_UNI.go @@ -0,0 +1,677 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var ToUni = []rune{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00C0, 0x00C1, 0x00C2, 0x00C3, + 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, + 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, + 0x00F1, 0x00F2, 0x00F3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x00D4, 0x00D5, 0x00D6, 0x0000, 0x00D8, + 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178, 0x0100, 0x0102, + 0x0104, 0x0106, 0x0108, 0x010A, 0x010C, 0x010E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00F4, 0x00F5, 0x00F6, 0x00DF, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, + 0x00FD, 0x00FE, 0x00FF, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010B, + 0x010D, 0x010F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0110, 0x0112, 0x0114, 0x0116, 0x0118, 0x011A, + 0x011C, 0x011E, 0x0120, 0x0122, 0x0124, 0x0126, 0x0128, 0x012A, 0x012C, + 0x012E, 0x0000, 0x0132, 0x0134, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0111, + 0x0113, 0x0115, 0x0117, 0x0119, 0x011B, 0x011D, 0x011F, 0x0121, 0x0123, + 0x0125, 0x0127, 0x0129, 0x012B, 0x012D, 0x012F, 0x0131, 0x0133, 0x0135, + 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0139, 0x013B, 0x013D, 0x013F, 0x0141, 0x0143, + 0x0145, 0x0147, 0x0000, 0x014A, 0x014C, 0x014E, 0x0150, 0x0152, 0x0154, + 0x0156, 0x0158, 0x015A, 0x015C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0138, 0x013A, + 0x013C, 0x013E, 0x0140, 0x0142, 0x0144, 0x0146, 0x0148, 0x0149, 0x014B, + 0x014D, 0x014F, 0x0151, 0x0153, 0x0155, 0x0157, 0x0159, 0x015B, 0x015D, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x015E, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016A, 0x016C, + 0x016E, 0x0170, 0x0172, 0x0174, 0x0176, 0x0179, 0x017B, 0x017D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x015F, 0x0161, 0x0163, + 0x0165, 0x0167, 0x0169, 0x016B, 0x016D, 0x016F, 0x0171, 0x0173, 0x0175, + 0x0177, 0x017A, 0x017C, 0x017E, 0x017F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0390, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, + 0x0388, 0x0389, 0x038A, 0x0000, 0x0391, 0x0000, 0x0393, 0x0394, 0x0395, + 0x0396, 0x0397, 0x0000, 0x0399, 0x0000, 0x039B, 0x039C, 0x039D, 0x039E, + 0x039F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, + 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, + 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03A1, + 0x0000, 0x0000, 0x03A4, 0x03A5, 0x0000, 0x03A7, 0x03A8, 0x03A9, 0x03AA, + 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000, 0x0392, 0x0398, 0x03D2, 0x03D3, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, + 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, + 0x0000, 0x03D0, 0x03D1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03D4, 0x03A6, 0x03A0, + 0x0000, 0x0000, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x03E2, 0x03E4, 0x03E6, + 0x03E8, 0x03EA, 0x03EC, 0x03EE, 0x039A, 0x0000, 0x03A3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x03D5, 0x03D6, 0x03D7, 0x03D9, 0x03DB, 0x03DD, + 0x03DF, 0x03E1, 0x03E3, 0x03E5, 0x03E7, 0x03E9, 0x03EB, 0x03ED, 0x03EF, + 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03FD, 0x03FE, 0x03FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03F5, 0x03F6, 0x03F8, 0x03FB, 0x03FC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD, + 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5, 0x24C6, + 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x24D0, 0x24D1, 0x24D2, + 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, + 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, + 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF21, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF22, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF23, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF24, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xFF25, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0410, 0x0424, 0x0408, 0x0478, 0x04A6, + 0x04CD, 0x04F4, 0x0000, 0x0544, 0x2160, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x01B3, 0x01DE, 0x0208, 0x0230, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1E00, 0x1E28, 0x1E50, 0x1E78, 0x1E60, 0x1EBE, 0x1EE6, 0x1F08, + 0x1F2A, 0x0000, 0x1F6C, 0x1F88, 0x1FAC, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0411, 0x0425, 0x0409, 0x047A, 0x04A8, 0x0000, + 0x04F6, 0x0531, 0x0545, 0x2161, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF28, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0182, 0x01B5, + 0x01E0, 0x020A, 0x0232, 0x0000, 0x0000, 0x019D, 0x0000, 0x0000, 0x0000, + 0x1E02, 0x1E2A, 0x1E52, 0x1E7A, 0x0000, 0x1EC0, 0x1EE8, 0x1F09, 0x1F2B, + 0x0000, 0x1F6D, 0x1F89, 0x1FAD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0412, 0x0426, 0x040A, 0x047C, 0x04AA, 0x04D0, 0x04F8, + 0x0532, 0x0546, 0x2162, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF29, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0184, 0x01B8, 0x01E2, + 0x020C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E04, + 0x1E2C, 0x1E54, 0x1E7C, 0x0000, 0x1EC2, 0x1EEA, 0x1F0A, 0x1F2C, 0x0000, + 0x1F6E, 0x1F8A, 0x1FAE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0413, 0x0427, 0x040B, 0x047E, 0x04AC, 0x04D2, 0x0000, 0x0533, + 0x0547, 0x2163, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF2A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0187, 0x0000, 0x01E4, 0x020E, + 0x0000, 0x0000, 0x0193, 0x0000, 0x01AE, 0x0000, 0x0000, 0x1E06, 0x1E2E, + 0x1E56, 0x1E7E, 0x0000, 0x1EC4, 0x1EEC, 0x1F0B, 0x1F2D, 0x0000, 0x1F6F, + 0x1F8B, 0x1FAF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0414, 0x0428, 0x040C, 0x0480, 0x04AE, 0x04D4, 0x0000, 0x0534, 0x0548, + 0x2164, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF2B, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x018B, 0x0000, 0x01E6, 0x0210, 0x0000, + 0x0000, 0x0000, 0x019F, 0x0000, 0x0000, 0x0000, 0x1E08, 0x1E30, 0x1E58, + 0x1E80, 0x0000, 0x1EC6, 0x1EEE, 0x1F0C, 0x1F2E, 0x0000, 0x1FBA, 0x1F8C, + 0x1FB8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415, + 0x0429, 0x040D, 0x0000, 0x04B0, 0x04D6, 0x0000, 0x0535, 0x0549, 0x2165, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF2C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01E8, 0x0212, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01B1, 0x0000, 0x0000, 0x1E0A, 0x1E32, 0x1E5A, 0x1E82, + 0x1EA0, 0x1EC8, 0x1EF0, 0x1F0D, 0x1F2F, 0x1F59, 0x1FBB, 0x1F8D, 0x1FB9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0416, 0x042A, + 0x040E, 0x048A, 0x04B2, 0x04D8, 0x0000, 0x0536, 0x054A, 0x2166, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF2D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0191, 0x0000, 0x01EA, 0x0214, 0x0000, 0x0000, 0x0194, + 0x0000, 0x01B2, 0x0000, 0x0000, 0x1E0C, 0x1E34, 0x1E5C, 0x1E84, 0x1EA2, + 0x1ECA, 0x1EF2, 0x1F0E, 0x1F38, 0x0000, 0x1FC8, 0x1F8E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0417, 0x042B, 0x040F, + 0x048C, 0x04B4, 0x04DA, 0x0000, 0x0537, 0x054B, 0x2167, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xFF2E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x01F6, 0x01BC, 0x01EC, 0x0216, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1E0E, 0x1E36, 0x1E5E, 0x1E86, 0x1EA4, 0x1ECC, + 0x1EF4, 0x1F0F, 0x1F39, 0x1F5B, 0x1FC9, 0x1F8F, 0x1FBC, 0x1FE8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0418, 0x042C, 0x0460, 0x048E, + 0x04B6, 0x04DC, 0x0000, 0x0538, 0x054C, 0x2168, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF2F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0198, 0x01C4, 0x01EE, 0x0218, 0x023A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1E10, 0x1E38, 0x0000, 0x1E88, 0x1EA6, 0x1ECE, 0x1EF6, + 0x1F18, 0x1F3A, 0x0000, 0x1FCA, 0x1F98, 0x0000, 0x1FE9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0419, 0x042D, 0x0462, 0x0490, 0x04B8, + 0x04DE, 0x0500, 0x0539, 0x054D, 0x2169, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF30, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x023D, + 0x01C7, 0x0000, 0x021A, 0x023B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1E12, 0x1E3A, 0x1E62, 0x1E8A, 0x1EA8, 0x1ED0, 0x1EF8, 0x1F19, + 0x1F3B, 0x1F5D, 0x1FCB, 0x1F99, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x041A, 0x042E, 0x0464, 0x0492, 0x04BA, 0x04E0, + 0x0502, 0x053A, 0x054E, 0x216A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF31, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01CA, + 0x01F1, 0x021C, 0x023E, 0x0181, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1E14, 0x1E3C, 0x1E64, 0x1E8C, 0x1EAA, 0x1ED2, 0x0000, 0x1F1A, 0x1F3C, + 0x0000, 0x1FDA, 0x1F9A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x041B, 0x042F, 0x0466, 0x0494, 0x04BC, 0x04E2, 0x0504, + 0x053B, 0x054F, 0x216B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0220, 0x01CD, 0x01F4, + 0x021E, 0x0000, 0x0186, 0x0197, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E16, + 0x1E3E, 0x1E66, 0x1E8E, 0x1EAC, 0x1ED4, 0x0000, 0x1F1B, 0x1F3D, 0x1F5F, + 0x1FDB, 0x1F9B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x041C, 0x0400, 0x0468, 0x0496, 0x04BE, 0x04E4, 0x0506, 0x053C, + 0x0550, 0x216C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF33, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01A0, 0x01CF, 0x01F8, 0x0000, + 0x0000, 0x0000, 0x0196, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E18, 0x1E40, + 0x1E68, 0x1E90, 0x1EAE, 0x1ED6, 0x0000, 0x1F1C, 0x1F3E, 0x0000, 0x1FF8, + 0x1F9C, 0x0000, 0x1FEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x041D, 0x0401, 0x046A, 0x0498, 0x04C0, 0x04E6, 0x0508, 0x053D, 0x0551, + 0x216D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF34, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01A2, 0x01D1, 0x01FA, 0x0222, 0x0000, + 0x0189, 0x0000, 0x0000, 0x01B7, 0x0000, 0x0000, 0x1E1A, 0x1E42, 0x1E6A, + 0x1E92, 0x1EB0, 0x1ED8, 0x0000, 0x1F1D, 0x1F3F, 0x0000, 0x1FF9, 0x1F9D, + 0x1FCC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x041E, + 0x0402, 0x046C, 0x049A, 0x04C1, 0x04E8, 0x050A, 0x053E, 0x0552, 0x216E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF35, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01A4, 0x01D3, 0x01FC, 0x0224, 0x0000, 0x018A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E1C, 0x1E44, 0x1E6C, 0x1E94, + 0x1EB2, 0x1EDA, 0x0000, 0x0000, 0x1F48, 0x0000, 0x1FEA, 0x1F9E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x041F, 0x0403, + 0x046E, 0x049C, 0x04C3, 0x04EA, 0x050C, 0x053F, 0x0553, 0x216F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF36, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01A7, 0x01D5, 0x01FE, 0x0226, 0x0000, 0x0000, 0x0000, + 0x01A6, 0x0241, 0x0000, 0x0000, 0x1E1E, 0x1E46, 0x1E6E, 0x0000, 0x1EB4, + 0x1EDC, 0x0000, 0x0000, 0x1F49, 0x0000, 0x1FEB, 0x1F9F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0420, 0x0404, 0x0470, + 0x049E, 0x04C5, 0x04EC, 0x050E, 0x0540, 0x0554, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xFF37, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01D7, 0x0200, 0x0228, 0x0000, 0x018F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1E20, 0x1E48, 0x1E70, 0x0000, 0x1EB6, 0x1EDE, + 0x0000, 0x0000, 0x1F4A, 0x1F68, 0x1FFA, 0x1FA8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0421, 0x0405, 0x0472, 0x04A0, + 0x04C7, 0x04EE, 0x0000, 0x0541, 0x0555, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x01D9, 0x0202, 0x022A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1E22, 0x1E4A, 0x1E72, 0x0000, 0x1EB8, 0x1EE0, 0x0000, + 0x0000, 0x1F4B, 0x1F69, 0x1FFB, 0x1FA9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0422, 0x0406, 0x0474, 0x04A2, 0x04C9, + 0x04F0, 0x0000, 0x0542, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF39, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AC, + 0x01DB, 0x0204, 0x022C, 0x0000, 0x0190, 0x019C, 0x01A9, 0x0000, 0x0000, + 0x0000, 0x1E24, 0x1E4C, 0x1E74, 0x0000, 0x1EBA, 0x1EE2, 0x0000, 0x1F28, + 0x1F4C, 0x1F6A, 0x0000, 0x1FAA, 0x1FD8, 0x1FFC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0423, 0x0407, 0x0476, 0x04A4, 0x04CB, 0x04F2, + 0x0000, 0x0543, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AF, 0x018E, + 0x0206, 0x022E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1E26, 0x1E4E, 0x1E76, 0x0000, 0x1EBC, 0x1EE4, 0x0000, 0x1F29, 0x1F4D, + 0x1F6B, 0x0000, 0x1FAB, 0x1FD9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF41, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF42, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF44, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF45, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF46, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0430, + 0x0444, 0x0458, 0x0479, 0x04A7, 0x04CE, 0x04F5, 0x0000, 0x0574, 0x2170, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF47, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0180, 0x01B4, 0x01DF, 0x0209, 0x0231, 0x0000, + 0x025D, 0x0271, 0x0285, 0x0299, 0x02AD, 0x1E01, 0x1E29, 0x1E51, 0x1E79, + 0x1E9B, 0x1EBF, 0x1EE7, 0x1F00, 0x1F22, 0x0000, 0x1F64, 0x1F80, 0x1FA4, + 0x1FD2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0431, 0x0445, + 0x0459, 0x047B, 0x04A9, 0x0000, 0x04F7, 0x0561, 0x0575, 0x2171, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF48, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0183, 0x01B6, 0x01E1, 0x020B, 0x0233, 0x0000, 0x025E, + 0x0272, 0x0286, 0x029A, 0x02AE, 0x1E03, 0x1E2B, 0x1E53, 0x1E7B, 0x0000, + 0x1EC1, 0x1EE9, 0x1F01, 0x1F23, 0x0000, 0x1F65, 0x1F81, 0x1FA5, 0x1FD3, + 0x1FF6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0432, 0x0446, 0x045A, + 0x047D, 0x04AB, 0x04D1, 0x04F9, 0x0562, 0x0576, 0x2172, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xFF49, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0185, 0x01B9, 0x01E3, 0x020D, 0x0234, 0x0000, 0x025F, 0x0273, + 0x0287, 0x029B, 0x02AF, 0x1E05, 0x1E2D, 0x1E55, 0x1E7D, 0x0000, 0x1EC3, + 0x1EEB, 0x1F02, 0x1F24, 0x0000, 0x1F66, 0x1F82, 0x1FA6, 0x0000, 0x1FF7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0433, 0x0447, 0x045B, 0x047F, + 0x04AD, 0x04D3, 0x0000, 0x0563, 0x0577, 0x2173, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF4A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0188, 0x01BA, 0x01E5, 0x020F, 0x0235, 0x0000, 0x0260, 0x0274, 0x0288, + 0x029C, 0x0000, 0x1E07, 0x1E2F, 0x1E57, 0x1E7F, 0x0000, 0x1EC5, 0x1EED, + 0x1F03, 0x1F25, 0x0000, 0x1F67, 0x1F83, 0x1FA7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0434, 0x0448, 0x045C, 0x0481, 0x04AF, + 0x04D5, 0x0000, 0x0564, 0x0578, 0x2174, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF4B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018C, + 0x01BB, 0x01E7, 0x0211, 0x0236, 0x0000, 0x0261, 0x0275, 0x0289, 0x029D, + 0x0000, 0x1E09, 0x1E31, 0x1E59, 0x1E81, 0x0000, 0x1EC7, 0x1EEF, 0x1F04, + 0x1F26, 0x1F50, 0x1F70, 0x1F84, 0x1FB0, 0x1FD6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0435, 0x0449, 0x045D, 0x0000, 0x04B1, 0x04D7, + 0x0000, 0x0565, 0x0579, 0x2175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF4C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018D, 0x0000, + 0x01E9, 0x0213, 0x0237, 0x0000, 0x0262, 0x0276, 0x028A, 0x029E, 0x0000, + 0x1E0B, 0x1E33, 0x1E5B, 0x1E83, 0x1EA1, 0x1EC9, 0x1EF1, 0x1F05, 0x1F27, + 0x1F51, 0x1F71, 0x1F85, 0x1FB1, 0x1FD7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0436, 0x044A, 0x045E, 0x048B, 0x04B3, 0x04D9, 0x0000, + 0x0566, 0x057A, 0x2176, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x01BE, 0x01EB, + 0x0215, 0x0238, 0x0000, 0x0263, 0x0277, 0x028B, 0x029F, 0x0000, 0x1E0D, + 0x1E35, 0x1E5D, 0x1E85, 0x1EA3, 0x1ECB, 0x1EF3, 0x1F06, 0x1F30, 0x1F52, + 0x1F72, 0x1F86, 0x1FB2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0437, 0x044B, 0x045F, 0x048D, 0x04B5, 0x04DB, 0x0000, 0x0567, + 0x057B, 0x2177, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF4E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0195, 0x01BD, 0x01ED, 0x0217, + 0x0239, 0x0250, 0x0264, 0x0278, 0x028C, 0x02A0, 0x0000, 0x1E0F, 0x1E37, + 0x1E5F, 0x1E87, 0x1EA5, 0x1ECD, 0x1EF5, 0x1F07, 0x1F31, 0x1F53, 0x1F73, + 0x1F87, 0x1FB3, 0x1FE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0438, 0x044C, 0x0461, 0x048F, 0x04B7, 0x04DD, 0x0000, 0x0568, 0x057C, + 0x2178, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF4F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0199, 0x01C6, 0x01EF, 0x0219, 0x0000, + 0x0251, 0x0265, 0x0279, 0x028D, 0x02A1, 0x0000, 0x1E11, 0x1E39, 0x1E61, + 0x1E89, 0x1EA7, 0x1ECF, 0x1EF7, 0x1F10, 0x1F32, 0x1F54, 0x1F74, 0x1F90, + 0x1FB4, 0x1FE1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0439, + 0x044D, 0x0463, 0x0491, 0x04B9, 0x04DF, 0x0501, 0x0569, 0x057D, 0x2179, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF50, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x019A, 0x01C9, 0x01F0, 0x021B, 0x023C, 0x0252, + 0x0266, 0x027A, 0x028E, 0x02A2, 0x0000, 0x1E13, 0x1E3B, 0x1E63, 0x1E8B, + 0x1EA9, 0x1ED1, 0x1EF9, 0x1F11, 0x1F33, 0x1F55, 0x1F75, 0x1F91, 0x0000, + 0x1FE2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x043A, 0x044E, + 0x0465, 0x0493, 0x04BB, 0x04E1, 0x0503, 0x056A, 0x057E, 0x217A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF51, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x019B, 0x01CC, 0x01F3, 0x021D, 0x0000, 0x0253, 0x0267, + 0x027B, 0x028F, 0x02A3, 0x0000, 0x1E15, 0x1E3D, 0x1E65, 0x1E8D, 0x1EAB, + 0x1ED3, 0x0000, 0x1F12, 0x1F34, 0x1F56, 0x1F76, 0x1F92, 0x1FB6, 0x1FE3, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x043B, 0x044F, 0x0467, + 0x0495, 0x04BD, 0x04E3, 0x0505, 0x056B, 0x057F, 0x217B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xFF52, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x019E, 0x01CE, 0x01F5, 0x021F, 0x023F, 0x0254, 0x0268, 0x027C, + 0x0290, 0x02A4, 0x0000, 0x1E17, 0x1E3F, 0x1E67, 0x1E8F, 0x1EAD, 0x1ED5, + 0x0000, 0x1F13, 0x1F35, 0x1F57, 0x1F77, 0x1F93, 0x1FB7, 0x1FE4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x043C, 0x0450, 0x0469, 0x0497, + 0x04BF, 0x04E5, 0x0507, 0x056C, 0x0580, 0x217C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF53, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x01A1, 0x01D0, 0x01F9, 0x0221, 0x0240, 0x0255, 0x0269, 0x027D, 0x0291, + 0x02A5, 0x0000, 0x1E19, 0x1E41, 0x1E69, 0x1E91, 0x1EAF, 0x1ED7, 0x0000, + 0x1F14, 0x1F36, 0x0000, 0x1F78, 0x1F94, 0x1FC2, 0x1FE5, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x043D, 0x0451, 0x046B, 0x0499, 0x0000, + 0x04E7, 0x0509, 0x056D, 0x0581, 0x217D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xFF54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01A3, + 0x01D2, 0x01FB, 0x0223, 0x0000, 0x0256, 0x026A, 0x027E, 0x0292, 0x02A6, + 0x0000, 0x1E1B, 0x1E43, 0x1E6B, 0x1E93, 0x1EB1, 0x1ED9, 0x0000, 0x1F15, + 0x1F37, 0x0000, 0x1F79, 0x1F95, 0x1FC3, 0x1FE6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x043E, 0x0452, 0x046D, 0x049B, 0x04C2, 0x04E9, + 0x050B, 0x056E, 0x0582, 0x217E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01A5, 0x01D4, + 0x01FD, 0x0225, 0x0000, 0x0257, 0x026B, 0x027F, 0x0293, 0x02A7, 0x0000, + 0x1E1D, 0x1E45, 0x1E6D, 0x1E95, 0x1EB3, 0x1EDB, 0x0000, 0x0000, 0x1F40, + 0x0000, 0x1F7A, 0x1F96, 0x1FC4, 0x1FE7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x043F, 0x0453, 0x046F, 0x049D, 0x04C4, 0x04EB, 0x050D, + 0x056F, 0x0583, 0x217F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF56, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01A8, 0x01D6, 0x01FF, + 0x0227, 0x0000, 0x0258, 0x026C, 0x0280, 0x0294, 0x02A8, 0x0000, 0x1E1F, + 0x1E47, 0x1E6F, 0x1E96, 0x1EB5, 0x1EDD, 0x0000, 0x0000, 0x1F41, 0x0000, + 0x1F7B, 0x1F97, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0440, 0x0454, 0x0471, 0x049F, 0x04C6, 0x04ED, 0x050F, 0x0570, + 0x0584, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF57, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AA, 0x01D8, 0x0201, 0x0229, + 0x0000, 0x0259, 0x026D, 0x0281, 0x0295, 0x02A9, 0x0000, 0x1E21, 0x1E49, + 0x1E71, 0x1E97, 0x1EB7, 0x1EDF, 0x0000, 0x0000, 0x1F42, 0x1F60, 0x1F7C, + 0x1FA0, 0x1FC6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0441, 0x0455, 0x0473, 0x04A1, 0x04C8, 0x04EF, 0x0000, 0x0571, 0x0585, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF58, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01AB, 0x01DA, 0x0203, 0x022B, 0x0000, + 0x025A, 0x026E, 0x0282, 0x0296, 0x02AA, 0x0000, 0x1E23, 0x1E4B, 0x1E73, + 0x1E98, 0x1EB9, 0x1EE1, 0x0000, 0x0000, 0x1F43, 0x1F61, 0x1F7D, 0x1FA1, + 0x1FC7, 0x1FF2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0442, + 0x0456, 0x0475, 0x04A3, 0x04CA, 0x04F1, 0x0000, 0x0572, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF59, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01AD, 0x01DC, 0x0205, 0x022D, 0x0000, 0x025B, + 0x026F, 0x0283, 0x0297, 0x02AB, 0x0000, 0x1E25, 0x1E4D, 0x1E75, 0x1E99, + 0x1EBB, 0x1EE3, 0x0000, 0x1F20, 0x1F44, 0x1F62, 0x0000, 0x1FA2, 0x1FD0, + 0x1FF3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0443, 0x0457, + 0x0477, 0x04A5, 0x04CC, 0x04F3, 0x0000, 0x0573, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF5A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01B0, 0x01DD, 0x0207, 0x022F, 0x0000, 0x025C, 0x0270, + 0x0284, 0x0298, 0x02AC, 0x0000, 0x1E27, 0x1E4F, 0x1E77, 0x1E9A, 0x1EBD, + 0x1EE5, 0x0000, 0x1F21, 0x1F45, 0x1F63, 0x0000, 0x1FA3, 0x1FD1, 0x1FF4} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/init.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/init.go new file mode 100644 index 0000000000..a454e58737 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/init.go @@ -0,0 +1,32 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +/* + File system encoding components: + +Code range Pattern Number Used Unused Blocks +----------------------------------------------------------------------------- +00C0..017F [.][0..4][g..z] 5*20= 100 97 3 Latin1 Supplement + Ext A +0370..03FF [.][5..9][g..z] 5*20= 100 88 12 Greek + Coptic +0400..052F [.][g..z][0..6] 20*7= 140 140 137 Cyrillic +0530..058F [.][g..z][7..8] 20*2= 40 38 2 Armenian +2160..217F [.][g..z][9] 20*1= 20 16 4 Number Forms +0180..02AF [.][g..z][a..k] 28*11=220 203 17 Latin Ext B + IPA +1E00..0EFF [.][g..z][l..r] 20*7= 140 136 4 Latin Additional Extended +1F00..1FFF [.][g..z][s..z] 20*8= 160 144 16 Greek Extended +.... .... [.][a..f][g..z] 6*20= 120 0 120 RESERVED +24B6..24E9 [.][@][a..z] 26 26 0 Enclosed Alphanumerics +FF21..FF5A [.][a..z][@] 26 26 0 Full Width forms + +All other characters are encoded using five bytes: + +[.][0..9a..z][0..9a..z][0..9a..z][0..9a..z] + +*/ diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/safe_char.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/safe_char.go new file mode 100644 index 0000000000..9cccd74c9b --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables/safe_char.go @@ -0,0 +1,20 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package tables + +var SafeChar = []bool{ + true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, /* ................ */ + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, /* ................ */ + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, /* !"#$%&'()*+,-./ */ + true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, /* 0123456789:;<=>? */ + false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, /* @ABCDEFGHIJKLMNO */ + true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, /* PQRSTUVWXYZ[\]^_ */ + false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, /* `abcdefghijklmno */ + true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, /* pqrstuvwxyz{|}~. */ +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/tablename_to_filename.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/tablename_to_filename.go new file mode 100644 index 0000000000..0779fbd66b --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/tablename_to_filename.go @@ -0,0 +1,50 @@ +// TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +// Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +// Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://opensource.org/licenses/MIT +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +package identifiertrans + +import ( + "dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/identifiertrans/internal/tables" + "fmt" +) + +func TablenameToFilename(tablename string) (filename string) { + for _, c := range tablename { + if c < 128 && tables.SafeChar[c] { + filename += string(c) + continue + } + + filename += "@" + + if (c >= 0x00C0 && c <= 0x05FF) || + (c >= 0x1E00 && c <= 0x1FFF) || + (c >= 0x2160 && c <= 0x217F) || + (c >= 0x24B0 && c <= 0x24EF) || + (c >= 0xFF20 && c <= 0xFF5F) { + var code rune + if c >= 0x00C0 && c <= 0x05FF { + code = tables.Uni0c0005ff[c-0x00C0] + } else if c >= 0x1E00 && c <= 0x1FFF { + code = tables.Uni1e001fff[c-0x1E00] + } else if c >= 0x2160 && c <= 0x217F { + code = tables.Uni2160217f[c-0x2160] + } else if c >= 0x24B0 && c <= 0x24EF { + code = tables.Uni24b024ef[c-0x24B0] + } else if c >= 0xFF20 && c <= 0xFF5F { + code = tables.UniFf20Ff5f[c-0xFF20] + } + filename += string(code/80 + 0x30) + filename += string(code%80 + 0x30) + continue + } + + filename += fmt.Sprintf("%04x", c) + } + return filename +} diff --git a/dbm-services/mysql/db-tools/mysql-monitor/pkg/itemscollect/ibdstatistic/ibd_statistic.go b/dbm-services/mysql/db-tools/mysql-monitor/pkg/itemscollect/ibdstatistic/ibd_statistic.go index 01a6d73c0a..c6c4e4a038 100644 --- a/dbm-services/mysql/db-tools/mysql-monitor/pkg/itemscollect/ibdstatistic/ibd_statistic.go +++ b/dbm-services/mysql/db-tools/mysql-monitor/pkg/itemscollect/ibdstatistic/ibd_statistic.go @@ -31,7 +31,7 @@ var partitionPattern *regexp.Regexp func init() { ibdExt = ".ibd" - partitionPattern = regexp.MustCompile(`^(.*)#P#.*\.ibd`) + partitionPattern = regexp.MustCompile(`^(.*)#[pP]#.*\.ibd`) } From 875b12af4f075913a998bf99c877202b3ec6473f Mon Sep 17 00:00:00 2001 From: xiepaup Date: Fri, 14 Jul 2023 10:44:50 +0800 Subject: [PATCH 140/476] =?UTF-8?q?fixfredis)=EF=BC=9A=E4=BF=AE=E5=A4=8DRe?= =?UTF-8?q?dis=20=E6=95=B4=E6=9C=BA=E6=9B=BF=E6=8D=A2/=E6=95=85=E9=9A=9C?= =?UTF-8?q?=E5=88=87=E6=8D=A2=20bug=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/cluster/nosqlcomm/scale_tendis.py | 18 +++++++++++---- dbm-ui/backend/db_meta/enums/comm.py | 1 + .../atom_jobs/redis_cluster_master_rep.py | 8 +++---- .../atom_jobs/redis_cluster_slave_rep.py | 12 +++++----- .../scene/redis/redis_cluster_scene_cmr.py | 14 +++++------- .../scene/redis/redis_cluster_scene_mss.py | 1 + .../backend/flow/utils/redis/redis_db_meta.py | 22 ++++++++++++++----- 7 files changed, 48 insertions(+), 28 deletions(-) diff --git a/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/scale_tendis.py b/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/scale_tendis.py index eb82433dee..a2aa91fc53 100644 --- a/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/scale_tendis.py +++ b/dbm-ui/backend/db_meta/api/cluster/nosqlcomm/scale_tendis.py @@ -133,7 +133,7 @@ def make_sync_mms(cluster: Cluster, tendisss: List[Dict]): @transaction.atomic -def switch_tendis(cluster: Cluster, tendisss: List[Dict]): +def switch_tendis(cluster: Cluster, tendisss: List[Dict], switch_type: str = SyncType.MMS.value): """ TendisCache 建立Sync 关系为: M1->S1->M2->S2 TendisPlus 建立Sync 关系为: M1->M2->S2 @@ -189,9 +189,19 @@ def switch_tendis(cluster: Cluster, tendisss: List[Dict]): new_ejector_obj = StorageInstance.objects.get( machine__ip=ms_pair["receiver"]["ip"], port=ms_pair["receiver"]["port"] ) - new_receiver_obj = new_ejector_obj.as_ejector.get().receiver - ejector_objs.append(new_ejector_obj) - receiver_objs.append(new_receiver_obj) + if switch_type != SyncType.MS.value: + logger.info("switch for sync {} need move cc module & add cc instance".format(switch_type)) + new_receiver_obj = new_ejector_obj.as_ejector.get().receiver + ejector_objs.append(new_ejector_obj) + receiver_objs.append(new_receiver_obj) + else: + logger.info( + "switch for sync {} need update role info {} 2 master".format(switch_type, ms_pair["receiver"]) + ) + new_ejector_obj.instance_role = InstanceRole.REDIS_MASTER.value + new_ejector_obj.instance_inner_role = InstanceInnerRole.MASTER.value + new_ejector_obj.save(update_fields=["instance_role", "instance_inner_role"]) + cc_add_instances(cluster, ejector_objs, DBCCModule.REDIS.value) cc_add_instances(cluster, receiver_objs, DBCCModule.REDIS.value) except Exception as e: # NOCC:broad-except(检查工具误报) diff --git a/dbm-ui/backend/db_meta/enums/comm.py b/dbm-ui/backend/db_meta/enums/comm.py index 8bd13c84e1..f8e697b556 100644 --- a/dbm-ui/backend/db_meta/enums/comm.py +++ b/dbm-ui/backend/db_meta/enums/comm.py @@ -14,6 +14,7 @@ class SyncType(str, StructuredEnum): + MS = EnumField("ms", _("ms")) SMS = EnumField("sms", _("sms")) MMS = EnumField("mms", _("mms")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py index 8aa06707db..40e2df3c66 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_master_rep.py @@ -81,9 +81,9 @@ def RedisClusterMasterReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, ma # #### 建同步关系 ############################################################################# sub_pipelines, sync_kwargs = [], deepcopy(act_kwargs) for replace_info in master_replace_detail: - old_master = replace_info["old"]["ip"] - new_host_master = replace_info["new"][0]["ip"] - new_host_slave = replace_info["new"][1]["ip"] + old_master = replace_info["ip"] + new_host_master = replace_info["target"]["master"]["ip"] + new_host_slave = replace_info["target"]["slave"]["ip"] sync_params = { "sync_type": act_kwargs.cluster["sync_type"], "origin_1": old_master, @@ -129,7 +129,7 @@ def RedisClusterMasterReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, ma # #### 下架旧实例 ############################################################################# sub_pipelines, shutdown_kwargs = [], deepcopy(act_kwargs) for replace_info in master_replace_detail: - old_master = replace_info["old"]["ip"] + old_master = replace_info["ip"] params = { "ip": old_master, "ports": act_kwargs.cluster["master_ports"][old_master], diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py index e123746eb5..6a79c91be8 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_cluster_slave_rep.py @@ -68,8 +68,8 @@ def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, sla sub_pipelines = [] for replace_link in slave_replace_detail: # "Old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - old_slave = replace_link["old"]["ip"] - new_slave = replace_link["new"]["ip"] + old_slave = replace_link["ip"] + new_slave = replace_link["target"]["ip"] install_params = { "sync_type": SyncType.SYNC_MS, "origin_1": act_kwargs.cluster["slave_master_map"][old_slave], @@ -93,8 +93,8 @@ def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, sla act_kwargs.cluster["tendiss"] = [] for replace_link in slave_replace_detail: # "Old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - old_slave = replace_link["old"]["ip"] - new_slave = replace_link["new"]["ip"] + old_slave = replace_link["ip"] + new_slave = replace_link["target"]["ip"] act_kwargs.cluster["old_slaves"].append( {"ip": old_slave, "ports": act_kwargs.cluster["slave_ports"][old_slave]} ) @@ -119,8 +119,8 @@ def RedisClusterSlaveReplaceJob(root_id, ticket_data, sub_kwargs: ActKwargs, sla sub_pipelines = [] for replace_link in slave_replace_detail: # "Old": {"ip": "2.2.a.4", "bk_cloud_id": 0, "bk_host_id": 123}, - old_slave = replace_link["old"]["ip"] - new_slave = replace_link["new"]["ip"] + old_slave = replace_link["ip"] + new_slave = replace_link["target"]["ip"] params = { "ignore_ips": act_kwargs.cluster["slave_master_map"][old_slave], "ip": old_slave, diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py index 02a85080a0..673830b835 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py @@ -358,19 +358,17 @@ def precheck_for_compelete_replace(self): raise Exception("redis cluster does not exist,{}", e) # check proxy for proxy in cluster_replacement.get("redis_proxy", []): - if not cluster.proxyinstance_set.filter(machine__ip=proxy["old"]["ip"]): - raise Exception("proxy {} does not exist in cluster {}", proxy["old"]["ip"], cluster.immute_domain) + if not cluster.proxyinstance_set.filter(machine__ip=proxy["ip"]): + raise Exception("proxy {} does not exist in cluster {}", proxy["ip"], cluster.immute_domain) # check slave for slave in cluster_replacement.get("redis_slave", []): if not cluster.storageinstance_set.filter( - machine__ip=slave["old"]["ip"], instance_role=InstanceRole.REDIS_SLAVE.value + machine__ip=slave["ip"], instance_role=InstanceRole.REDIS_SLAVE.value ): - raise Exception("slave {} does not exist in cluster {}", slave["old"]["ip"], cluster.immute_domain) + raise Exception("slave {} does not exist in cluster {}", slave["ip"], cluster.immute_domain) # check master for master in cluster_replacement.get("redis_master", []): if not cluster.storageinstance_set.filter( - machine__ip=master["old"]["ip"], instance_role=InstanceRole.REDIS_MASTER.value + machine__ip=master["ip"], instance_role=InstanceRole.REDIS_MASTER.value ): - raise Exception( - "master {} does not exist in cluster {}", master["old"]["ip"], cluster.immute_domain - ) + raise Exception("master {} does not exist in cluster {}", master["ip"], cluster.immute_domain) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py index f40cb98201..de7d4fc7e0 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py @@ -223,6 +223,7 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch): act_kwargs.get_redis_payload_func = RedisActPayload.bkdbmon_install.__name__ for slave_ip in slave_ips: sub_kwargs = deepcopy(act_kwargs) + sub_kwargs.exec_ip = slave_ip sub_kwargs.cluster["servers"] = [ { "app": app, diff --git a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py index 87d23e6d78..d12794d35b 100644 --- a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py +++ b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py @@ -22,8 +22,8 @@ from backend.db_meta.api.cluster.tendiscache.handler import TendisCacheClusterHandler from backend.db_meta.api.cluster.tendispluscluster.handler import TendisPlusClusterHandler from backend.db_meta.api.cluster.tendisssd.handler import TendisSSDClusterHandler -from backend.db_meta.enums import ClusterPhase, ClusterType, InstanceInnerRole, InstanceRole, MachineType -from backend.db_meta.models import Cluster, StorageInstance +from backend.db_meta.enums import AccessLayer, ClusterPhase, ClusterType, InstanceInnerRole, InstanceRole, MachineType +from backend.db_meta.models import Cluster, Machine, ProxyInstance, StorageInstance from backend.db_services.dbbase.constants import IP_PORT_DIVIDER, SPACE_DIVIDER from backend.db_services.redis.rollback.models import TbTendisRollbackTasks from backend.flow.consts import DEFAULT_DB_MODULE_ID, ConfigFileEnum, ConfigTypeEnum, InstanceStatus @@ -406,9 +406,15 @@ def instances_status_update(self) -> bool: Redis/Proxy 实例修改实例状态 {"ip":"","ports":[],"status":11} """ with atomic(): - api.cluster.nosqlcomm.decommission_instances( - ip=self.cluster["ip"], bk_cloud_id=self.cluster["bk_cloud_id"], ports=self.cluster["ports"] - ) + machine_obj = Machine.objects.get(ip=self.cluster["meta_update_ip"]) + if machine_obj.access_layer == AccessLayer.PROXY.value: + ProxyInstance.objects.filter( + machine__ip=self.cluster["meta_update_ip"], port__in=self.cluster["meta_udpate_ports"] + ).update(status=self.cluster["meta_update_status"]) + else: + StorageInstance.objects.filter( + machine__ip=self.cluster["meta_update_ip"], port__in=self.cluster["meta_udpate_ports"] + ).update(status=self.cluster["meta_update_status"]) return True def tendis_switch_4_scene(self): @@ -416,7 +422,11 @@ def tendis_switch_4_scene(self): cluster = Cluster.objects.get( bk_cloud_id=self.cluster["bk_cloud_id"], immute_domain=self.cluster["immute_domain"] ) - api.cluster.nosqlcomm.switch_tendis(cluster=cluster, tendisss=self.cluster["sync_relation"]) + api.cluster.nosqlcomm.switch_tendis( + cluster=cluster, + tendisss=self.cluster["sync_relation"], + switch_type=self.cluster["switch_condition"]["sync_type"], + ) def update_rollback_task_status(self) -> bool: """ From ebcfccadc61f76fa9dc80af2433739f4cdb43a84 Mon Sep 17 00:00:00 2001 From: yksitu <92353472+yksitu@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:39:15 +0800 Subject: [PATCH 141/476] =?UTF-8?q?fix(mysql):=20=E4=BF=AE=E5=A4=8Dspider-?= =?UTF-8?q?master=E8=A7=92=E8=89=B2=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E9=81=97=E7=95=99=E7=9A=84=E9=97=AE=E9=A2=98=20#441?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #441 --- .../api/cluster/tendbcluster/__init__.py | 3 +- .../api/cluster/tendbcluster/add_spider.py | 61 ++++++++++ .../tendbcluster/create_slave_cluster.py | 43 +------ .../api/cluster/tendbcluster/handler.py | 114 +++++------------- .../bamboo/scene/common/get_file_list.py | 4 - .../scene/spider/common/common_sub_flow.py | 42 ++++--- .../bamboo/scene/spider/spider_add_nodes.py | 19 +-- .../scene/spider/spider_cluster_deploy.py | 58 ++------- .../scene/spider/spider_cluster_destroy.py | 4 +- .../collections/mysql/clone_user.py | 17 ++- .../collections/spider/add_spider_routing.py | 109 +++++++++++++++-- .../collections/spider/ctl_drop_routing.py | 1 + .../collections/spider/drop_spider_ronting.py | 13 +- .../utils/mysql/check_client_connections.py | 3 + .../flow/utils/mysql/mysql_act_playload.py | 9 +- .../flow/utils/spider/get_spider_incr.py | 2 - .../flow/utils/spider/spider_db_meta.py | 53 ++++---- 17 files changed, 300 insertions(+), 255 deletions(-) create mode 100644 dbm-ui/backend/db_meta/api/cluster/tendbcluster/add_spider.py diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/__init__.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/__init__.py index 4d8e512898..f017b06a3c 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/__init__.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/__init__.py @@ -7,7 +7,8 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ +from .add_spider import add_spiders from .add_spider_mnt import add_spider_mnt from .create_cluster import create, create_pre_check -from .create_slave_cluster import add_spider_slaves, slave_cluster_create_pre_check +from .create_slave_cluster import slave_cluster_create_pre_check from .decommission import decommission, decommission_precheck diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/add_spider.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/add_spider.py new file mode 100644 index 0000000000..140cd7cad6 --- /dev/null +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/add_spider.py @@ -0,0 +1,61 @@ +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from typing import List, Optional + +from django.db import transaction + +from backend.db_meta.api import common +from backend.db_meta.enums import InstanceInnerRole, TenDBClusterSpiderRole +from backend.db_meta.models import Cluster, ClusterEntry, ProxyInstance, TenDBClusterSpiderExt + + +@transaction.atomic +def add_spiders( + cluster: Optional[Cluster], + spiders: Optional[List], + spider_role: Optional[TenDBClusterSpiderRole], + domain_entry: Optional[ClusterEntry] = None, +): + """ + 添加spider节点元信息, 包括spider不同角色的添加 + """ + # 获取相关的spider节点orm对象 + spiders_objs = common.filter_out_instance_obj(spiders, ProxyInstance.objects.all()) + + # 对所有的spider实例角色属性 + for obj in spiders_objs: + TenDBClusterSpiderExt.objects.create(instance=obj, spider_role=spider_role) + + # 添加 cluster 与所有spider实例的映射关系 + cluster.proxyinstance_set.add(*spiders_objs) + + # 对所有的分片的实例,添加与spider实例的映射关系 + for shard_info in cluster.tendbclusterstorageset_set.exclude( + storage_instance_tuple__ejector__instance_inner_role=InstanceInnerRole.REPEATER + ): + if spider_role == TenDBClusterSpiderRole.SPIDER_MASTER: + # ejector是代表master实例对象 + shard_info.storage_instance_tuple.ejector.proxyinstance_set.add(*spiders_objs) + + if spider_role == TenDBClusterSpiderRole.SPIDER_SLAVE: + # receiver是代表slave实例对象 + shard_info.storage_instance_tuple.receiver.proxyinstance_set.add(*spiders_objs) + + if not spider_role == TenDBClusterSpiderRole.SPIDER_MNT: + # 非运维节点添加域名映射 + domain_entry.proxyinstance_set.add(*spiders_objs) + + # 直到这里才有明确的 db module + for ins in spiders_objs: + m = ins.machine + ins.db_module_id = cluster.db_module_id + m.db_module_id = cluster.db_module_id + ins.save(update_fields=["db_module_id"]) + m.save(update_fields=["db_module_id"]) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_slave_cluster.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_slave_cluster.py index 34b82c1aaa..ffef7a7982 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_slave_cluster.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/create_slave_cluster.py @@ -12,10 +12,9 @@ from django.db import transaction from django.utils.translation import ugettext as _ -from backend.db_meta.api import common -from backend.db_meta.enums import ClusterEntryRole, ClusterEntryType, InstanceInnerRole, TenDBClusterSpiderRole +from backend.db_meta.enums import ClusterEntryType from backend.db_meta.exceptions import DBMetaException -from backend.db_meta.models import Cluster, ClusterEntry, ProxyInstance, TenDBClusterSpiderExt +from backend.db_meta.models import ClusterEntry @transaction.atomic @@ -31,41 +30,3 @@ def slave_cluster_create_pre_check(slave_domain: str): if pre_check_errors: raise DBMetaException(message=", ".join(pre_check_errors)) - - -@transaction.atomic -def add_spider_slaves( - cluster: Optional[Cluster], - spiders: Optional[List], - cluster_slave_entry: Optional[ClusterEntry], -): - """ - 添加从节点元信息 - """ - # 获取相关的spider节点orm对象 - spiders_objs = common.filter_out_instance_obj(spiders, ProxyInstance.objects.all()) - - # 对所有的spider slave实例角色属性 - for obj in spiders_objs: - TenDBClusterSpiderExt.objects.create(instance=obj, spider_role=TenDBClusterSpiderRole.SPIDER_SLAVE) - - # 添加 cluster 与所有spider slave 实例的映射关系 - cluster.proxyinstance_set.add(*spiders_objs) - - # 对所有的分片的slave实例,添加与spider slave实例的映射关系 - for shard_info in cluster.tendbclusterstorageset_set.exclude( - storage_instance_tuple__ejector__instance_inner_role=InstanceInnerRole.REPEATER - ): - # receiver是代表slave实例对象 - shard_info.storage_instance_tuple.receiver.proxyinstance_set.add(*spiders_objs) - - # 添加从域名映射 - cluster_slave_entry.proxyinstance_set.add(*spiders_objs) - - # 直到这里才有明确的 db module - for ins in spiders_objs: - m = ins.machine - ins.db_module_id = cluster.db_module_id - m.db_module_id = cluster.db_module_id - ins.save(update_fields=["db_module_id"]) - m.save(update_fields=["db_module_id"]) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py index 6360bf1d23..b84afe98c0 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py @@ -25,6 +25,7 @@ InstanceInnerRole, InstanceRole, MachineType, + TenDBClusterSpiderRole, ) from backend.db_meta.models import Cluster, ClusterEntry, StorageInstanceTuple from backend.db_package.models import Package @@ -175,35 +176,41 @@ def topo_graph(self): @classmethod @transaction.atomic - def add_spider_slaves( + def add_spiders( cls, cluster_id: int, creator: str, spider_version: str, - slave_domain: str, - spider_slaves: list, - is_create: bool, + add_spiders: list, + spider_role: Optional[TenDBClusterSpiderRole], + resource_spec: dict, + is_slave_cluster_create: bool, + domain: str = None, ): """ - 对已有的集群添加从集群信息 + 对已有的集群添加spider的元信息 因为从集群添加的行为spider-slave扩容行为基本类似,所以这里作为一个公共方法,对域名处理根据不同单据类型做不同的处理 @param cluster_id: 待关联的集群id @param creator: 提单的用户名称 @param spider_version: 待加入的spider版本号(包括小版本信息) - @param slave_domain: 待添加从域名 - @param spider_slaves: 待加入的spider-slave机器信息 - @param is_create: 代表这次是否是添加从集群,还是spider-slave扩容 + @param domain: 待关联的域名 + @param add_spiders: 待加入的spider机器信息 + @param spider_role: 待加入spider的角色 + @param resource_spec: 待加入spider的规格 + @param is_slave_cluster_create: 代表这次是否是添加从集群 """ cluster = Cluster.objects.get(id=cluster_id) # 录入机器 machines = [] - for ip_info in spider_slaves: + for ip_info in add_spiders: machines.append( { "ip": ip_info["ip"], "bk_biz_id": cluster.bk_biz_id, "machine_type": MachineType.SPIDER.value, + "spec_id": resource_spec[MachineType.SPIDER.value]["id"], + "spec_config": resource_spec[MachineType.SPIDER.value], }, ) # 录入机器信息 @@ -215,54 +222,48 @@ def add_spider_slaves( version=spider_version, pkg_type=MediumEnum.Spider, db_type=DBType.MySQL ) - for ip_info in spider_slaves: + for ip_info in add_spiders: spiders.append( { "ip": ip_info["ip"], "port": cluster.proxyinstance_set.first().port, - "admin_port": cluster.proxyinstance_set.first().admin_port, # spider_slave是否存储管理端口? + "admin_port": cluster.proxyinstance_set.first().admin_port, "version": get_spider_real_version(spider_pkg.name), } ) # 新增的实例继承cluster集群的时区设置 api.proxy_instance.create(proxies=spiders, creator=creator, time_zone=cluster.time_zone) - # 判断is_create参数,如果是True则代表做从集群添加,需要添加从域名元信息;如果False则代表spider-slave扩容 - if is_create: - api.cluster.tendbcluster.slave_cluster_create_pre_check(slave_domain=slave_domain) - cluster_slave_entry = ClusterEntry.objects.create( + # 判断is_slave_cluster_create参数,如果是True则代表做从集群添加,需要添加从域名元信息;如果False则代表spider扩容 + if is_slave_cluster_create: + api.cluster.tendbcluster.slave_cluster_create_pre_check(slave_domain=domain) + cluster_entry = ClusterEntry.objects.create( cluster=cluster, cluster_entry_type=ClusterEntryType.DNS, - entry=slave_domain, + entry=domain, creator=creator, role=ClusterEntryRole.SLAVE_ENTRY.value, ) else: - cluster_slave_entry = cluster.clusterentry_set.get(entry=slave_domain) + if domain: + cluster_entry = cluster.clusterentry_set.get(entry=domain) + else: + # 运维节点添加不需要做域名映射 + cluster_entry = None # 录入集群相关信息 - api.cluster.tendbcluster.add_spider_slaves( - cluster=cluster, spiders=spiders, cluster_slave_entry=cluster_slave_entry + api.cluster.tendbcluster.add_spiders( + cluster=cluster, spiders=spiders, domain_entry=cluster_entry, spider_role=spider_role ) # spider主机转移模块、添加对应的服务实例 transfer_host_in_cluster_module( cluster_ids=[cluster_id], - ip_list=[ip_info["ip"] for ip_info in spider_slaves], + ip_list=[ip_info["ip"] for ip_info in add_spiders], machine_type=MachineType.SPIDER.value, bk_cloud_id=cluster.bk_cloud_id, ) - @classmethod - @transaction.atomic - def add_spider_master( - cls, - cluster_id: int, - creator: str, - spider_masters: list, - ): - pass - @classmethod @transaction.atomic def reduce_spider( @@ -324,56 +325,3 @@ def remote_switch(cls, cluster_id: int, switch_tuples: list): "labels": {"instance_role": InstanceRole.BACKEND_SLAVE.value}, } ) - - def spider_mnt_create(cls, cluster_id, creator, spider_version, spider_mnts): - """ - 对已有的集群添加临时节点信息 - 根据cluster_id获取相关的cluster信息 - """ - cluster = Cluster.objects.get(id=cluster_id) - - # 录入机器 - machines = [] - for ip_info in spider_mnts: - machines.append( - { - "ip": ip_info["ip"], - "bk_biz_id": cluster.bk_biz_id, - "machine_type": MachineType.SPIDER.value, - }, - ) - # # 录入机器信息 - api.machine.create(machines=machines, creator=creator, bk_cloud_id=cluster.bk_cloud_id) - - # 录入机器对应的实例信息 - spiders = [] - spider_pkg = Package.get_latest_package( - version=spider_version, pkg_type=MediumEnum.Spider, db_type=DBType.MySQL - ) - - for ip_info in spider_mnts: - spiders.append( - { - "ip": ip_info["ip"], - "port": cluster.proxyinstance_set.first().port, - "admin_port": cluster.proxyinstance_set.first().admin_port, # spider_slave是否存储管理端口? - "version": get_spider_real_version(spider_pkg.name), - } - ) - # # 新增的实例继承cluster集群的时区设置 - api.proxy_instance.create(proxies=spiders, creator=creator, time_zone=cluster.time_zone) - - # 录入集群相关信息 - # 这里区分与从域名的与检查从域名,不用检查域名,应为已经有了cluster id,主域名是必然存在的 - api.cluster.tendbcluster.add_spider_mnt( - cluster=cluster, - spiders=spiders, - ) - - # spider主机转移模块、添加对应的服务实例 - transfer_host_in_cluster_module( - cluster_ids=[cluster_id], - ip_list=[ip_info["ip"] for ip_info in spider_mnts], - machine_type=MachineType.SPIDER.value, - bk_cloud_id=cluster.bk_cloud_id, - ) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py b/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py index f1a62cb89b..07e5ba3a66 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/common/get_file_list.py @@ -463,14 +463,10 @@ def spider_slave_install_package(self, spider_version: str) -> list: mysql_crond_pkg = Package.get_latest_package( version=MediumEnum.Latest, pkg_type=MediumEnum.MySQLCrond, db_type=DBType.MySQL ) - mysql_monitor_pkg = Package.get_latest_package( - version=MediumEnum.Latest, pkg_type=MediumEnum.MySQLMonitor, db_type=DBType.MySQL - ) return [ f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{self.actuator_pkg.path}", f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{spider_slave_pkg.path}", f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{mysql_crond_pkg.path}", - f"{env.BKREPO_PROJECT}/{env.BKREPO_BUCKET}/{mysql_monitor_pkg.path}", ] @staticmethod diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py index 253f73074e..50615e9aa8 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/common/common_sub_flow.py @@ -14,7 +14,7 @@ from backend.configuration.constants import DBType from backend.constants import IP_PORT_DIVIDER -from backend.db_meta.enums import ClusterType, InstanceStatus, TenDBClusterSpiderRole +from backend.db_meta.enums import ClusterType, InstanceStatus, MachineType, TenDBClusterSpiderRole from backend.db_meta.models import Cluster from backend.flow.consts import AUTH_ADDRESS_DIVIDER, DBA_ROOT_USER, TDBCTL_USER from backend.flow.engine.bamboo.scene.common.builder import SubBuilder @@ -149,6 +149,7 @@ def add_spider_slaves_sub_flow( { "source": tmp_spider.ip_port, "target": f"{spider['ip']}{AUTH_ADDRESS_DIVIDER}{tmp_spider.port}", + "machine_type": MachineType.SPIDER.value, "bk_cloud_id": cluster.bk_cloud_id, }, ] @@ -211,6 +212,7 @@ def add_spider_masters_sub_flow( # 获取到集群对应的spider端口,作为这次的安装 parent_global_data["spider_ports"] = [cluster.proxyinstance_set.first().port] + parent_global_data["ctl_port"] = cluster.proxyinstance_set.first().admin_port sub_pipeline = SubBuilder(root_id=root_id, data=parent_global_data) # 拼接执行原子任务活动节点需要的通用的私有参数结构体, 减少代码重复率,但引用时注意内部参数值传递的问题 @@ -227,7 +229,7 @@ def add_spider_masters_sub_flow( DownloadMediaKwargs( bk_cloud_id=cluster.bk_cloud_id, exec_ip=[ip_info["ip"] for ip_info in add_spider_masters], - file_list=GetFileList(db_type=DBType.MySQL).spider_slave_install_package( + file_list=GetFileList(db_type=DBType.MySQL).spider_master_install_package( spider_version=parent_global_data["spider_version"] ), ) @@ -273,6 +275,7 @@ def add_spider_masters_sub_flow( # 判断添加的角色来是否安装中控实例,spider-mnt不需要安装 if not is_add_spider_mnt: + acts_list = [] for ctl_ip in add_spider_masters: exec_act_kwargs.exec_ip = ctl_ip["ip"] exec_act_kwargs.cluster = {"immutable_domain": cluster.immute_domain} @@ -290,7 +293,6 @@ def add_spider_masters_sub_flow( acts_list = [] # 这里获取集群内running状态的spider节点作为这次克隆权限的依据 - # todo 这里目前spider节点克隆权限API接口出现异常,需要调整 tmp_spider = cluster.proxyinstance_set.filter(status=InstanceStatus.RUNNING)[0] for spider in add_spider_masters: @@ -304,6 +306,7 @@ def add_spider_masters_sub_flow( { "source": tmp_spider.ip_port, "target": f"{spider['ip']}{AUTH_ADDRESS_DIVIDER}{tmp_spider.port}", + "machine_type": MachineType.SPIDER.value, "bk_cloud_id": cluster.bk_cloud_id, }, ] @@ -335,11 +338,12 @@ def add_spider_masters_sub_flow( if not is_add_spider_mnt: # 阶段8 待添加中控实例建立主从数据同步关系 sub_pipeline.add_sub_pipeline( - sub_flow=add_ctl_node_with_gtid( + sub_flow=build_ctl_replication_with_gtid( root_id=root_id, parent_global_data=parent_global_data, - cluster=cluster, - add_tdbctls=add_spider_masters, + bk_cloud_id=cluster.bk_cloud_id, + ctl_primary=cluster.tendbcluster_ctl_primary_address(), + ctl_secondary_list=add_spider_masters, ) ) # 阶段8 添加域名映射关系 @@ -444,20 +448,20 @@ def build_apps_for_spider_sub_flow( return sub_pipeline.build_sub_process(sub_name=_("安装Spider周边程序")) -def add_ctl_node_with_gtid( +def build_ctl_replication_with_gtid( root_id: str, parent_global_data: dict, - cluster: Cluster, - add_tdbctls: list, + bk_cloud_id: int, + ctl_primary: str, + ctl_secondary_list: list, ): """ 添加新的定义ctl建立基于gtid的主从同步 """ - ctl_master = cluster.tendbcluster_ctl_primary_address() extend = { - "mysql_port": ctl_master.split(":")[1], - "master_ip": ctl_master.split(":")[0], - "slaves": [ip_info["ip"] for ip_info in add_tdbctls], + "mysql_port": int(ctl_primary.split(":")[1]), + "master_ip": ctl_primary.split(":")[0], + "slaves": [ip_info["ip"] for ip_info in ctl_secondary_list], } sub_pipeline = SubBuilder(root_id=root_id, data=parent_global_data) @@ -466,22 +470,22 @@ def add_ctl_node_with_gtid( act_component_code=ExecuteDBActuatorScriptComponent.code, kwargs=asdict( ExecActuatorKwargs( - bk_cloud_id=cluster.bk_cloud_id, - exec_ip=ctl_master.split(":")[0], + bk_cloud_id=bk_cloud_id, + exec_ip=ctl_primary.split(":")[0], get_mysql_payload_func=MysqlActPayload.get_grant_repl_for_ctl_payload.__name__, cluster=extend, ) ), ) acts_list = [] - for tdbctl in add_tdbctls: + for tdbctl in ctl_secondary_list: acts_list.append( { "act_name": _("建立主从关系"), "act_component_code": ExecuteDBActuatorScriptComponent.code, "kwargs": asdict( ExecActuatorKwargs( - bk_cloud_id=cluster.bk_cloud_id, + bk_cloud_id=bk_cloud_id, exec_ip=tdbctl["ip"], get_mysql_payload_func=MysqlActPayload.get_change_master_for_gitd_payload.__name__, cluster=extend, @@ -491,7 +495,7 @@ def add_ctl_node_with_gtid( ) sub_pipeline.add_parallel_acts(acts_list=acts_list) - return sub_pipeline.build_sub_process(sub_name=_("部署spider-ctl集群")) + return sub_pipeline.build_sub_process(sub_name=_("建立spider-ctl数据同步")) def reduce_spider_slaves_flow( @@ -743,6 +747,7 @@ def remote_migrate_switch_sub_flow( { "source": f"{tuple_info['old_master']}", "target": f"{tuple_info['new_master']}", + "machine_type": MachineType.REMOTE.value, "bk_cloud_id": cluster.bk_cloud_id, } ) @@ -750,6 +755,7 @@ def remote_migrate_switch_sub_flow( { "source": f"{tuple_info['old_slave']}", "target": f"{tuple_info['new_slave']}", + "machine_type": MachineType.REMOTE.value, "bk_cloud_id": cluster.bk_cloud_id, } ) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py index e6024bc813..d6de6372e3 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_add_nodes.py @@ -16,7 +16,7 @@ from django.utils.translation import ugettext as _ from backend.db_meta.enums import ClusterEntryRole, TenDBClusterSpiderRole -from backend.db_meta.models import Cluster +from backend.db_meta.models import Cluster, ClusterEntry from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder from backend.flow.engine.bamboo.scene.spider.common.common_sub_flow import ( add_spider_masters_sub_flow, @@ -76,24 +76,28 @@ def add_spider_nodes(self): if info["add_spider_role"] == TenDBClusterSpiderRole.SPIDER_MASTER: # 加入spider-master 子流程 + sub_flow_context["ctl_charset"] = spider_charset sub_pipelines.append(self.add_spider_master_notes(sub_flow_context, cluster)) elif info["add_spider_role"] == TenDBClusterSpiderRole.SPIDER_SLAVE: - # 先判断集群是否存在已添加从集群,如果没有则跳过这次扩容,判断依据是集群是存在有且只有一个的从域名 - slave_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.SLAVE_ENTRY) - if not slave_dns: + try: + # 先判断集群是否存在已添加从集群,如果没有则跳过这次扩容,判断依据是集群是存在有且只有一个的从域名 + slave_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.SLAVE_ENTRY) + # 加入spider-slave 子流程 + sub_pipelines.append(self.add_spider_slave_notes(sub_flow_context, cluster, slave_dns.entry)) + + except ClusterEntry.DoesNotExist: logger.warning(_("[{}]The cluster has not added a slave cluster, skip".format(cluster.name))) continue - # 加入spider-slave 子流程 - sub_pipelines.append(self.add_spider_slave_notes(sub_flow_context, cluster, slave_dns.entry)) - else: # 理论上不会出现,出现就中断这次流程构造 raise NormalSpiderFlowException( message=_("[{}]This type of role addition is not supported".format(info["add_spider_role"])) ) + if not sub_pipelines: + raise NormalSpiderFlowException(message=_("build spider-add-nodes-pipeline failed")) pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) pipeline.run_pipeline() @@ -102,7 +106,6 @@ def add_spider_master_notes(self, sub_flow_context: dict, cluster: Cluster): """ 定义spider master集群部署子流程 目前产品形态 spider专属一套集群,所以流程只支持spider单机单实例安装 - todo 目前spider-master扩容功能开发中,当前中控版本需要调整,等最新版本做联调工作 """ # 启动子流程 diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py index 78f4dd6152..4e077b8489 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py @@ -17,6 +17,7 @@ from django.utils.translation import ugettext as _ from backend.configuration.constants import DBType +from backend.constants import IP_PORT_DIVIDER from backend.db_meta.enums import ClusterType, TenDBClusterSpiderRole from backend.flow.consts import TDBCTL_USER from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder @@ -25,7 +26,10 @@ build_repl_by_manual_input_sub_flow, build_surrounding_apps_sub_flow, ) -from backend.flow.engine.bamboo.scene.spider.common.common_sub_flow import build_apps_for_spider_sub_flow +from backend.flow.engine.bamboo.scene.spider.common.common_sub_flow import ( + build_apps_for_spider_sub_flow, + build_ctl_replication_with_gtid, +) from backend.flow.plugins.components.collections.mysql.dns_manage import MySQLDnsManageComponent from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent from backend.flow.plugins.components.collections.mysql.trans_flies import TransFileComponent @@ -308,7 +312,13 @@ def deploy_cluster(self): # 阶段5 构建spider中控集群 deploy_pipeline.add_sub_pipeline( - sub_flow=self.build_ctl_replication_with_gtid(ctl_master=ctl_master, ctl_slaves=ctl_slaves) + sub_flow=build_ctl_replication_with_gtid( + root_id=self.root_id, + parent_global_data=self.data, + bk_cloud_id=int(self.data["bk_cloud_id"]), + ctl_primary=f"{ctl_master['ip']}{IP_PORT_DIVIDER}{self.data['ctl_port']}", + ctl_secondary_list=ctl_slaves, + ) ) # 阶段6 内部集群节点之间授权 @@ -383,47 +393,3 @@ def deploy_cluster(self): sub_flow=deploy_pipeline.build_sub_process(sub_name=_("{}集群部署").format(self.data["cluster_name"])) ) pipeline.run_pipeline(init_trans_data_class=SpiderApplyManualContext()) - - def build_ctl_replication_with_gtid(self, ctl_master: dict, ctl_slaves: list): - """ - 定义ctl建立基于gtid的主从同步 - """ - - cluster = { - "mysql_port": self.data["ctl_port"], - "master_ip": ctl_master["ip"], - "slaves": [ip_info["ip"] for ip_info in ctl_slaves], - } - - sub_pipeline = SubBuilder(root_id=self.root_id, data=self.data) - sub_pipeline.add_act( - act_name=_("新增repl帐户"), - act_component_code=ExecuteDBActuatorScriptComponent.code, - kwargs=asdict( - ExecActuatorKwargs( - bk_cloud_id=self.data["bk_cloud_id"], - exec_ip=ctl_master["ip"], - get_mysql_payload_func=MysqlActPayload.get_grant_repl_for_ctl_payload.__name__, - cluster=cluster, - ) - ), - ) - acts_list = [] - for slave in ctl_slaves: - acts_list.append( - { - "act_name": _("建立主从关系"), - "act_component_code": ExecuteDBActuatorScriptComponent.code, - "kwargs": asdict( - ExecActuatorKwargs( - bk_cloud_id=self.data["bk_cloud_id"], - exec_ip=slave["ip"], - get_mysql_payload_func=MysqlActPayload.get_change_master_for_gitd_payload.__name__, - cluster=cluster, - ) - ), - } - ) - - sub_pipeline.add_parallel_acts(acts_list=acts_list) - return sub_pipeline.build_sub_process(sub_name=_("部署spider-ctl集群")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py index f994d0a31b..216a1aa298 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_destroy.py @@ -68,8 +68,8 @@ def __get_cluster_info(cluster_id: int) -> dict: "name": cluster.name, "remote_objs": remote_objs, "spider_port": spider_objs[0].port, - "remote_ip_list": [s.machine.ip for s in remote_objs], - "spider_ip_list": [s.machine.ip for s in spider_objs], + "remote_ip_list": list(set([s.machine.ip for s in remote_objs])), + "spider_ip_list": list(set([s.machine.ip for s in spider_objs])), "spider_ctl_port": ctl_objs[0].admin_port, "spider_ctl_ip_list": [c.machine.ip for c in ctl_objs], } diff --git a/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_user.py b/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_user.py index 6c664934c8..eb6f6f8e77 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_user.py +++ b/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_user.py @@ -27,6 +27,8 @@ class CloneUserService(BaseService): """ slave 克隆账号 + 优化即使实例不在db_meta记录,都能克隆权限(针对添加实例场景) + 如果传入不存machine_type, 则db_meta为准,兼容旧版本代表 """ def _execute(self, data, parent_data, callback=None) -> bool: @@ -40,17 +42,20 @@ def _execute(self, data, parent_data, callback=None) -> bool: try: for clone_data in clone_data_list: - params = {"bk_biz_id": global_data["bk_biz_id"], "operator": global_data["created_by"]} + if clone_data.get("machine_type"): + target_machine_type = source_machine_type = clone_data["machine_type"] + else: + source_machine_type = address__machine_map[clone_data["source"]].machine_type + target_machine_type = address__machine_map[clone_data["target"]].machine_type + + params = {"bk_biz_id": int(global_data["bk_biz_id"]), "operator": global_data["created_by"]} params.update( { "source": { "address": clone_data["source"], - "machine_type": address__machine_map[clone_data["source"]].machine_type, - }, - "target": { - "address": clone_data["target"], - "machine_type": address__machine_map[clone_data["target"]].machine_type, + "machine_type": source_machine_type, }, + "target": {"address": clone_data["target"], "machine_type": target_machine_type}, "bk_cloud_id": clone_data["bk_cloud_id"], } ) diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/add_spider_routing.py b/dbm-ui/backend/flow/plugins/components/collections/spider/add_spider_routing.py index 9b5b4f9dea..9911a17af8 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/spider/add_spider_routing.py +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/add_spider_routing.py @@ -16,7 +16,7 @@ from backend.core.encrypt.handlers import RSAHandler from backend.db_meta.enums import TenDBClusterSpiderRole from backend.db_meta.models import Cluster -from backend.flow.consts import PrivRole +from backend.flow.consts import TDBCTL_USER, PrivRole from backend.flow.engine.bamboo.scene.spider.common.exceptions import ( AddSpiderNodeFailedException, NormalSpiderFlowException, @@ -39,6 +39,59 @@ class AddSpiderRoutingService(BaseService): } """ + def _drop_user(self, spider_ip: str, spider_port: int, cluster: Cluster): + """ + todo 临时方法,后续需要调整这块逻辑再删除 + """ + primary_host = cluster.tendbcluster_ctl_primary_address().split(":")[0] + res = DRSApi.rpc( + { + "addresses": [f"{spider_ip}{IP_PORT_DIVIDER}{spider_port}"], + "cmds": [f"DROP USER if exists '{TDBCTL_USER}'@'{primary_host}'"], + "force": False, + "bk_cloud_id": cluster.bk_cloud_id, + } + ) + if res[0]["error_msg"]: + self.log_error(f"drop user failed:[{res[0]['error_msg']}]") + return False + return True + + def _read_ctl_pass(self, ctl_master, bk_cloud_id): + """ + 获取第一次集群部署中控的密码,保证统一集群的所有中控访问的账号秘密是一致的,避免中控同步出现复制冲突 + """ + res = DRSApi.rpc( + { + "addresses": [f"{ctl_master}"], + "cmds": [f"select Password as result from mysql.servers where Server_name like 'TDBCTL%' limit 1"], + "force": False, + "bk_cloud_id": bk_cloud_id, + } + ) + if res[0]["error_msg"]: + self.log_error(f"drop user failed:[{res[0]['error_msg']}]") + return "" + + return res[0]["cmd_results"][0]["table_data"][0]["result"] + + def _reset_master(self, spider_ip: str, spider_port: int, bk_cloud_id): + """ + 定义reset master 方法,tdbctl添加时专属 + """ + res = DRSApi.rpc( + { + "addresses": [f"{spider_ip}{IP_PORT_DIVIDER}{spider_port}"], + "cmds": [f"reset master"], + "force": False, + "bk_cloud_id": bk_cloud_id, + } + ) + if res[0]["error_msg"]: + self.log_error(f"reset master failed:[{res[0]['error_msg']}]") + return False + return True + def _check_node_is_add(self, spider_ip: str, spider_port: int, cluster: Cluster): """ 定义一个内置的检测方式,添加之前检测节点是否已存在添加 @@ -81,20 +134,26 @@ def _exec_create_node(self, cluster: Cluster, user: str, passwd: str, spider_ip: if not self._check_node_is_add(cluster=cluster, spider_ip=spider_ip, spider_port=spider_port): # 代表这个节点在集群的路由表已经存在,则这里选择跳过 # todo 这里出现重复只能选择跳过,如果选择重做还没有想好逻辑,而且重做会有风险。 - return None + return True + + if tag == "TDBCTL": + # 如果create node 是一个tdbctl,则由于gtid的原因需要先reset master,保证新实例GTID_EXECUTED为空,再create node + if not self._reset_master(spider_ip=spider_ip, spider_port=spider_port, bk_cloud_id=cluster.bk_cloud_id): + return False sql = ( - "tdbctl create node wrapper '{}' options(user '{}'," " password '{}', host '{}', port {}) with database" + "tdbctl create node wrapper '{}' options(user '{}', password '{}', host '{}', port {}) with database" ).format(tag, user, passwd, spider_ip, spider_port) - rpc_params["cmds"] = cmds + [sql] + rpc_params["cmds"] = cmds + [sql] + ["TDBCTL FLUSH ROUTING"] res = DRSApi.rpc(rpc_params) if res[0]["error_msg"]: - raise AddSpiderNodeFailedException(message=_("TdbCtl-create-node failed: {}".format(res[0]["error_msg"]))) + self.log_error("TdbCtl-create-node failed: {}".format(res[0]["error_msg"])) + return False self.log_info("TdbCtl-create-node added successfully [{}:{}]".format(spider_ip, spider_port)) - return None + return True def _add_system_user( self, @@ -103,6 +162,7 @@ def _add_system_user( created_by: str, user: str, passwd: str, + ctl_pass: str, clt_master_ip: str, add_spider_role: str, ): @@ -113,7 +173,9 @@ def _add_system_user( @param created_by: 发起单据的用户名称 @param user: 内置账号名称, @param passwd: 内置账号密码, + @param ctl_pass: 中控的内置账号密码 @param clt_master_ip: 当前集群的中控实例的ip + @param add_spider_role: 添加的spider角色 """ # 获取云区域id的方式,已集群信息为准 spider_port = cluster.proxyinstance_set.first().port @@ -123,6 +185,9 @@ def _add_system_user( encrypted = RSAHandler.encrypt_password(MySQLPrivManagerApi.fetch_public_key(), passwd, salt=None) for spider_ip in add_spiders: + if not self._drop_user(spider_ip=spider_ip["ip"], spider_port=spider_port, cluster=cluster): + return False + content = { "bk_cloud_id": cluster.bk_cloud_id, "bk_biz_id": cluster.bk_biz_id, @@ -144,6 +209,10 @@ def _add_system_user( if add_spider_role == TenDBClusterSpiderRole.SPIDER_MASTER.value: # 部署spider-master实例,必定启动中控实例,这里增加对中控实例的内置授权 content["address"] = f'{spider_ip["ip"]}{IP_PORT_DIVIDER}{admin_port}' + content["role"] = PrivRole.TDBCTL.value + content["psw"] = RSAHandler.encrypt_password( + MySQLPrivManagerApi.fetch_public_key(), ctl_pass, salt=None + ) MySQLPrivManagerApi.add_priv_without_account_rule(content) self.log_info(_("在[{}]创建添加内置账号成功").format(content["address"])) @@ -151,6 +220,8 @@ def _add_system_user( self.log_error(_("[{}]添加用户接口异常,相关信息: {}").format(content["address"], e)) return False + return True + def _execute(self, data, parent_data): kwargs = data.get_one_of_inputs("kwargs") global_data = data.get_one_of_inputs("global_data") @@ -160,17 +231,27 @@ def _execute(self, data, parent_data): ctl_master = cluster.tendbcluster_ctl_primary_address() spider_port = cluster.proxyinstance_set.first().port admin_port = cluster.proxyinstance_set.first().admin_port + ctl_pass = "" + + if kwargs["add_spider_role"] == TenDBClusterSpiderRole.SPIDER_MASTER.value: + # 如果添加的是spider_master,则必须添加中控实例,添加中控实例之前,获取中控实例的密码 + ctl_pass = self._read_ctl_pass(ctl_master=ctl_master, bk_cloud_id=cluster.bk_cloud_id) + if not ctl_pass: + return False # 先对待加入的spider节点添加内置账号,接口幂等 - self._add_system_user( + + if not self._add_system_user( cluster=cluster, add_spiders=kwargs["add_spiders"], created_by=global_data["created_by"], user=kwargs["user"], passwd=kwargs["passwd"], + ctl_pass=ctl_pass, clt_master_ip=ctl_master.split(":")[0], add_spider_role=kwargs["add_spider_role"], - ) + ): + return False # 循环添加路由信息,添加之前判断是否已经存在 for add_spider in kwargs["add_spiders"]: @@ -186,26 +267,28 @@ def _execute(self, data, parent_data): raise NormalSpiderFlowException(message=_("This spider-role is not supported,check")) # 执行添加node的方法,方法幂等 - self._exec_create_node( + if not self._exec_create_node( cluster=cluster, user=kwargs["user"], passwd=kwargs["passwd"], spider_ip=add_spider["ip"], spider_port=spider_port, tag=tag, - ) + ): + return False if kwargs["add_spider_role"] == TenDBClusterSpiderRole.SPIDER_MASTER.value: # 对中控实例也执行添加node行为 tag = "TDBCTL" - self._exec_create_node( + if not self._exec_create_node( cluster=cluster, user=kwargs["user"], - passwd=kwargs["passwd"], + passwd=ctl_pass, spider_ip=add_spider["ip"], spider_port=admin_port, tag=tag, - ) + ): + return False return True diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py index e186e3afd0..4dd76340b0 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/ctl_drop_routing.py @@ -59,6 +59,7 @@ def _execute(self, data, parent_data): exec_sql = [ "set tc_admin=1", f"TDBCTL DROP NODE IF EXISTS {server_name}", + "TDBCTL FLUSH ROUTING", ] rpc_params["cmds"] = exec_sql res = DRSApi.rpc(rpc_params) diff --git a/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py b/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py index de5992efb5..485a3a0f92 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py +++ b/dbm-ui/backend/flow/plugins/components/collections/spider/drop_spider_ronting.py @@ -23,13 +23,19 @@ def _pre_check(self, cluster: Cluster, reduce_spider: ProxyInstance): 检测待下架的spider节点是否有存在访问 """ - res = check_client_connection(cluster.bk_cloud_id, reduce_spider.ip_port) + res = check_client_connection(bk_cloud_id=cluster.bk_cloud_id, instances=[reduce_spider.ip_port]) if res[0]["error_msg"]: raise DropSpiderNodeFailedException(message=_("select processlist failed: {}".format(res[0]["error_msg"]))) if res[0]["cmd_results"][0]["table_data"]: - self.log_error(f"There are also {res[0]['cmd_results'][1]['rows_affected']} non-sleep state threads") + self.log_error(f"There are also {len(res[0]['cmd_results'][0]['table_data'])} non-sleep state threads") + process_list = res[0]["cmd_results"][0]["table_data"] + for p in process_list: + # 打印连接 + self.log_error( + f"proc_id: {p['ID']}, command:{p['COMMAND']}, host:{p['HOST']}, info:{p['INFO']}, time:{p['TIME']}" + ) return False return True @@ -71,6 +77,7 @@ def _exec_drop_routing(self, cluster: Cluster, spider: ProxyInstance): exec_sql = [ "set tc_admin=1", f"TDBCTL DROP NODE IF EXISTS {server_name}", + "TDBCTL FLUSH ROUTING", ] rpc_params["cmds"] = exec_sql res = DRSApi.rpc(rpc_params) @@ -99,7 +106,7 @@ def _execute(self, data, parent_data): # 执行删除路由 self.log_info(f"exec drop node [{s.ip_port}]") self._exec_drop_routing(cluster, s) - return True + return True class DropSpiderRoutingComponent(Component): diff --git a/dbm-ui/backend/flow/utils/mysql/check_client_connections.py b/dbm-ui/backend/flow/utils/mysql/check_client_connections.py index 80bfa85b59..7acc3cb0ee 100644 --- a/dbm-ui/backend/flow/utils/mysql/check_client_connections.py +++ b/dbm-ui/backend/flow/utils/mysql/check_client_connections.py @@ -36,6 +36,9 @@ def check_client_connection(bk_cloud_id: int, instances: list, is_filter_sleep: } )["content"] admin_user_name_list = [data["admin_user"], data["backup_user"], data["monitor_user"], data["repl_user"]] + + # 对于tendb-cluster集群的实例,这里不考虑过滤内置账号的session,因为执行ddl时候,实例会存在内置账号session + # 过滤会有风险 users = ",".join( ["'" + str(x) + "'" for x in MYSQL_SYS_USER + admin_user_name_list + get_mysql_sys_users(bk_cloud_id)] ) diff --git a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py index 9cfcd5128c..fb5fbada63 100644 --- a/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py +++ b/dbm-ui/backend/flow/utils/mysql/mysql_act_playload.py @@ -26,7 +26,7 @@ from backend.core.consts import BK_PKG_INSTALL_PATH from backend.core.encrypt.constants import RSAConfigType from backend.core.encrypt.handlers import RSAHandler -from backend.db_meta.enums import InstanceInnerRole, MachineType +from backend.db_meta.enums import InstanceInnerRole, MachineType, TenDBClusterSpiderRole from backend.db_meta.exceptions import DBMetaException from backend.db_meta.models import Cluster, Machine, ProxyInstance, StorageInstance, StorageInstanceTuple from backend.db_package.models import Package @@ -660,6 +660,7 @@ def get_uninstall_spider_ctl_payload(self, **kwargs) -> dict: def get_install_db_backup_payload(self, **kwargs) -> dict: """ 安装备份程序,目前是必须是先录入元信息后,才执行备份程序的安装 + 非spider-master角色实例不安装备份程序,已在外层屏蔽 """ db_backup_pkg = Package.get_latest_package(version=MediumEnum.Latest, pkg_type=MediumEnum.DbBackup) cfg = self.__get_dbbackup_config() @@ -684,7 +685,7 @@ def get_install_db_backup_payload(self, **kwargs) -> dict: cluster_id_map[instance.port] = cluster.id # 如果是spider-master类型机器,中控实例也需要安装备份程序 - if machine.machine_type == MachineType.SPIDER.value: + if role == TenDBClusterSpiderRole.SPIDER_MASTER.value: mysql_ports.append(instance.admin_port) port_domain_map[instance.admin_port] = cluster.immute_domain cluster_id_map[instance.admin_port] = cluster.id @@ -1659,7 +1660,7 @@ def get_grant_repl_for_ctl_payload(self, **kwargs) -> dict: "extend": { "host": kwargs["ip"], "port": self.cluster["mysql_port"], - "repl_hosts": kwargs["trans_data"].get("slaves", self.cluster["slaves"]), + "repl_hosts": self.cluster["slaves"], }, }, } @@ -1676,7 +1677,7 @@ def get_change_master_for_gitd_payload(self, **kwargs) -> dict: "extend": { "host": kwargs["ip"], "port": self.cluster["mysql_port"], - "master_host": kwargs["trans_data"].get("master_ip", self.cluster["master_ip"]), + "master_host": self.cluster["master_ip"], "master_port": self.cluster["mysql_port"], "is_gtid": True, "max_tolerate_delay": 0, diff --git a/dbm-ui/backend/flow/utils/spider/get_spider_incr.py b/dbm-ui/backend/flow/utils/spider/get_spider_incr.py index ddc8ab8e5d..1ab7ddba49 100644 --- a/dbm-ui/backend/flow/utils/spider/get_spider_incr.py +++ b/dbm-ui/backend/flow/utils/spider/get_spider_incr.py @@ -38,8 +38,6 @@ def get_spider_master_incr(cluster: Cluster, add_spiders: list) -> list: } ) - print(res) - if res[0]["error_msg"]: raise FailedToAssignIncrException( message=_("select spider_auto_increment failed: {}".format(res[0]["error_msg"])) diff --git a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py index e57d02dfe3..6655688395 100644 --- a/dbm-ui/backend/flow/utils/spider/spider_db_meta.py +++ b/dbm-ui/backend/flow/utils/spider/spider_db_meta.py @@ -8,12 +8,13 @@ specific language governing permissions and limitations under the License. """ import logging +from typing import Optional from django.db import transaction from backend.db_meta.api.cluster.tendbcluster.handler import TenDBClusterClusterHandler from backend.db_meta.api.cluster.tendbcluster.remotedb_node_migrate import TenDBClusterMigrateRemoteDb -from backend.db_meta.enums import ClusterEntryRole +from backend.db_meta.enums import ClusterEntryRole, TenDBClusterSpiderRole from backend.db_meta.models import Cluster from backend.flow.utils.dict_to_dataclass import dict_to_dataclass from backend.flow.utils.spider.spider_act_dataclass import ShardInfo @@ -85,36 +86,47 @@ def tendb_cluster_slave_apply(self): "cluster_id": self.global_data["cluster_id"], "creator": self.global_data["created_by"], "spider_version": self.global_data["spider_version"], - "slave_domain": self.global_data["slave_domain"], - "spider_slaves": self.global_data["spider_slave_ip_list"], - "is_create": True, + "domain": self.global_data["slave_domain"], + "add_spiders": self.global_data["spider_slave_ip_list"], + "spider_role": TenDBClusterSpiderRole.SPIDER_SLAVE, + "resource_spec": self.global_data["resource_spec"], + "is_slave_cluster_create": True, } - TenDBClusterClusterHandler.add_spider_slaves(**kwargs) + TenDBClusterClusterHandler.add_spiders(**kwargs) return True - def add_spider_slave_nodes_apply(self): + def add_spider_nodes(self, spider_role: Optional[TenDBClusterSpiderRole], domain: str = None): """ - 对已有的TenDB cluster集群 (spider集群)扩容spider-slave节点 + 对已有的TenDB cluster集群 (spider集群)扩容写入的公共方法 """ - cluster = Cluster.objects.get(id=self.global_data["cluster_id"]) - slave_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.SLAVE_ENTRY).entry kwargs = { "cluster_id": self.global_data["cluster_id"], "creator": self.global_data["created_by"], "spider_version": self.global_data["spider_version"], - "slave_domain": slave_dns, - "spider_slaves": self.global_data["spider_ip_list"], - "is_create": False, + "domain": domain, + "add_spiders": self.global_data["spider_ip_list"], + "spider_role": spider_role, + "resource_spec": self.global_data["resource_spec"], + "is_slave_cluster_create": False, } - TenDBClusterClusterHandler.add_spider_slaves(**kwargs) + TenDBClusterClusterHandler.add_spiders(**kwargs) return True + def add_spider_slave_nodes_apply(self): + """ + 对已有的TenDB cluster集群 (spider集群)扩容spider-slave节点 + """ + cluster = Cluster.objects.get(id=self.global_data["cluster_id"]) + slave_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.SLAVE_ENTRY).entry + self.add_spider_nodes(spider_role=TenDBClusterSpiderRole.SPIDER_SLAVE, domain=slave_dns) + def add_spider_master_nodes_apply(self): """ 对已有的TenDB cluster集群 (spider集群)扩容spider-master节点 - todo 后续tdbctl新版本出现在补齐 """ - return True + cluster = Cluster.objects.get(id=self.global_data["cluster_id"]) + master_dns = cluster.clusterentry_set.get(role=ClusterEntryRole.MASTER_ENTRY).entry + self.add_spider_nodes(spider_role=TenDBClusterSpiderRole.SPIDER_MASTER, domain=master_dns) def reduce_spider_nodes_apply(self): """ @@ -128,16 +140,9 @@ def reduce_spider_nodes_apply(self): def add_spider_mnt(self): """ - 已有集群添加运维节点 + 对已有的TenDB cluster集群 (spider集群)扩容spider-mnt节点 """ - kwargs = { - "cluster_id": self.global_data["cluster_id"], - "creator": self.global_data["created_by"], - "spider_version": self.global_data["spider_version"], - "spider_mnts": self.global_data["spider_ip_list"], - } - TenDBClusterClusterHandler.spider_mnt_create(**kwargs) - return True + self.add_spider_nodes(spider_role=TenDBClusterSpiderRole.SPIDER_MNT, domain=None) def remote_switch(self): """ From c52fc819a5d811443c72e28e0c485d4a204d9083 Mon Sep 17 00:00:00 2001 From: daryl Date: Thu, 13 Jul 2023 17:29:33 +0800 Subject: [PATCH 142/476] =?UTF-8?q?feat(frontend):=20=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=B1=A0=E8=A7=84=E6=A0=BC=20&=20=E9=83=A8=E7=BD=B2=E5=8D=95?= =?UTF-8?q?=E6=8D=AE=E6=94=B9=E9=80=A0=20#113?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply-items/PlanSelector.vue | 186 ---------- .../apply-items/RedisBackendSpec.vue | 329 ++++++++++++++++++ dbm-ui/frontend/src/locales/en.json | 114 ++++++ dbm-ui/frontend/src/locales/zh-cn.json | 13 +- .../model/resource-spec/resourceSpec.ts | 7 + dbm-ui/frontend/src/services/resourceSpec.ts | 52 +++ dbm-ui/frontend/src/styles/applyInstance.less | 12 +- .../src/views/es-manage/apply/Index.vue | 16 +- .../src/views/hdfs-manage/apply/Index.vue | 16 +- .../src/views/influxdb-manage/apply/index.vue | 16 +- .../src/views/kafka-manage/apply/Index.vue | 16 +- .../src/views/mysql/apply/ApplyMySQL.vue | 8 +- .../src/views/pulsar-manage/apply/index.vue | 16 +- .../src/views/redis/apply/ApplyRedis.vue | 47 ++- .../src/views/redis/apply/common/const.ts | 2 - .../resource-spec/components/SpecCreate.vue | 25 ++ .../components/spec-form-item/SpecQPS.vue | 102 ++++++ .../tickets/components/redis/DetailsRedis.vue | 69 +++- 18 files changed, 777 insertions(+), 269 deletions(-) delete mode 100644 dbm-ui/frontend/src/components/apply-items/PlanSelector.vue create mode 100644 dbm-ui/frontend/src/components/apply-items/RedisBackendSpec.vue create mode 100644 dbm-ui/frontend/src/views/resource-spec/components/spec-form-item/SpecQPS.vue diff --git a/dbm-ui/frontend/src/components/apply-items/PlanSelector.vue b/dbm-ui/frontend/src/components/apply-items/PlanSelector.vue deleted file mode 100644 index d809e0f1ec..0000000000 --- a/dbm-ui/frontend/src/components/apply-items/PlanSelector.vue +++ /dev/null @@ -1,186 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/components/apply-items/RedisBackendSpec.vue b/dbm-ui/frontend/src/components/apply-items/RedisBackendSpec.vue new file mode 100644 index 0000000000..fab770877e --- /dev/null +++ b/dbm-ui/frontend/src/components/apply-items/RedisBackendSpec.vue @@ -0,0 +1,329 @@ + + + + + diff --git a/dbm-ui/frontend/src/locales/en.json b/dbm-ui/frontend/src/locales/en.json index 94d27d909a..8809f5aa06 100644 --- a/dbm-ui/frontend/src/locales/en.json +++ b/dbm-ui/frontend/src/locales/en.json @@ -1467,5 +1467,119 @@ "确定禁用北极星": "Make sure to disable Polaris", "确定启用北极星": "Make sure to enable Polaris", "禁用北极星": "Disable Polaris", + "((n))台": "({n}) stations", + "(n)台": "{n} units", + "QPS预估范围": "QPS estimated range", + "Redis_工具箱": "redis_toolbox", + "name容量从nG扩容至nG": "{name} capacity expanded from {totalDisk} G to {expansionDisk} G", + "name容量从nG缩容至nG": "{name} shrinks from {totalDisk} G to {expansionDisk} G", + "n核": "{n} core", + "不能大于最大台数": "Cannot be greater than the maximum number", + "业务空闲机": "business idle machine", + "主库故障主机": "Main database failure host", + "主库故障切换:主机级别操作,即同机所有集群的从库均会升级成主库": "Master library failover: host-level operation, that is, the slave libraries of all clusters on the same machine will be upgraded to the main library", + "主故障切换": "primary failover", + "主机已被导入": "The host has been imported", + "从库将会直接替换主库所有信息,请谨慎操作!": "The slave library will directly replace all the information of the master library, please be careful!", + "切换模式": "switch mode", + "单据ID:": "Document ID:", + "单机QPS": "Standalone QPS", + "台数只能为正整数": "The number of units can only be a positive integer", + "后端存储规格": "Backend Storage Specifications", + "复制全部 IP": "Copy all IPs", + "复制异常 IP": "Copy abnormal IP", + "定点构造": "fixed-point construction", + "定点构造任务提交成功": "Fixed-point construction task submitted successfully", + "定点构造:XXX": "Fixed-point construction: XXX", + "导入设置": "import settings", + "已选:n台主机": "Selected: {0} hosts", + "已选n台": "Selected {0} stations", + "已选n条,": "{0} items selected,", + "异常主机不可用": "exception host unavailable", + "当前已经有n个导入任务正在进行中,": "There are currently {0} import tasks in progress,", + "当前方案": "current plan", + "当前规格": "current specification", + "当前资源规格": "current resource specification", + "待构造的实例": "instance to be constructed", + "待构造的集群": "cluster to be constructed", + "待确认": "to be confirmed", + "扩容后预估容量": "Estimated capacity after expansion", + "扩容存储层提交成功": "The storage layer expansion is submitted successfully", + "扩容接入层": "Access Layer Expansion", + "扩容接入层提交成功": "The expansion of the access layer is submitted successfully", + "扩容方案": "Expansion plan", + "扩容至(台)": "Expand to (unit)", + "扩容节点类型": "Expansion node type", + "批量回写": "batch write back", + "批量添加": "batch add", + "批量销毁": "Batch destruction", + "指定Redis版本": "Specify Redis version", + "数据为空": "data is empty", + "数据构造": "data structure", + "整机替换": "Complete machine replacement", + "无匹配的资源规格_请先修改容量及QPS设置": "There is no matching resource specification, please modify the capacity and QPS settings first", + "无需确认": "No need to confirm", + "替换后所有的数据将会迁移到新的主机上,请谨慎操作!": "All data will be migrated to the new host after the replacement, please be careful!", + "期望容量": "expected capacity", + "未来集群容量需求": "Future Cluster Capacity Requirements", + "构造主机数量": "Number of construction hosts", + "构造产物访问入口": "Construct product access entry", + "构造到指定时间": "Build to specified time", + "构造实例": "Construction instance", + "构造实例范围": "Construct instance scope", + "构造的主机数量": "The number of hosts constructed", + "构造的集群": "constructed cluster", + "每秒": "per second", + "消费主机": "consumer host", + "清除所有勾选": "clear all checks", + "目标台数不能为空": "Target number cannot be empty", + "确认定点构造 n 个集群?": "Confirm fixed-point construction of {n} clusters?", + "确认扩容存储层n个集群?": "Are you sure to expand the storage layer to {n} clusters?", + "确认扩容接入层n个集群?": "Are you sure to expand the access layer to {n} clusters?", + "确认接入层缩容n个集群?": "Confirm that the access layer shrinks {n} clusters?", + "确认提交 n 个主库故障切换任务?": "Are you sure to submit {n} master failover tasks?", + "确认整机替换n台主机?": "Confirm that the whole machine replaces {n} hosts?", + "确认缩容存储层n个集群?": "Are you sure to shrink {n} clusters at the storage layer?", + "禁止选择": "no choice", + "立即查看": "view now", + "缩容存储层提交成功": "The shrink storage layer is submitted successfully", + "缩容接入层": "Shrink the access layer", + "缩容接入层提交成功": "The shrink access layer is submitted successfully", + "缩容接入层:XXX": "Shrinkage access layer: XXX", + "缩容至(台)": "Shrink to (unit)", + "缩容节点类型": "Scale-in node type", + "规格需求": "Specification requirements", + "请先设置容量及QPS范围": "Please set capacity and QPS range first", + "请先输入集群": "Please enter the group first", + "请谨慎操作!": "Please operate with caution!", + "请输入字段名搜索": "Please enter a field name to search", + "请输入或选择集群": "Please enter or select a cluster", + "请选择Redis版本": "Please select Redis version", + "请选择切换模式": "Please select switching mode", + "请选择匹配规格": "Please select a matching specification", + "请选择扩容方案": "Please choose an expansion plan", + "请选择操作时间": "Please select an operating time", + "资源规格": "resource specification", + "输入主机后自动生成": "Automatically generated after entering the host", + "输入集群后自动生成": "Automatically generated after entering the cluster", + "选择扩容方案后自动生成": "Automatically generated after selecting the expansion plan", + "选择集群后自动生成": "Automatically generated after selecting a cluster", + "选择集群目标方案": "Select a cluster target scheme", + "部署机器组数": "Number of deployed machine groups", + "集群QPS(每秒)": "Cluster QPS (per second)", + "集群QPS每秒": "Cluster QPS (per second)", + "集群上的数据将会全部构造至指定的新机器共 n GB,预计时长 m 分钟": "All the data on the cluster will be constructed to the specified new machine with a total of {n} GB, and the estimated time is {m} minutes", + "集群关联的其他任务": "Other tasks associated with the cluster", + "集群分片": "cluster sharding", + "集群容量(G)": "Cluster capacity (G)", + "集群容量G": "Cluster capacity (G)", + "集群容量变更": "Cluster capacity change", + "集群容量变更:XXX": "Cluster capacity change: XXX", + "集群容量需求": "Cluster Capacity Requirements", + "集群选择": "cluster selection", + "集群部署方案": "Cluster deployment scheme", + "需人工确认": "Manual confirmation is required", + "需机器组数": "Required number of machine groups", + "默认使用部署时选定的规格,将从资源池自动匹配机器": "By default, the specification selected during deployment will be used, and the machine will be automatically matched from the resource pool", "这行勿动!新增翻译请在上一行添加!": "" } diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 929e278857..433cbca82a 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1559,5 +1559,16 @@ "替换后所有的数据将会迁移到新的主机上,请谨慎操作!": "替换后所有的数据将会迁移到新的主机上,请谨慎操作!", "定点构造:XXX": "定点构造:XXX", "集群容量变更:XXX": "集群容量变更:XXX", + "后端存储规格": "后端存储规格", + "集群容量需求": "集群容量需求", + "未来集群容量需求": "未来集群容量需求", + "QPS预估范围": "QPS预估范围", + "集群部署方案": "集群部署方案", + "单机QPS": "单机QPS", + "每秒": "每秒", + "请先设置容量及QPS范围": "请先设置容量及 QPS 范围", + "无匹配的资源规格_请先修改容量及QPS设置": "无匹配的资源规格,请先修改容量及 QPS 设置", + "集群容量G": "集群容量(G)", + "集群QPS每秒": "集群QPS(每秒)", "这行勿动!新增翻译请在上一行添加!": "" -} \ No newline at end of file +} diff --git a/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts b/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts index 0dd272b283..d3737ca5a7 100644 --- a/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts +++ b/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts @@ -39,6 +39,10 @@ export default class ResourceSpec { updater: string; spec_id: number; instance_num?: number; + qps?: { + min: number, + max: number + }; constructor(payload = {} as ResourceSpec) { this.cpu = payload.cpu; @@ -55,5 +59,8 @@ export default class ResourceSpec { this.updater = payload.updater; this.spec_id = payload.spec_id; this.instance_num = payload.instance_num ?? 0; + if (payload.qps) { + this.qps = payload.qps; + } } } diff --git a/dbm-ui/frontend/src/services/resourceSpec.ts b/dbm-ui/frontend/src/services/resourceSpec.ts index 3d7840a296..a1ddb3cad5 100644 --- a/dbm-ui/frontend/src/services/resourceSpec.ts +++ b/dbm-ui/frontend/src/services/resourceSpec.ts @@ -15,6 +15,38 @@ import http from './http'; import ResourceSpecModel from './model/resource-spec/resourceSpec'; import type { ListBase } from './types/common'; +export interface FilterClusterSpecItem { + creator: string, + updater: string, + spec_id: number, + spec_name: string, + spec_cluster_type: string, + spec_machine_type: string, + cpu: { + max: number, + min: number + }, + mem: { + max: number, + min: number + }, + device_class: string[], + storage_spec: { + size: number, + type: string, + mount_point: string + }[], + desc: string, + instance_num: number, + qps: { + max: number, + min: number + }, + capacity: number, + machine_pair: number, + cluster_capacity: number, + cluster_shard_num: number +} // 获取资源规格列表 export const getResourceSpecList = function (params: Record & { @@ -47,3 +79,23 @@ export const batchDeleteResourceSpec = function (params: Record & { export const deleteResourceSpec = function (specId: number) { return http.delete(`/apis/dbresource/spec/${specId}/`); }; + +// 获取 qps 的范围 +export const queryQPSRange = (params: { + spec_cluster_type: string, + spec_machine_type: string, + capacity: number, + future_capacity: number, +}) => http.get<{max: number, min: number}>('/apis/dbresource/spec/query_qps_range/', params); + +// 筛选集群部署规格方案 +export const getFilterClusterSpec = (params: { + spec_cluster_type: string, + spec_machine_type: string, + capacity: number, + future_capacity: number, + qps: { + min: number, + max: number + } +}) => http.post('/apis/dbresource/spec/filter_cluster_spec/', params); diff --git a/dbm-ui/frontend/src/styles/applyInstance.less b/dbm-ui/frontend/src/styles/applyInstance.less index b64adcee28..a8a25aaa1b 100644 --- a/dbm-ui/frontend/src/styles/applyInstance.less +++ b/dbm-ui/frontend/src/styles/applyInstance.less @@ -45,8 +45,16 @@ width: 220px; } - :deep(.bk-radio-button-label) { - width: 100%; + :deep(.bk-radio-group) { + width: 435px; + + .bk-radio-button { + flex: auto; + } + + .bk-radio-button-label { + width: 100%; + } } } diff --git a/dbm-ui/frontend/src/views/es-manage/apply/Index.vue b/dbm-ui/frontend/src/views/es-manage/apply/Index.vue index a1090e11e8..f11c1f3996 100644 --- a/dbm-ui/frontend/src/views/es-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/es-manage/apply/Index.vue @@ -58,14 +58,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} @@ -747,6 +743,14 @@ } } + .bk-radio-group { + width: 435px; + + .bk-radio-button { + flex: auto; + } + } + .item-input { width: 435px; } diff --git a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue index 9fae40a219..ff95dbd6c8 100644 --- a/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/hdfs-manage/apply/Index.vue @@ -59,14 +59,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} @@ -624,6 +620,14 @@ } } + .bk-radio-group { + width: 435px; + + .bk-radio-button { + flex: auto; + } + } + .item-input { width: 435px; } diff --git a/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue b/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue index d09dcdab9e..45fb240fa9 100644 --- a/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue +++ b/dbm-ui/frontend/src/views/influxdb-manage/apply/index.vue @@ -57,14 +57,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} @@ -340,6 +336,14 @@ } } + :deep(.bk-radio-group) { + width: 435px; + + .bk-radio-button { + flex: auto; + } + } + :deep(.item-input) { width: 435px; } diff --git a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue index 28232b847c..b2232787a1 100644 --- a/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue +++ b/dbm-ui/frontend/src/views/kafka-manage/apply/Index.vue @@ -58,14 +58,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} @@ -563,6 +559,14 @@ } } + .bk-radio-group { + width: 435px; + + .bk-radio-button { + flex: auto; + } + } + .item-input { width: 435px; } diff --git a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue index 41c5245878..a888424cb7 100644 --- a/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue +++ b/dbm-ui/frontend/src/views/mysql/apply/ApplyMySQL.vue @@ -205,14 +205,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} diff --git a/dbm-ui/frontend/src/views/pulsar-manage/apply/index.vue b/dbm-ui/frontend/src/views/pulsar-manage/apply/index.vue index 5900c697ff..bfc473a212 100644 --- a/dbm-ui/frontend/src/views/pulsar-manage/apply/index.vue +++ b/dbm-ui/frontend/src/views/pulsar-manage/apply/index.vue @@ -55,14 +55,10 @@ required> - + {{ $t('自动从资源池匹配') }} - + {{ $t('手动录入IP') }} @@ -630,6 +626,14 @@ } } + :deep(.bk-radio-group) { + width: 435px; + + .bk-radio-button { + flex: auto; + } + } + :deep(.item-input) { width: 435px; } diff --git a/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue b/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue index 86b9129df3..759e6a5d17 100644 --- a/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue +++ b/dbm-ui/frontend/src/views/redis/apply/ApplyRedis.vue @@ -88,11 +88,6 @@ {{ item.text }} @@ -264,11 +259,11 @@ - @@ -326,7 +321,7 @@ import CloudItem from '@components/apply-items/CloudItem.vue'; import ClusterAlias from '@components/apply-items/ClusterAlias.vue'; import ClusterName from '@components/apply-items/ClusterName.vue'; - import PlanSelector from '@components/apply-items/PlanSelector.vue'; + import RedisBackendSpec from '@components/apply-items/RedisBackendSpec.vue'; import SpecSelector from '@components/apply-items/SpecSelector.vue'; import IpSelector from '@components/ip-selector/IpSelector.vue'; @@ -353,6 +348,7 @@ const masterRef = ref(); const slaveRef = ref(); const specProxyRef = ref(); + const specBackendRef = ref(); const capSpecsKey = ref(generateId('CLUSTER_APPLAY_CAP_')); const renderRedisClusterTypes = computed(() => { const values = Object.values(redisClusterTypes); @@ -450,7 +446,7 @@ city_code: '', db_version: '', cap_key: '', - ip_source: redisIpSources.manual_input.id, + ip_source: redisIpSources.resource_pool.id, nodes: { proxy: [] as HostDetails[], master: [] as HostDetails[], @@ -461,10 +457,13 @@ spec_id: '', count: 2, }, - }, - resource_plan: { - resource_plan_name: '', - resource_plan_id: '', + backend_group: { + count: 0, + spec_name: '', + spec_id: '', + capacity: '' as number | string, + future_capacity: '' as number | string, + }, }, }, }; @@ -686,7 +685,11 @@ if (state.formdata.details.ip_source === 'resource_pool') { delete details.nodes; + // 集群容量需求不需要提交 + delete details.resource_spec.backend_group.capacity; + delete details.resource_spec.backend_group.future_capacity; + const specInfo = specBackendRef.value.getData(); return { ...details, resource_spec: { @@ -697,12 +700,16 @@ spec_cluster_type: typeInfos.value.cluster_type, spec_machine_type: typeInfos.value.machine_type, }, + backend_group: { + ...details.resource_spec.backend_group, + count: specInfo.machine_pair, + spec_info: specInfo, + }, }, }; } delete details.resource_spec; - delete details.resource_plan; return { ...details, nodes: { @@ -725,14 +732,6 @@ @import "@styles/applyInstance.less"; .apply-instance { - .bk-radio-group { - display: inline-flex; - - :deep(.bk-radio-button) { - flex: 1; - } - } - :deep(.item-input) { width: 462px; } diff --git a/dbm-ui/frontend/src/views/redis/apply/common/const.ts b/dbm-ui/frontend/src/views/redis/apply/common/const.ts index 9a2a5e88d6..41471a32bb 100644 --- a/dbm-ui/frontend/src/views/redis/apply/common/const.ts +++ b/dbm-ui/frontend/src/views/redis/apply/common/const.ts @@ -24,12 +24,10 @@ export const redisIpSources = { resource_pool: { id: 'resource_pool', text: t('自动从资源池匹配'), - disabled: true, }, manual_input: { id: 'manual_input', text: t('手动录入IP'), - disabled: false, }, }; export type RedisIpSources = keyof typeof redisIpSources; diff --git a/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue b/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue index 693fb7217b..0d87d2cb89 100644 --- a/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue +++ b/dbm-ui/frontend/src/views/resource-spec/components/SpecCreate.vue @@ -59,6 +59,10 @@ :min="1" type="number" /> + !notRequiredStorageList.includes(`${props.clusterType}_${props.machineType}`)); + const hasQPSSpecs = [ + `${ClusterTypes.TWEMPROXY_REDIS_INSTANCE}_tendiscache`, + `${ClusterTypes.TWEMPROXY_TENDIS_SSD_INSTANCE}_tendisssd`, + `${ClusterTypes.PREDIXY_TENDISPLUS_CLUSTER}_tendisplus`, + ]; + const hasQPS = computed(() => hasQPSSpecs.includes(`${props.clusterType}_${props.machineType}`)); useStickyFooter(formWrapperRef, formFooterRef); @@ -192,6 +207,7 @@ device_class: formdata.value.device_class.filter(item => item), storage_spec: formdata.value.storage_spec.filter(item => item.mount_point && item.size && item.type), }; + if (props.isEdit) { updateResourceSpec((formdata.value as ResourceSpecModel).spec_id, params) .then(() => { @@ -209,6 +225,15 @@ delete params.instance_num; } + if (hasQPS.value) { + params.qps = { + max: Number(params.qps?.max), + min: Number(params.qps?.min), + }; + } else { + delete params.qps; + } + createResourceSpec(params) .then(() => { messageSuccess(t('新建成功')); diff --git a/dbm-ui/frontend/src/views/resource-spec/components/spec-form-item/SpecQPS.vue b/dbm-ui/frontend/src/views/resource-spec/components/spec-form-item/SpecQPS.vue new file mode 100644 index 0000000000..6c2d4ff158 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-spec/components/spec-form-item/SpecQPS.vue @@ -0,0 +1,102 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue b/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue index 62e3845e16..586c78cc21 100644 --- a/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue +++ b/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue @@ -48,6 +48,10 @@ {{ $t('服务器') }}: {{ getIpSource() }} +
+ {{ $t('备注') }}: + {{ ticketDetails?.remark || '--' }} +
-
- {{ $t('备注') }}: - {{ ticketDetails?.remark || '--' }} -
- diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue index 24eaa2b816..479cd5e347 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCapacity.vue @@ -24,21 +24,25 @@
+ class="capacity-box" + @click="handleClickSelect">
{{ $t('磁盘') }}: - 93.12% - ({{ data }}) - (+12.00%) + {{ percent > 100 ? 100 : percent }}% + {{ `(${data.used}G/${data.total}G)` }} + {{ `(${changeObj.rate}%, ${changeObj.num}G)` }}
@@ -49,7 +53,7 @@ import type { IDataRow } from './Row.vue'; interface Props { - data?: IDataRow['estimateCapacity']; + data?: IDataRow['targetCapacity']; isLoading?: boolean; } @@ -57,10 +61,36 @@ (e: 'click-select'): void } - defineProps(); + const props = defineProps(); const emits = defineEmits(); + const percent = computed(() => { + if (props.data) return Number(((props.data.used / props.data.total) * 100).toFixed(2)); + return 0; + }); + + const changeObj = computed(() => { + if (props.data) { + const diff = props.data.total - props.data.current; + const rate = ((diff / props.data.current) * 100).toFixed(2); + if (diff < 0) { + return { + rate, + num: diff, + }; + } + return { + rate: `+${rate}`, + num: `+${diff}`, + }; + } + return { + rate: 0, + num: 0, + }; + }); + const handleClickSelect = () => { emits('click-select'); }; @@ -95,7 +125,6 @@ margin-left: 5px; font-size: 12px; font-weight: bold; - color: #EA3636; } } } diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue index b01469565b..eec48b4a53 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/RenderTargetCluster.vue @@ -33,7 +33,7 @@ import type { IDataRow } from './Row.vue'; interface Props { - modelValue?: IDataRow['cluster'] + modelValue?: IDataRow['targetCluster'] } interface Emits { diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue index f7806a2960..f1b01baa90 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/Row.vue @@ -15,23 +15,26 @@ - + - + - + @@ -42,8 +45,7 @@ @@ -55,6 +57,12 @@ :is-loading="data.isLoading" :list="versionList" /> + + +
import { ref } from 'vue'; + import { RedisClusterTypes } from '@services/model/redis/redis'; + + import RenderText from '@components/db-table-columns/RenderText.vue'; + import { random } from '@utils'; import RenderCurrentCapacity from './RenderCurrentCapacity.vue'; - import RenderCurrentSpec from './RenderCurrentSpec.vue'; import RenderSpecifyVersion from './RenderSpecifyVersion.vue'; + import RenderSwitchMode, { type OnlineSwitchType } from './RenderSwitchMode.vue'; import RenderTargetCapacity from './RenderTargetCapacity.vue'; import RenderTargetCluster from './RenderTargetCluster.vue'; export interface IDataRow { rowKey: string; isLoading: boolean; - cluster: string; + targetCluster: string; clusterId: number; - currentPlan: string; - scaleUpPlan?: string; - currentCapacity?: string; - estimateCapacity?: string; + bkCloudId: number; + shardNum?: number; + groupNum?: number; + currentSepc?: string; + currentCapacity?: { + used: number, + total: number, + }; + targetCapacity?: { + current: number, + used: number, + total: number, + }; version?: string; + clusterType?: RedisClusterTypes; + switchMode?: OnlineSwitchType; + sepcId?: number, + targetShardNum?: number; + targetGroupNum?: number; } // 创建表格数据 export const createRowData = (): IDataRow => ({ rowKey: random(), isLoading: false, - cluster: '', + targetCluster: '', clusterId: 0, - currentPlan: '', - scaleUpPlan: '', - currentCapacity: '', - estimateCapacity: '', - version: '', + bkCloudId: 0, }); @@ -130,8 +152,8 @@ interface Exposes { getValue: () => Promise<{ - scaleUpPlan: string; - version: string; + version: string, + switchMode: string, }> } @@ -139,8 +161,8 @@ const emits = defineEmits(); - const scaleUpPlanRef = ref(); const versionRef = ref(); + const switchModeRef = ref(); const handleClickSelect = () => { emits('click-select'); @@ -164,13 +186,13 @@ defineExpose({ async getValue() { return Promise.all([ - scaleUpPlanRef.value.getValue(), versionRef.value.getValue(), + switchModeRef.value.getValue(), ]).then((data) => { - const [scaleUpPlan, version] = data; + const [version, switchMode] = data; return { - scaleUpPlan, version, + switchMode, }; }); }, diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue index 61825978bc..58b63e03bb 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page2/Index.vue @@ -15,7 +15,7 @@
{ router.push({ - name: 'RedisStorageScaleUp', + name: 'RedisCapacityChange', }); }; diff --git a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue index 90c7b07426..874b0ffa11 100644 --- a/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue +++ b/dbm-ui/frontend/src/views/redis/common/instance-selector/components/RenderRedisHost.vue @@ -86,7 +86,8 @@ ip: string; role: string; cluster_domain: string; - spec_config: SpecInfo + spec_config: SpecInfo; + instance_count?: number; } const props = defineProps(); @@ -101,7 +102,7 @@ const checkedMap = shallowRef({} as Record); - const masterSlaveMap: {[key: string]: string} = {}; + const masterSlaveMap: Record = {}; watch(() => props.lastValues, (lastValues) => { // 切换 tab 回显选中状态 \ 预览结果操作选中状态 @@ -281,6 +282,7 @@ role: data.role, cluster_domain: props.node?.clusterDomain ?? '', spec_config: data.spec_config, + instance_count: data.instance_count, }); const handleSelectPageAll = (checked: boolean) => { diff --git a/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue b/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue index 55ac18dc39..74af057012 100644 --- a/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue +++ b/dbm-ui/frontend/src/views/redis/common/spec-panel/Index.vue @@ -29,7 +29,8 @@ CPU:
- {{ $t('n核', { n: data.cpu }) }} + {{ data.cpu.min === data.cpu.max ? + $t('n核', { n: data.cpu.min }) :$t('((n-m))台', { n: data.cpu.min, m: data.cpu.max }) }}
@@ -37,7 +38,7 @@ {{ $t('内存') }}:
- {{ data.mem }} G + {{ data.mem.min === data.mem.max ? data.mem.min : `(${data.mem.min}~${data.mem.max})` }} G
@@ -59,13 +60,13 @@
- {{ data.storage_spec.mount_point }} + {{ data.storage_spec[0].mount_point }}
- {{ data.storage_spec.size }} + {{ data.storage_spec[0].size }}
- {{ data.storage_spec.type }} + {{ data.storage_spec[0].type }}
@@ -78,15 +79,20 @@ diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/Index.vue new file mode 100644 index 0000000000..332981bfcb --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/Index.vue @@ -0,0 +1,380 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Index.vue new file mode 100644 index 0000000000..225c4ba81e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Index.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderHost.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderHost.vue new file mode 100644 index 0000000000..fbc9cfdd47 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderHost.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderSpec.vue new file mode 100644 index 0000000000..9e98728f7d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderSpec.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderTargetNumber.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderTargetNumber.vue new file mode 100644 index 0000000000..78ad79e922 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderTargetNumber.vue @@ -0,0 +1,59 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue new file mode 100644 index 0000000000..461ade0009 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Row.vue new file mode 100644 index 0000000000..b8fd87a1d4 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/Row.vue @@ -0,0 +1,168 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page2/Index.vue new file mode 100644 index 0000000000..a3843b88e4 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue new file mode 100644 index 0000000000..77b34e231b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue @@ -0,0 +1,547 @@ + + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Index.vue new file mode 100644 index 0000000000..bd04a5a8d6 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Index.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderAccessCode.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderAccessCode.vue new file mode 100644 index 0000000000..cc784a1951 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderAccessCode.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderKeyRelated.vue new file mode 100644 index 0000000000..005d820d2b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderKeyRelated.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderSourceCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderSourceCluster.vue new file mode 100644 index 0000000000..efe74dec5d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderSourceCluster.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderTargetCluster.vue new file mode 100644 index 0000000000..e65d506c98 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/RenderTargetCluster.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Row.vue new file mode 100644 index 0000000000..d29cba1705 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Intra-business-third/Row.vue @@ -0,0 +1,197 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue new file mode 100644 index 0000000000..2388d03d2f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderKeyRelated.vue new file mode 100644 index 0000000000..005d820d2b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderKeyRelated.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderSourceCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderSourceCluster.vue new file mode 100644 index 0000000000..efe74dec5d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderSourceCluster.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetBusiness.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetBusiness.vue new file mode 100644 index 0000000000..6d037c6f77 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetBusiness.vue @@ -0,0 +1,91 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue new file mode 100644 index 0000000000..e65d506c98 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Row.vue new file mode 100644 index 0000000000..ee55fb7089 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Row.vue @@ -0,0 +1,196 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue new file mode 100644 index 0000000000..81f3efe9be --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue @@ -0,0 +1,202 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderAccessCode.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderAccessCode.vue new file mode 100644 index 0000000000..83af10d236 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderAccessCode.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderClusterType.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderClusterType.vue new file mode 100644 index 0000000000..ed815c55ab --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderClusterType.vue @@ -0,0 +1,93 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue new file mode 100644 index 0000000000..005d820d2b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderSourceCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderSourceCluster.vue new file mode 100644 index 0000000000..efe74dec5d --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderSourceCluster.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderTargetCluster.vue new file mode 100644 index 0000000000..e65d506c98 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderTargetCluster.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Row.vue new file mode 100644 index 0000000000..959a6e0c04 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Row.vue @@ -0,0 +1,209 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue new file mode 100644 index 0000000000..15d811ee85 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue new file mode 100644 index 0000000000..80ba92d4ea --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderSourceCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderSourceCluster.vue new file mode 100644 index 0000000000..d2e9f1ca21 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderSourceCluster.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue new file mode 100644 index 0000000000..e65d506c98 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Row.vue new file mode 100644 index 0000000000..f1ea1cfa2e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Row.vue @@ -0,0 +1,184 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue new file mode 100644 index 0000000000..2da54e344e --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue index b176d1688f..ac29d02748 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue @@ -109,7 +109,7 @@ const totalNum = computed(() => tableData.value.filter(item => Boolean(item.ip)).length); - // slave -> master + // slave <-> master const slaveMasterMap: Record = {}; // 检测列表是否为空 @@ -118,7 +118,7 @@ return false; } const [firstRow] = list; - return firstRow.ip; + return !firstRow.ip; }; // 更新slave -> master 映射表 @@ -134,6 +134,7 @@ if (pairs !== null) { pairs.forEach((item) => { slaveMasterMap[item.slave_ip] = item.master_ip; + slaveMasterMap[item.master_ip] = item.slave_ip; }); } }); @@ -205,11 +206,12 @@ isGeneral: true, rowSpan: 1, }, - spec: data.spec, + spec: data.spec_config, }; tableData.value[index] = obj; ipMemo[ip] = true; sortTableByCluster(); + updateSlaveMasterMap(); }; // 追加一个集群 @@ -255,7 +257,9 @@ const generateRequestParam = () => { const clusterMap: Record = {}; const dataArr = tableData.value.filter(item => Boolean(item.ip)); + const clusterIds = new Set(); dataArr.forEach((item) => { + clusterIds.add(item.clusterId); const clusterName = item.cluster.domain; if (!clusterMap[clusterName]) { clusterMap[clusterName] = [item]; @@ -263,8 +267,8 @@ clusterMap[clusterName].push(item); } }); - const keys = Object.keys(clusterMap); - const infos = keys.map((domain) => { + const domains = Object.keys(clusterMap); + const infos = domains.map((domain) => { const sameArr = clusterMap[domain]; const infoItem: InfoItem = { cluster_domain: domain, @@ -274,7 +278,7 @@ redis_master: [], redis_slave: [], }; - + const needDeleteSlaves: string[] = []; sameArr.forEach((item) => { const specObj = { ip: item.ip, @@ -284,10 +288,14 @@ infoItem.redis_slave.push(specObj); } else if (item.role === 'master') { infoItem.redis_master.push(specObj); + const deleteSlaveIp = slaveMasterMap[item.ip]; + if (deleteSlaveIp) needDeleteSlaves.push(deleteSlaveIp); } else { infoItem.proxy.push(specObj); } }); + // 当选择了master的时候,对应的slave不要传给后端 + infoItem.redis_slave = infoItem.redis_slave.filter(item => !needDeleteSlaves.includes(item.ip)); return infoItem; }); return infos; @@ -298,7 +306,7 @@ const infos = generateRequestParam(); const params: SubmitTicket = { bk_biz_id: currentBizId, - ticket_type: TicketTypes.REDIS_CLUSTER_SLAVE_CUTOFF, + ticket_type: TicketTypes.REDIS_CLUSTER_CUTOFF, details: { ip_source: 'resource_pool', infos, @@ -324,7 +332,6 @@ }); }) .catch((e) => { - // 目前后台还未调通 console.error('db repace submit ticket error', e); }) .finally(() => { diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue index 1550fa9e8c..cbf695d407 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue @@ -37,6 +37,7 @@ {{ $t('规格需求') }} diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue index 8f6c98475a..6bf68338ef 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Row.vue @@ -78,15 +78,21 @@ rowSpan: number }, spec?: { - cpu: number; + cpu: { + max: number; + min: number; + }, id: number; - mem: number; + mem: { + max: number; + min: number; + }, name: string; storage_spec: { mount_point: string; size: number; type: string; - } + }[] } } @@ -97,6 +103,7 @@ ip: data?.ip ?? '', role: data?.role ?? '', clusterId: 0, + bkCloudId: 0, cluster: { domain: data?.cluster?.domain ?? '', isStart: false, diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue index 362244fde9..3d3ece1765 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue @@ -115,7 +115,7 @@ return false; } const [firstRow] = list; - return firstRow.cluster; + return !firstRow.cluster; }; // Master 批量选择 @@ -148,7 +148,6 @@ bkCloudId: item.cluster.bk_cloud_id, instances, spec: { - count: instances.length, ...item.storage[0].machine__spec_config, }, }; @@ -178,7 +177,6 @@ bkCloudId: data.cluster.bk_cloud_id, instances, spec: { - count: instances.length, ...data.storage[0].machine__spec_config, }, }; diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderSpec.vue index 9e98728f7d..fc48cf6abd 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderSpec.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderSpec.vue @@ -35,7 +35,7 @@ v-if="!data" key="empty" style="color: #c4c6cc;"> - {{ $t('输入主机后自动生成') }} + {{ $t('输入集群后自动生成') }} diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue index a246f6360f..67a52b680f 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue @@ -63,6 +63,8 @@ - diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/SpecSelect.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/SpecSelect.vue deleted file mode 100644 index bd47c670e6..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/SpecSelect.vue +++ /dev/null @@ -1,425 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue index 3dadb9ab2a..10fff8bc80 100644 --- a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue @@ -119,7 +119,7 @@ return false; } const [firstRow] = list; - return firstRow.ip; + return !firstRow.ip; }; // Master 批量选择 @@ -171,24 +171,19 @@ tableData.value[index].ip = ip; const ret = await queryMasterSlaveByIp({ ips: [ip], - }).catch((e) => { - console.error('query cluster info by ip failed: ', e); - return null; }); - if (ret) { - const data = ret[0]; - const obj = { - rowKey: tableData.value[index].rowKey, - isLoading: false, - ip, - clusterId: data.cluster.id, - cluster: data.cluster?.immute_domain, - masters: data.instances.map(item => item.instance), - slave: data.slave_ip, - }; - tableData.value[index] = obj; - ipMemo[ip] = true; - } + const data = ret[0]; + const obj = { + rowKey: tableData.value[index].rowKey, + isLoading: false, + ip, + clusterId: data.cluster.id, + cluster: data.cluster?.immute_domain, + masters: data.instances.map(item => item.instance), + slave: data.slave_ip, + }; + tableData.value[index] = obj; + ipMemo[ip] = true; }; // 追加一个集群 @@ -232,7 +227,7 @@ const infos = generateRequestParam(); const params: SubmitTicket & { details: { force: boolean }} = { bk_biz_id: currentBizId, - ticket_type: TicketTypes.REDIS_CLUSTER_MASTER_FAILOVER, + ticket_type: TicketTypes.REDIS_MASTER_SLAVE_SWITCH, details: { force: isForceSwitch.value, infos, diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue index e16a5a69b2..880e0c5c4b 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue @@ -101,7 +101,7 @@ return false; } const [firstRow] = list; - return firstRow.cluster; + return !firstRow.cluster; }; const router = useRouter(); @@ -138,7 +138,7 @@ clustersInfo.forEach((item) => { const domain = item.cluster.immute_domain; if (!domainMemo[domain]) { - const row: IDataRow = { + const row = { rowKey: item.cluster.immute_domain, isLoading: false, cluster: item.cluster.immute_domain, @@ -146,11 +146,11 @@ bkCloudId: item.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { - count: item.proxy.length, ...item.proxy[0].machine__spec_config, }, targetNum: '1', }; + row.spec.count = item.proxy.length; newList.push(row); domainMemo[domain] = true; } @@ -166,25 +166,23 @@ // 输入集群后查询集群信息并填充到table const handleChangeCluster = async (index: number, domain: string) => { const ret = await getClusterInfo(domain); - if (ret) { - const data = ret[0]; - const row: IDataRow = { - rowKey: data.cluster.immute_domain, - isLoading: false, - cluster: data.cluster.immute_domain, - clusterId: data.cluster.id, - bkCloudId: data.cluster.bk_cloud_id, - nodeType: 'Proxy', - spec: { - count: data.proxy.length, - ...data.proxy[0].machine__spec_config, + const data = ret[0]; + const row = { + rowKey: data.cluster.immute_domain, + isLoading: false, + cluster: data.cluster.immute_domain, + clusterId: data.cluster.id, + bkCloudId: data.cluster.bk_cloud_id, + nodeType: 'Proxy', + spec: { + ...data.proxy[0].machine__spec_config, - }, - targetNum: '1', - }; - tableData.value[index] = row; - domainMemo[domain] = true; - } + }, + targetNum: '1', + }; + row.spec.count = data.proxy.length; + tableData.value[index] = row; + domainMemo[domain] = true; }; // 追加一个集群 @@ -193,6 +191,7 @@ dataList.splice(index + 1, 0, ...appendList); tableData.value = dataList; }; + // 删除一个集群 const handleRemove = (index: number) => { const dataList = [...tableData.value]; diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue index 9b1f0c42db..d4c2f40fdb 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue @@ -109,11 +109,11 @@ // 检测列表是否为空 const checkListEmpty = (list: Array) => { - if (list.length > 0) { + if (list.length > 1) { return false; } const [firstRow] = list; - return firstRow.cluster; + return !firstRow.cluster; }; // Master 批量选择 @@ -136,7 +136,7 @@ clustersInfo.forEach((item) => { const domain = item.cluster.immute_domain; if (!domainMemo[domain]) { - const row: IDataRow = { + const row = { rowKey: item.cluster.immute_domain, isLoading: false, cluster: item.cluster.immute_domain, @@ -144,11 +144,11 @@ bkCloudId: item.cluster.bk_cloud_id, nodeType: 'Proxy', spec: { - count: item.proxy.length, ...item.proxy[0].machine__spec_config, }, targetNum: '1', }; + row.spec.count = item.proxy.length; newList.push(row); domainMemo[domain] = true; } @@ -164,25 +164,22 @@ // 输入集群后查询集群信息并填充到table const handleChangeCluster = async (index: number, domain: string) => { const ret = await getClusterInfo(domain); - if (ret) { - const data = ret[0]; - const row: IDataRow = { - rowKey: data.cluster.immute_domain, - isLoading: false, - cluster: data.cluster.immute_domain, - clusterId: data.cluster.id, - bkCloudId: data.cluster.bk_cloud_id, - nodeType: 'Proxy', - spec: { - count: data.proxy.length, - ...data.proxy[0].machine__spec_config, - - }, - targetNum: '1', - }; - tableData.value[index] = row; - domainMemo[domain] = true; - } + const data = ret[0]; + const row = { + rowKey: data.cluster.immute_domain, + isLoading: false, + cluster: data.cluster.immute_domain, + clusterId: data.cluster.id, + bkCloudId: data.cluster.bk_cloud_id, + nodeType: 'Proxy', + spec: { + ...data.proxy[0].machine__spec_config, + }, + targetNum: '1', + }; + row.spec.count = data.proxy.length, + tableData.value[index] = row; + domainMemo[domain] = true; }; // 追加一个集群 diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue index ee2db733c6..8e38a05718 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/SpecPanel.vue @@ -28,7 +28,8 @@ CPU:
- {{ $t('n核', { n: data.cpu }) }} + {{ data.cpu.min === data.cpu.max ? + $t('n核', { n: data.cpu.min }) :$t('((n-m))台', { n: data.cpu.min, m: data.cpu.max }) }}
@@ -36,7 +37,7 @@ {{ $t('内存') }}:
- {{ data.mem }} G + {{ data.mem.min === data.mem.max ? data.mem.min : `(${data.mem.min}~${data.mem.max})` }} G
@@ -58,13 +59,13 @@
- {{ data.storage_spec.mount_point }} + {{ data.storage_spec[0].mount_point }}
- {{ data.storage_spec.size }} + {{ data.storage_spec[0].size }}
- {{ data.storage_spec.type }} + {{ data.storage_spec[0].type }}
@@ -77,15 +78,21 @@ - diff --git a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts index b3235161c8..71d8a23a4b 100644 --- a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts +++ b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts @@ -39,6 +39,11 @@ export default [ id: 'RedisProxyScaleDown', parentId: 'redis', }, + { + name: t('新建从库'), + id: 'RedisDBCreateSlave', + parentId: 'redis', + }, { name: t('主故障切换'), id: 'RedisMasterFailover', @@ -54,7 +59,7 @@ export default [ { name: t('数据构造'), id: 'redis', - icon: 'db-icon-cluster', + icon: 'db-icon-copy', children: [ { name: t('定点构造'), @@ -68,4 +73,16 @@ export default [ }, ], }, + { + name: t('数据传输(DTS)'), + id: 'redis', + icon: 'db-icon-data', + children: [ + { + name: t('数据复制'), + id: 'RedisDBDataCopy', + parentId: 'redis', + }, + ], + }, ]; From 42d75c380fb5654891d8431c2ccda7422de436a1 Mon Sep 17 00:00:00 2001 From: austinqli <1344583166@qq.com> Date: Fri, 14 Jul 2023 12:06:48 +0800 Subject: [PATCH 147/476] =?UTF-8?q?feat(frontend):=20redis=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=20#396?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/src/locales/zh-cn.json | 1 + dbm-ui/frontend/src/services/dbResource.ts | 27 --------- .../model/resource-spec/cluster-sepc.ts | 4 +- .../capacity-change/pages/page1/Index.vue | 14 ++--- .../components/ChooseClusterTargetPlan.vue | 20 +++---- .../db-create-slave/pages/page1/Index.vue | 28 ++++----- .../page1/components/RenderTargetNumber.vue | 59 ------------------- .../pages/page1/components/RenderText.vue | 45 -------------- .../redis/db-data-copy/pages/page1/Index.vue | 6 +- .../page1/Intra-business-third/Index.vue | 9 +-- .../pages/page1/cross-business/Index.vue | 9 +-- .../Index.vue | 9 +-- .../pages/page1/within-business/Index.vue | 10 +--- .../redis/db-replace/pages/page1/Index.vue | 33 +++++------ .../redis/db-structure/pages/page1/Index.vue | 10 +--- .../master-failover/pages/page1/Index.vue | 10 +--- .../proxy-scale-down/pages/page1/Index.vue | 10 +--- .../proxy-scale-up/pages/page1/Index.vue | 10 +--- 18 files changed, 73 insertions(+), 241 deletions(-) delete mode 100644 dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderTargetNumber.vue delete mode 100644 dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 3643823939..7f508b0282 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1608,5 +1608,6 @@ "*Key$ :提取以 Key 结尾的 key,包括 Key": "*Key$ :提取以 Key 结尾的 key,包括 Key", "^Key$:提取精确匹配的Key": "^Key$:提取精确匹配的Key", "* :代表所有": "* :代表所有", + "未来集群容量必须大于等于当前的容量需求": "", "这行勿动!新增翻译请在上一行添加!": "" } \ No newline at end of file diff --git a/dbm-ui/frontend/src/services/dbResource.ts b/dbm-ui/frontend/src/services/dbResource.ts index 3c95f697c2..f52f240a0d 100644 --- a/dbm-ui/frontend/src/services/dbResource.ts +++ b/dbm-ui/frontend/src/services/dbResource.ts @@ -15,7 +15,6 @@ import DbResourceModel from '@services/model/db-resource/DbResource'; import DeployPlanModel from '@services/model/db-resource/DeployPlan'; import ImportHostModel from '@services/model/db-resource/import-host'; import OperationModel from '@services/model/db-resource/Operation'; -import ClusterSpecModel from '@services/model/resource-spec/cluster-sepc'; import ResourceSpecModel from '@services/model/resource-spec/resourceSpec'; import http from './http'; @@ -164,29 +163,3 @@ export function fetchRecommendSpec(params: { .then(data => data.map(item => new ResourceSpecModel(item))); } - -interface QueryQPSRangeParams { - spec_cluster_type: string, - spec_machine_type: string, - capacity: number, - future_capacity: number, -} - -// 获取qps的范围 -export function queryQPSRange(params: QueryQPSRangeParams) { - return http.get<{ - min: number, - max: number - }>('/apis/dbresource/spec/query_qps_range/', params); -} - -// 筛选集群部署规格方案 -export function queryClusterDeployPlans(params: QueryQPSRangeParams & { - qps: { - min: number, - max: number - } -}) { - return http.post('/apis/dbresource/spec/filter_cluster_spec/', params); -} - diff --git a/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts b/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts index 7bfd9b2c18..13c4e2ec69 100644 --- a/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts +++ b/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts @@ -14,7 +14,7 @@ /** * 集群节点规格 */ -export default class ClusterSpec { +export default class RedisClusterSpec { capacity: number; cluster_capacity: number; cluster_shard_num: number; @@ -44,7 +44,7 @@ export default class ClusterSpec { type: string; }[]; - constructor(payload = {} as ClusterSpec) { + constructor(payload = {} as RedisClusterSpec) { this.capacity = payload.capacity; this.cluster_capacity = payload.cluster_capacity; this.cluster_shard_num = payload.cluster_shard_num; diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue index 743330b16d..0776bf2ce4 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue @@ -69,7 +69,7 @@ import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; - import ClusterSpecModel from '@services/model/resource-spec/cluster-sepc'; + import RedisClusterSpecModel from '@services/model/resource-spec/cluster-sepc'; import { createTicket } from '@services/ticket'; import type { SubmitTicket } from '@services/types/ticket'; @@ -147,7 +147,7 @@ }); // 从侧边窗点击确认后触发 - const handleChoosedTargetCapacity = (obj: ClusterSpecModel) => { + const handleChoosedTargetCapacity = (obj: RedisClusterSpecModel) => { const currentRow = tableData.value[activeRowIndex.value]; currentRow.sepcId = obj.spec_id; currentRow.targetShardNum = obj.cluster_shard_num; @@ -241,16 +241,12 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const { targetCluster } = dataList[index]; - dataList.splice(index, 1); - tableData.value = dataList; + const { targetCluster } = tableData.value[index]; + tableData.value.splice(index, 1); delete domainMemo[targetCluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue index 693d8fcc2c..b885bf0121 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue @@ -117,7 +117,7 @@ v-model="capacityFutureNeed" class="mb10" clearable - :max="100" + :max="100000000" :min="1" size="small" type="number" /> @@ -173,9 +173,9 @@ diff --git a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue b/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue deleted file mode 100644 index 461ade0009..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-create-slave/pages/page1/components/RenderText.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue index 77b34e231b..4ba483449b 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue @@ -38,15 +38,15 @@ :cluster-list="clusterList" @on-change-table-available="handleTableDataAvailableChange" />
) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const { srcCluster } = removeItem; - dataList.splice(index, 1); + tableData.value.splice(index, 1); delete domainMemo[srcCluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue index 2388d03d2f..114915a10f 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/Index.vue @@ -115,16 +115,13 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const { srcCluster } = removeItem; - dataList.splice(index, 1); + tableData.value.splice(index, 1); delete domainMemo[srcCluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue index 81f3efe9be..cc136ff988 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/Index.vue @@ -119,16 +119,13 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const { srcCluster } = removeItem; - dataList.splice(index, 1); + tableData.value.splice(index, 1); delete domainMemo[srcCluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue index 15d811ee85..9656910942 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/Index.vue @@ -110,18 +110,14 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const { srcCluster } = removeItem; - dataList.splice(index, 1); - tableData.value = dataList; + tableData.value.splice(index, 1); delete domainMemo[srcCluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue index ac29d02748..3b36574cdb 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/Index.vue @@ -216,18 +216,15 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); sortTableByCluster(); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const removeIp = removeItem.ip; - dataList.splice(index, 1); + tableData.value.splice(index, 1); delete ipMemo[removeIp]; // slave 与 master 删除联动 @@ -236,35 +233,35 @@ if (masterIp) { // 看看表中有没有对应的master let masterIndex = -1; - for (let i = 0; i < dataList.length; i++) { - if (dataList[i].ip === masterIp) { + for (let i = 0; i < tableData.value.length; i++) { + if (tableData.value[i].ip === masterIp) { masterIndex = i; break; } } if (masterIndex !== -1) { // 表格中存在master记录 - dataList.splice(masterIndex, 1); + tableData.value.splice(masterIndex, 1); delete ipMemo[masterIp]; } } } - tableData.value = dataList; sortTableByCluster(); }; // 根据表格数据生成提交单据请求参数 const generateRequestParam = () => { const clusterMap: Record = {}; - const dataArr = tableData.value.filter(item => Boolean(item.ip)); const clusterIds = new Set(); - dataArr.forEach((item) => { - clusterIds.add(item.clusterId); - const clusterName = item.cluster.domain; - if (!clusterMap[clusterName]) { - clusterMap[clusterName] = [item]; - } else { - clusterMap[clusterName].push(item); + tableData.value.forEach((item) => { + if (item.ip) { + clusterIds.add(item.clusterId); + const clusterName = item.cluster.domain; + if (!clusterMap[clusterName]) { + clusterMap[clusterName] = [item]; + } else { + clusterMap[clusterName].push(item); + } } }); const domains = Object.keys(clusterMap); diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue index 3d3ece1765..d7d3f38d30 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/Index.vue @@ -187,16 +187,12 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const { cluster } = dataList[index]; - dataList.splice(index, 1); - tableData.value = dataList; + const { cluster } = tableData.value[index]; + tableData.value.splice(index, 1); delete domainMemo[cluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue index 10fff8bc80..d85ba3eaba 100644 --- a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue @@ -188,19 +188,15 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const removeItem = dataList[index]; + const removeItem = tableData.value[index]; const removeIp = removeItem.ip; - dataList.splice(index, 1); + tableData.value.splice(index, 1); delete ipMemo[removeIp]; - tableData.value = dataList; }; // 根据表格数据生成提交单据请求参数 diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue index 880e0c5c4b..fd0f9c1676 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue @@ -187,17 +187,13 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const { cluster } = dataList[index]; - dataList.splice(index, 1); - tableData.value = dataList; + const { cluster } = tableData.value[index]; + tableData.value.splice(index, 1); delete domainMemo[cluster]; }; diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue index d4c2f40fdb..19d747d392 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/Index.vue @@ -184,16 +184,12 @@ // 追加一个集群 const handleAppend = (index: number, appendList: Array) => { - const dataList = [...tableData.value]; - dataList.splice(index + 1, 0, ...appendList); - tableData.value = dataList; + tableData.value.splice(index + 1, 0, ...appendList); }; // 删除一个集群 const handleRemove = (index: number) => { - const dataList = [...tableData.value]; - const { cluster } = dataList[index]; - dataList.splice(index, 1); - tableData.value = dataList; + const { cluster } = tableData.value[index]; + tableData.value.splice(index, 1); delete domainMemo[cluster]; }; From 027fde42f65422b0e4cf0805fd79e81949582ae0 Mon Sep 17 00:00:00 2001 From: iSecloud <869820505@qq.com> Date: Fri, 14 Jul 2023 14:28:06 +0800 Subject: [PATCH 148/476] =?UTF-8?q?fix(backend):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E9=9B=86=E7=BE=A4=E8=A7=84=E6=A0=BC=E7=9A=84qps=E5=80=BC=20#49?= =?UTF-8?q?8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_services/dbresource/handlers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dbm-ui/backend/db_services/dbresource/handlers.py b/dbm-ui/backend/db_services/dbresource/handlers.py index e54a413130..0616a4100f 100644 --- a/dbm-ui/backend/db_services/dbresource/handlers.py +++ b/dbm-ui/backend/db_services/dbresource/handlers.py @@ -34,7 +34,9 @@ def calc_machine_pair(self): """计算每种规格所需的机器组数和集群总容量: 目标容量 / 规格容量""" for spec in self.specs: spec["machine_pair"] = math.ceil(self.capacity / spec["capacity"]) + # 集群容量:机器组数 * 规格容量;集群qps:机器组数 * 规格qps的min spec["cluster_capacity"] = spec["machine_pair"] * spec["capacity"] + spec["cluster_qps"] = spec["machine_pair"] * spec["qps"]["min"] def calc_cluster_shard_num(self): """计算每种规格的分片数, 根据不同的集群计算方式也不同""" From 07dd8ddc12b9f6e401143e50fbd4a26d66992204 Mon Sep 17 00:00:00 2001 From: yksitu <1297650644@qq.com> Date: Fri, 14 Jul 2023 16:15:14 +0800 Subject: [PATCH 149/476] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4tendb=20cluste?= =?UTF-8?q?r=E9=9B=86=E7=BE=A4=E9=83=A8=E7=BD=B2=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E5=85=A5=E5=8F=82=E6=A0=BC=E5=BC=8F=20#495?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scene/spider/spider_cluster_deploy.py | 52 ++++++++----------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py index 4e077b8489..e2c0afdc76 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_deploy.py @@ -78,14 +78,20 @@ def __init__(self, root_id: str, data: Optional[Dict]): # 集群所有组件统一字符集配置 self.data["ctl_charset"] = self.data["spider_charset"] = self.data["charset"] - # 一个单据自动生成同一份随机密码, 中控实例需要,不需要内部来维护 + # 一个单据自动生成同一份随机密码, 中控实例需要,不需要内部来维护,每次部署随机生成一次 self.tdbctl_pass = get_random_string(length=10) # 声明中控实例的端口 self.data["ctl_port"] = self.data["spider_port"] + 1000 - if len(self.data["mysql_ip_list"]) % 2 != 0: - raise Exception(_("存入的存储节点数量不是偶数,请检查!")) + if len(self.data["remote_group"]) * int(self.data["remote_shard_num"]) != int(self.data["cluster_shard_num"]): + raise Exception(_("传入参数有异常,请检查!len(remote_group)*remote_shard_num != cluster_shard_num")) + + # 获取所有的remote ip + self.data["mysql_ip_list"] = [] + for i in self.data["remote_group"]: + self.data["mysql_ip_list"].append(i["master"]) + self.data["mysql_ip_list"].append(i["slave"]) def __calc_install_ports(self, inst_sum: int) -> list: """ @@ -107,29 +113,21 @@ def __calc_install_ports(self, inst_sum: int) -> list: def __assign_shard_master_slave(self, install_port_list: list) -> Optional[List[ShardInfo]]: """ 根据需求场景,为集群每个分片组分配合适的主从机器 - todo 后续需要在自动分配时保持分片组的主从机器的反亲和性 - @param + 资源池获取的资源保持分片组的主从机器的具有反亲和性 + @param install_port_list: 单机部署的端口列表 """ shard_cluster_list = [] - master_ip = "" - slave_ip = "" - cycles = 0 - mysql_ip_list = copy.deepcopy(self.data["mysql_ip_list"]) - for key in range(1, self.data["cluster_shard_num"] + 1): - - if len(install_port_list) * cycles < key: - master_ip = mysql_ip_list.pop(0)["ip"] - slave_ip = mysql_ip_list.pop(0)["ip"] - cycles += 1 - - inst_tuple = InstanceTuple( - master_ip=master_ip, - slave_ip=slave_ip, - mysql_port=install_port_list[(key - 1) % len(install_port_list)], - ) - shard_info = ShardInfo(shard_key=key - 1, instance_tuple=inst_tuple) - shard_cluster_list.append(shard_info) - + start_index = 0 + for remote_tuple in self.data["remote_group"]: + for index, mysql_port in enumerate(install_port_list): + inst_tuple = InstanceTuple( + master_ip=remote_tuple["master"]["ip"], + slave_ip=remote_tuple["slave"]["ip"], + mysql_port=mysql_port, + ) + shard_info = ShardInfo(shard_key=index + start_index, instance_tuple=inst_tuple) + shard_cluster_list.append(shard_info) + start_index += len(install_port_list) return shard_cluster_list def __create_cluster_nodes_info(self, shard_infos: Optional[List[ShardInfo]]) -> dict: @@ -162,15 +160,11 @@ def deploy_cluster(self): """ 机器通过手动输入IP而触发的场景 todo 集群所有节点的时区是否需要对比?如果要对比,怎么对比 - todo 补充周边组件部署 todo 目前bamboo-engine存在bug,不能正常给trans_data初始化值,先用流程套子流程方式来避开这个问题 """ - # 根据集群总分片数、存储节点数量计算出每个节点需要部署的实例的数量, - # 比如总分片数是4,存储节点是4,那么每个存储需要部署2个实例(考虑主从) - inst_sum = int(self.data["cluster_shard_num"] / int((len(self.data["mysql_ip_list"]) / 2))) # 计算每个mysql机器需要部署的mysql端口信息 - self.data["mysql_ports"] = self.__calc_install_ports(inst_sum=inst_sum) + self.data["mysql_ports"] = self.__calc_install_ports(inst_sum=int(self.data["remote_shard_num"])) # 先确定谁是中控集群中谁是master,对后续做数据同步依赖和初始化集群路由信息依赖 ctl_master = self.data["spider_ip_list"][0] From 779a9e09ef9fc28e962838abb1642f204c165047 Mon Sep 17 00:00:00 2001 From: seanlook Date: Fri, 14 Jul 2023 16:48:10 +0800 Subject: [PATCH 150/476] =?UTF-8?q?feat(mysql):=20=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E5=A4=87=E4=BB=BD=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=20close=20#470?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../go-pubpkg/backupclient/backupclient.go | 100 ++++++++++ .../common/go-pubpkg/backupclient/types.go | 40 ++++ .../common/go-pubpkg/cmutil/command.go | 51 ++++++ .../common/go-pubpkg/netutil/netutil.go | 24 +++ dbm-services/mysql/db-tools/dbactuator/go.mod | 1 + dbm-services/mysql/db-tools/dbactuator/go.sum | 2 + .../internal/subcmd/mysqlcmd/cmd.go | 1 + .../subcmd/mysqlcmd/install_backup_client.go | 98 ++++++++++ .../components/mysql/install_backup_client.go | 173 ++++++++++++++++++ .../db-tools/dbactuator/pkg/core/cst/mysql.go | 3 +- .../pkg/src/dbareport/report.go | 22 ++- .../db-tools/mysql-rotatebinlog/Makefile | 3 +- .../pkg/backup/backup_cos.go | 15 +- .../pkg/backup/backup_ibs.go | 10 +- .../mysql-rotatebinlog/pkg/backup/init.go | 6 +- .../mysql-rotatebinlog/pkg/util/util.go | 47 +---- 16 files changed, 540 insertions(+), 56 deletions(-) create mode 100644 dbm-services/common/go-pubpkg/backupclient/backupclient.go create mode 100644 dbm-services/common/go-pubpkg/backupclient/types.go create mode 100644 dbm-services/common/go-pubpkg/netutil/netutil.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/install_backup_client.go create mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_backup_client.go diff --git a/dbm-services/common/go-pubpkg/backupclient/backupclient.go b/dbm-services/common/go-pubpkg/backupclient/backupclient.go new file mode 100644 index 0000000000..2615a8f846 --- /dev/null +++ b/dbm-services/common/go-pubpkg/backupclient/backupclient.go @@ -0,0 +1,100 @@ +package backupclient + +import ( + "encoding/json" + "path/filepath" + "strings" + + "github.com/pkg/errors" + + "dbm-services/common/go-pubpkg/cmutil" +) + +const ( + BackupClientPath = "/usr/local/backup_client/bin/backup_client" + AuthFilePath = ".cosinfo.toml" +) + +type BackupClient struct { + ClientPath string + AuthFile string + FileTag string + + registerArgs []string + queryArgs []string +} + +type RegisterResp struct { + TaskId string `json:"task_id"` +} + +type QueryResp struct { + TaskId string `json:"task_id"` + Status int `json:"status"` + StatusMsg string `json:"status_msg"` +} + +// New 初始一个 backup_client 命令 +// 默认使用 /usr/local/backup_client/bin/backup_client --auth-file $HOME/.cosinfo.toml +func New(clientPath string, authFile string, fileTag string) (*BackupClient, error) { + if clientPath == "" { + clientPath = BackupClientPath + } + if !cmutil.FileExists(clientPath) { + return nil, errors.Errorf("backup_client not found:%s", clientPath) + } + + b := &BackupClient{ + ClientPath: clientPath, + AuthFile: authFile, + FileTag: fileTag, + } + if b.FileTag == "" { + return nil, errors.New("file_tag is required") + } + b.registerArgs = []string{b.ClientPath, "register", "--tag", b.FileTag} + if b.AuthFile != "" { + if !cmutil.FileExists(b.AuthFile) { + return nil, errors.Errorf("auth-file not found:%s", clientPath) + } + b.registerArgs = append(b.registerArgs, "--auth-file", b.AuthFile) + } + b.queryArgs = []string{b.ClientPath, "query"} + return b, nil +} + +func (b *BackupClient) register(filePath string) (backupTaskId string, err error) { + if !filepath.IsAbs(filePath) { + return "", errors.Errorf("file %s need absolute path", filePath) + } + registerArgs := append(b.registerArgs, "-f", filePath) + stdoutStr, stderrStr, err := cmutil.ExecCommand(false, registerArgs[0], registerArgs[1:]...) + if err != nil { + return "", errors.Wrapf(err, "register cmd failed %v with %s", registerArgs, stderrStr) + } + if strings.Count(stdoutStr, "-") == 3 && len(stdoutStr) < 80 { + // 这里粗略判断是否是合法的 task_id + return stdoutStr, nil + } else { + return "", errors.Errorf("illegal backup_task_id %s for %s", stdoutStr, filePath) + } +} + +// Upload upload 异步的,调用 register 来本地注册任务 +func (b *BackupClient) Upload(filePath string) (backupTaskId string, err error) { + return b.register(filePath) +} + +func (b *BackupClient) Query(backupTaskId string) (uploadStatus int, err error) { + queryArgs := append(b.queryArgs, "--task-id", backupTaskId) + stdout, stderr, err := cmutil.ExecCommandReturnBytes(false, queryArgs[0], queryArgs[1:]...) + if err != nil { + return 0, errors.Wrapf(err, "query cmd failed %v with %s", queryArgs, string(stderr)) + } + return 4, nil + var resp QueryResp + if err := json.Unmarshal(stdout, &resp); err != nil { + return 0, errors.Wrapf(err, "parse query response %s", string(stdout)) + } + return resp.Status, err +} diff --git a/dbm-services/common/go-pubpkg/backupclient/types.go b/dbm-services/common/go-pubpkg/backupclient/types.go new file mode 100644 index 0000000000..bfcf0e7751 --- /dev/null +++ b/dbm-services/common/go-pubpkg/backupclient/types.go @@ -0,0 +1,40 @@ +package backupclient + +// CosAuth cos bucket 信息 +type CosAuth struct { + CosServer string `mapstructure:"cos_server" json:"cos_server" toml:"cos_server"` + Region string `mapstructure:"region" json:"region" toml:"region"` + SecretId string `mapstructure:"secret_id" json:"secret_id" toml:"secret_id"` + SecretKey string `mapstructure:"secret_key" json:"secret_key" toml:"secret_key"` + BucketName string `mapstructure:"bucket_name" json:"bucket_name" toml:"bucket_name"` +} + +// AppAttr 机器业务属性 +type AppAttr struct { + BkBizId int `mapstructure:"bk_biz_id" json:"bk_biz_id" toml:"bk_biz_id"` + BkCloudId int `mapstructure:"bk_cloud_id" json:"bk_cloud_id" toml:"bk_cloud_id"` +} + +// CosInfo cosinfo.toml +type CosInfo struct { + Cos *CosAuth `toml:"cos_auth" json:"cos_auth"` + AppAttr *AppAttr `toml:"app_attr" json:"app_attr"` +} + +type CosClientConfig struct { + Base BaseLimit `toml:"coslimits" json:"coslimit" mapstructure:"coslimits"` + Cfg UploadConfig `toml:"cfg" json:"cfg" mapstructure:"cfg"` +} + +type UploadConfig struct { + // FileTagAllowed 允许的 file tag 列表 + FileTagAllowed string `mapstructure:"file_tag_allowed" json:"file_tag_allowed" toml:"file_tag_allowed"` + // NetAddr 本机内网ip地址 + NetAddr string `mapstructure:"net_addr" json:"net_addr" toml:"net_addr"` +} + +type BaseLimit struct { + BlockSize int `mapstructure:"chunk_size" json:"block_size" toml:"chunk_size"` + LocalTotalLimit int `mapstructure:"local_total_limit" json:"local_total_limit" toml:"local_total_limit"` + LocalFileLimit int `mapstructure:"local_file_limit" json:"local_file_limit" toml:"local_file_limit"` +} diff --git a/dbm-services/common/go-pubpkg/cmutil/command.go b/dbm-services/common/go-pubpkg/cmutil/command.go index a03c8961c0..4cf3ac61bd 100644 --- a/dbm-services/common/go-pubpkg/cmutil/command.go +++ b/dbm-services/common/go-pubpkg/cmutil/command.go @@ -3,7 +3,9 @@ package cmutil import ( "bytes" "fmt" + "os" "os/exec" + "strings" "github.com/pkg/errors" ) @@ -32,3 +34,52 @@ func ExecShellCommand(isSudo bool, param string) (stdoutStr string, err error) { return stdout.String(), nil } + +// ExecCommand bash=true: bash -c 'cmdName args', bash=false: ./cmdName args list +// ExecCommand(false, "df", "-k /data") will get `df '-k /data'` error command. you need change it to (false, "df", "-k", "/data") or (true, "df -k /data") +// bash=false need PATH +// return stdout, stderr ,err +func ExecCommand(bash bool, cmdName string, args ...string) (string, string, error) { + stdout, stderr, err := ExecCommandReturnBytes(bash, cmdName, args...) + if err != nil { + return "", "", err + } + stdoutStr := strings.TrimSpace(string(stdout)) + stderrStr := strings.TrimSpace(string(stderr)) + return stdoutStr, stderrStr, nil +} + +// ExecCommandReturnBytes run exec.Command +// return stdout, stderr ,err +func ExecCommandReturnBytes(bash bool, cmdName string, args ...string) ([]byte, []byte, error) { + var cmd *exec.Cmd + if bash { + if cmdName != "" { + cmdName += " " + } + cmdStr := fmt.Sprintf(`%s%s`, cmdName, strings.Join(args, " ")) + cmd = exec.Command("bash", "-c", cmdStr) + } else { + if cmdName == "" { + return nil, nil, errors.Errorf("command name should not be empty:%v", args) + } + // args should be list + cmd = exec.Command(cmdName, args...) + } + cmd.Env = []string{ + fmt.Sprintf( + "PATH=%s:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin", + os.Getenv("PATH"), + ), + } + //logger.Info("PATH:%s cmd.Env:%v", os.Getenv("PATH"), cmd.Env) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + + //logger.Error("stdout:%s, stderr:%s, cmd:%s", stdout.String(), stderr.String(), cmd.String()) + return stdout.Bytes(), stderr.Bytes(), errors.Wrap(err, cmd.String()) + } + return stdout.Bytes(), stderr.Bytes(), nil +} diff --git a/dbm-services/common/go-pubpkg/netutil/netutil.go b/dbm-services/common/go-pubpkg/netutil/netutil.go new file mode 100644 index 0000000000..7f7b69ea16 --- /dev/null +++ b/dbm-services/common/go-pubpkg/netutil/netutil.go @@ -0,0 +1,24 @@ +package netutil + +import ( + "fmt" + "net" +) + +// GetAllIpAddr 获取本机所有ip地址 +func GetAllIpAddr() []string { + addrs, err := net.InterfaceAddrs() + if err != nil { + fmt.Println(err) + return nil + } + var ipList []string + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + ipList = append(ipList, ipnet.IP.String()) + } + } + } + return ipList +} diff --git a/dbm-services/mysql/db-tools/dbactuator/go.mod b/dbm-services/mysql/db-tools/dbactuator/go.mod index 3f8483c119..9d0932bf75 100644 --- a/dbm-services/mysql/db-tools/dbactuator/go.mod +++ b/dbm-services/mysql/db-tools/dbactuator/go.mod @@ -3,6 +3,7 @@ module dbm-services/mysql/db-tools/dbactuator go 1.19 require ( + github.com/BurntSushi/toml v1.3.2 github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 github.com/dustin/go-humanize v1.0.1 github.com/go-sql-driver/mysql v1.7.1 diff --git a/dbm-services/mysql/db-tools/dbactuator/go.sum b/dbm-services/mysql/db-tools/dbactuator/go.sum index 5f61c466e9..703997c21b 100644 --- a/dbm-services/mysql/db-tools/dbactuator/go.sum +++ b/dbm-services/mysql/db-tools/dbactuator/go.sum @@ -1,3 +1,5 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go index fb238ae709..f1c2ff428b 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go @@ -46,6 +46,7 @@ func NewMysqlCommand() *cobra.Command { NewExecPartitionSQLCommand(), NewBackupDemandCommand(), NewDropTableCommand(), + InstallBackupClientCommand(), }, }, { diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/install_backup_client.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/install_backup_client.go new file mode 100644 index 0000000000..16908fc337 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/install_backup_client.go @@ -0,0 +1,98 @@ +package mysqlcmd + +import ( + "fmt" + + "dbm-services/common/go-pubpkg/logger" + "dbm-services/mysql/db-tools/dbactuator/internal/subcmd" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql" + "dbm-services/mysql/db-tools/dbactuator/pkg/util" + + "github.com/spf13/cobra" +) + +// InstallBackupClientAct TODO +type InstallBackupClientAct struct { + *subcmd.BaseOptions + Service mysql.InstallBackupClientComp +} + +// CommandInstallBackupClient TODO +const CommandInstallBackupClient = "install-backup-client" + +// InstallBackupClientCommand TODO +func InstallBackupClientCommand() *cobra.Command { + act := InstallBackupClientAct{ + BaseOptions: subcmd.GBaseOptions, + } + cmd := &cobra.Command{ + Use: CommandInstallBackupClient, + Short: "部署 backup_client", + Example: fmt.Sprintf( + `dbactuator mysql %s %s %s`, CommandInstallBackupClient, + subcmd.CmdBaseExampleStr, + subcmd.ToPrettyJson(act.Service.Example()), + ), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(act.Validate()) + if act.RollBack { + util.CheckErr(act.Rollback()) + return + } + util.CheckErr(act.Init()) + util.CheckErr(act.Run()) + }, + } + return cmd +} + +// Init TODO +func (d *InstallBackupClientAct) Init() (err error) { + if err = d.Deserialize(&d.Service.Params); err != nil { + logger.Error("DeserializeAndValidate err %s", err.Error()) + return err + } + d.Service.GeneralParam = subcmd.GeneralRuntimeParam + return nil +} + +// Run TODO +func (d *InstallBackupClientAct) Run() (err error) { + steps := subcmd.Steps{ + { + FunName: "init", + Func: d.Service.Init, + }, + { + FunName: "预检查", + Func: d.Service.PreCheck, + }, + { + FunName: "部署二进制", + Func: d.Service.DeployBinary, + }, + { + FunName: "渲染 config.toml", + Func: d.Service.GenerateBinaryConfig, + }, + { + FunName: "生成 cosinfo.toml", + Func: d.Service.GenerateBucketConfig, + }, + { + FunName: "添加 upload crontab", + Func: d.Service.InstallCrontab, + }, + } + + if err := steps.Run(); err != nil { + return err + } + logger.Info("install backup_client successfully~") + return nil +} + +// Rollback TODO +func (d *InstallBackupClientAct) Rollback() (err error) { + return +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_backup_client.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_backup_client.go new file mode 100644 index 0000000000..658b52f5d0 --- /dev/null +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/install_backup_client.go @@ -0,0 +1,173 @@ +package mysql + +import ( + "bytes" + "fmt" + "os" + "os/user" + "path/filepath" + + "github.com/pkg/errors" + + "github.com/BurntSushi/toml" + + "dbm-services/common/go-pubpkg/backupclient" + "dbm-services/common/go-pubpkg/cmutil" + "dbm-services/common/go-pubpkg/logger" + "dbm-services/common/go-pubpkg/netutil" + "dbm-services/mysql/db-tools/dbactuator/pkg/components" + "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/common" + "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" + "dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil" +) + +// InstallBackupClientComp 基本结构 +type InstallBackupClientComp struct { + GeneralParam *components.GeneralParam `json:"general"` + Params InstallBackupClientParam `json:"extend"` + configFile string + binPath string + installPath string +} + +// InstallBackupClientParam 输入参数 +type InstallBackupClientParam struct { + components.Medium + Config backupclient.CosClientConfig `json:"config" validate:"required"` // 模板配置 + CosInfo backupclient.CosInfo `json:"cosinfo" validate:"required"` + // 发起执行actor的用户,仅用于审计 + ExecUser string `json:"exec_user"` +} + +// Init 初始化 +func (c *InstallBackupClientComp) Init() (err error) { + c.installPath = cst.BackupClientInstallPath + c.binPath = filepath.Join(c.installPath, "bin/backup_client") + return nil +} + +// PreCheck 预检查 +func (c *InstallBackupClientComp) PreCheck() (err error) { + ipList := netutil.GetAllIpAddr() + if !cmutil.StringsHas(ipList, c.Params.Config.Cfg.NetAddr) { + return errors.Errorf("ipaddr %s is not in host net address list", c.Params.Config.Cfg.NetAddr) + } + if err = c.Params.Medium.Check(); err != nil { + logger.Error("check backup_client pkg failed: %s", err.Error()) + return err + } + return nil +} + +// DeployBinary 部署 backup_client 二进制 +func (c *InstallBackupClientComp) DeployBinary() (err error) { + decompressCmd := fmt.Sprintf( + `tar zxf %s -C %s`, + c.Params.Medium.GetAbsolutePath(), "/usr/local", + ) + _, err = osutil.ExecShellCommand(false, decompressCmd) + if err != nil { + logger.Error("decompress backup_client pkg failed: %s", err.Error()) + return err + } + chownCmd := fmt.Sprintf(`chown -R root.root %s && chmod +x %s`, c.installPath, c.binPath) + _, err = osutil.ExecShellCommand(false, chownCmd) + if err != nil { + logger.Error("chown %s to root failed: %s", c.installPath, err.Error()) + return err + } + return nil +} + +// GenerateBinaryConfig 生成 mysql-rotatebinlog 配置文件 +func (c *InstallBackupClientComp) GenerateBinaryConfig() (err error) { + c.configFile = filepath.Join(c.installPath, "conf/config.toml") + buf := bytes.NewBuffer([]byte{}) + if err = toml.NewEncoder(buf).Encode(&c.Params.Config); err != nil { + return errors.Wrapf(err, "write config file") + } + + if err := os.WriteFile(c.configFile, buf.Bytes(), 0644); err != nil { + return err + } + return nil +} + +func (c *InstallBackupClientComp) GenerateBucketConfig() (err error) { + mysqlUser, err := user.Lookup("mysql") + if err != nil { + return err + } + userHome := mysqlUser.HomeDir + if userHome != "" && cmutil.IsDirectory(userHome) { + + } + configFile := filepath.Join(userHome, ".cosinfo.toml") + buf := bytes.NewBuffer([]byte{}) + if err := toml.NewEncoder(buf).Encode(&c.Params.CosInfo); err != nil { + return err + } + if err := os.WriteFile(configFile, buf.Bytes(), 0644); err != nil { + return err + } + return nil +} + +// InstallCrontab 注册crontab +func (c *InstallBackupClientComp) InstallCrontab() (err error) { + err = osutil.RemoveSystemCrontab("backup_client upload") + if err != nil { + logger.Error("remove old 'backup_client upload' crontab failed: %s", err.Error()) + return err + } + uploadCrontabCmd := fmt.Sprintf("%s addcrontab -u root >/dev/null", c.binPath) + str, err := osutil.ExecShellCommand(false, uploadCrontabCmd) + if err != nil { + logger.Error( + "failed add '%s' to crond: %s(%s)", uploadCrontabCmd, str, err.Error(), + ) + } + return err +} + +// Example 样例 +func (c *InstallBackupClientComp) Example() interface{} { + return InstallBackupClientComp{ + GeneralParam: &components.GeneralParam{ + RuntimeAccountParam: components.RuntimeAccountParam{ + MySQLAccountParam: common.AccountMonitorExample, + }, + }, + Params: InstallBackupClientParam{ + Medium: components.Medium{ + Pkg: "backup_client.tar.gz", + PkgMd5: "12345", + }, + Config: backupclient.CosClientConfig{ + Base: backupclient.BaseLimit{ + BlockSize: 100, + LocalFileLimit: 100, + LocalTotalLimit: 100, + }, + Cfg: backupclient.UploadConfig{ + FileTagAllowed: "MYSQL_FULL_BACKUP,REDIS_FULL....", + NetAddr: "x.x.x.x", + }, + }, + CosInfo: backupclient.CosInfo{ + Cos: &backupclient.CosAuth{ + Region: "xxx", + BucketName: "yyy", + SecretId: "sid encrypted", + SecretKey: "skey encrypted", + CosServer: "urlxxx", + }, + AppAttr: &backupclient.AppAttr{ + BkBizId: 3, + BkCloudId: 0, + }, + }, + ExecUser: "sys", + }, + } +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/mysql.go b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/mysql.go index bfb6f15d82..7a3f885b81 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/mysql.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/mysql.go @@ -58,7 +58,8 @@ const ( // MysqlRotateBinlogInstallPath rotate binlog MysqlRotateBinlogInstallPath = "/home/mysql/mysql-rotatebinlog" // DBAReportBase 上报根目录 - DBAReportBase = "/home/mysql/dbareport" + DBAReportBase = "/home/mysql/dbareport" + BackupClientInstallPath = "/usr/local/backup_client" ) const ( diff --git a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/report.go b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/report.go index 2ec790a2fa..0b564456f0 100644 --- a/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/report.go +++ b/dbm-services/mysql/db-tools/mysql-dbbackup/pkg/src/dbareport/report.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "dbm-services/common/go-pubpkg/backupclient" "dbm-services/common/go-pubpkg/cmutil" "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" "dbm-services/mysql/db-tools/mysql-dbbackup/pkg/config" @@ -120,6 +121,24 @@ func (r *Reporter) ReportBackupStatus(status string) error { // ExecuteBackupClient execute backup_client which sends files to backup system func (r *Reporter) ExecuteBackupClient(fileName string) (taskid string, err error) { + if r.cfg.BackupClient.Enable { + backupClient, err := backupclient.New("", "", r.cfg.BackupClient.FileTag) + if err != nil { + return "", err + } + logger.Log.Infof("upload register file %s", fileName) + taskid, err = backupClient.Upload(fileName) + if err != nil { + return "", err + } + } else { + taskid = "-1" + } + return taskid, nil +} + +// ExecuteBackupClient2 execute backup_client which sends files to backup system +func (r *Reporter) ExecuteBackupClient2(fileName string) (taskid string, err error) { var checksumStr string var filesystemStr string if r.cfg.BackupClient.Enable { @@ -189,7 +208,8 @@ func (r *Reporter) ReportBackupResult(backupBaseResult BackupResult) error { if match { // execute backup_client, and send file to backup system var taskId string - if taskId, err = r.ExecuteBackupClient(entry.Name()); err != nil { + fileName := filepath.Join(r.cfg.Public.BackupDir, entry.Name()) + if taskId, err = r.ExecuteBackupClient(fileName); err != nil { return err } backupTaskResult := backupBaseResult diff --git a/dbm-services/mysql/db-tools/mysql-rotatebinlog/Makefile b/dbm-services/mysql/db-tools/mysql-rotatebinlog/Makefile index 4ac38012e2..e7335773f3 100644 --- a/dbm-services/mysql/db-tools/mysql-rotatebinlog/Makefile +++ b/dbm-services/mysql/db-tools/mysql-rotatebinlog/Makefile @@ -13,7 +13,8 @@ release: @CGO_ENABLE=0 GOARCH=amd64 GOOS=linux go build -ldflags ${RELEASE_BUILD_FLAG} -o ${OUTPUT_DIR}/${PROJ}/${PROJ_BIN} @cp config.example.yaml ${OUTPUT_DIR}/${PROJ}/config.yaml.example @tar -C ${OUTPUT_DIR} -zcf ${OUTPUT_DIR}/${PROJ_PKG} ${PROJ}/ - +release-bin: + @CGO_ENABLE=0 GOARCH=amd64 GOOS=linux go build -ldflags ${RELEASE_BUILD_FLAG} -o ${OUTPUT_DIR}/${PROJ}/${PROJ_BIN} .PHONY: beta beta: @cd ${BASE_DIR}/cmd && go build -ldflags ${BETA_BUILD_FLAG} -o ${OUTPUT_DIR}/${PROJ}/${PROJ_BIN} diff --git a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_cos.go b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_cos.go index 27aad2ba90..a23f550c45 100644 --- a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_cos.go +++ b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_cos.go @@ -1,20 +1,31 @@ package backup +import "dbm-services/common/go-pubpkg/backupclient" + // COSBackupClient TODO type COSBackupClient struct { + ToolPath string `mapstructure:"tool_path" json:"tool_path" validate:"required"` + FileTag string `mapstructure:"file_tag" json:"file_tag" validate:"required"` + AuthFile string `mapstructure:"auth_file" json:"auth_file"` + backupClient *backupclient.BackupClient } // Init TODO func (o *COSBackupClient) Init() error { + if backupClient, err := backupclient.New(o.ToolPath, o.AuthFile, o.FileTag); err != nil { + return err + } else { + o.backupClient = backupClient + } return nil } // Upload TODO func (o *COSBackupClient) Upload(fileName string) (string, error) { - return "123", nil + return o.backupClient.Upload(fileName) } // Query TODO func (o *COSBackupClient) Query(taskId string) (int, error) { - return 4, nil + return o.backupClient.Query(taskId) } diff --git a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_ibs.go b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_ibs.go index c671d55bc4..552d302db0 100644 --- a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_ibs.go +++ b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/backup_ibs.go @@ -6,11 +6,11 @@ import ( "strconv" "strings" + "github.com/pkg/errors" + + "dbm-services/common/go-pubpkg/cmutil" "dbm-services/common/go-pubpkg/logger" "dbm-services/common/go-pubpkg/validate" - "dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/util" - - "github.com/pkg/errors" ) const ( @@ -54,7 +54,7 @@ func (o *IBSBackupClient) Upload(fileName string) (taskId string, err error) { logger.Info("backup upload to ibs: %s", fileName) backupCmd := fmt.Sprintf(`%s -f %s`, o.ibsUploadCmd, fileName) var stdout, stderr string - if stdout, stderr, err = util.ExecCommand(true, "", backupCmd); err != nil { + if stdout, stderr, err = cmutil.ExecCommand(true, "", backupCmd); err != nil { return "", errors.Wrapf(err, "upload failed:%s", stderr) } reTaskId := regexp.MustCompile(`taskid:(\d+)`) @@ -74,7 +74,7 @@ func (o *IBSBackupClient) Query(taskid string) (taskStatus int, err error) { // queryCmd := fmt.Sprintf(`%s -q --taskid=%s`, o.IBSBackup, taskid) queryCmd := fmt.Sprintf(`%s -q --taskid %s`, o.ibsQueryCmd, taskid) var stdout, stderr string - if stdout, stderr, err = util.ExecCommand(true, "", queryCmd); err != nil { + if stdout, stderr, err = cmutil.ExecCommand(true, "", queryCmd); err != nil { return 0, errors.Wrapf(err, "query failed:%s", stderr) } outLines := strings.Split(stdout, "\n") diff --git a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/init.go b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/init.go index 4598a50c69..d13d230a3e 100644 --- a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/init.go +++ b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/backup/init.go @@ -26,11 +26,11 @@ func InitBackupClient() (backupClient BackupClient, err error) { if !viper.GetBool("backup_client.cos.enable") { continue } - var ibsClient COSBackupClient - if err := mapstructure.Decode(cfgClient, &ibsClient); err != nil { + var cosClient COSBackupClient + if err := mapstructure.Decode(cfgClient, &cosClient); err != nil { return nil, err } else { - backupClient = &ibsClient + backupClient = &cosClient } } else { logger.Error("unknown backup_client %s", name) diff --git a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/util/util.go b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/util/util.go index 3bec96317d..d6f7f87635 100644 --- a/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/util/util.go +++ b/dbm-services/mysql/db-tools/mysql-rotatebinlog/pkg/util/util.go @@ -2,19 +2,15 @@ package util import ( - "bytes" "fmt" - "os" - "os/exec" "regexp" "strconv" "strings" - "dbm-services/common/go-pubpkg/cmutil" - "dbm-services/common/go-pubpkg/logger" - "github.com/pkg/errors" "github.com/spf13/cast" + + "dbm-services/common/go-pubpkg/cmutil" ) // DiskDfResult disk df output @@ -52,7 +48,7 @@ func GetDiskPartitionWithDir(dirName string) (*DiskDfResult, error) { return nil, errors.New("df -m dirName should not be empty") } cmdArgs := []string{"-m", dirName} - stdout, stderr, err := ExecCommand(false, "df", cmdArgs...) + stdout, stderr, err := cmutil.ExecCommand(false, "df", cmdArgs...) if err != nil { return nil, errors.Wrapf(err, "dir:%s, err:%+v", dirName, stderr) } @@ -87,7 +83,7 @@ func GetDirectorySizeMB(binlogDir string) (int64, error) { */ // cmdArgs := fmt.Sprintf("-sm %s", binlogDir) // du -sh /xx cmdArgs := []string{"-sm", binlogDir} - stdout, stderr, err := ExecCommand(false, "du", cmdArgs...) + stdout, stderr, err := cmutil.ExecCommand(false, "du", cmdArgs...) errStr := strings.SplitN(stderr, "\n", 1)[0] if err != nil { if strings.Contains(stdout, binlogDir) && strings.Contains(stderr, "lost+found") { @@ -113,38 +109,3 @@ func squashSpace(ss string) string { reSpaces := regexp.MustCompile(`\s+`) return reSpaces.ReplaceAllString(ss, " ") } - -// ExecCommand bash=true: bash -c 'cmdName args', bash=false: ./cmdName args list -// ExecCommand(false, "df", "-k /data") will get `df '-k /data'` error command. you need change it to (false, "df", "-k", "/data") or (true, "df -k /data") -// bash=false need PATH -func ExecCommand(bash bool, cmdName string, args ...string) (string, string, error) { - var cmd *exec.Cmd - if bash { - if cmdName != "" { - cmdName += " " - } - cmdStr := fmt.Sprintf(`%s%s`, cmdName, strings.Join(args, " ")) - cmd = exec.Command("bash", "-c", cmdStr) - } else { - if cmdName == "" { - return "", "", errors.Errorf("command name should not be empty:%v", args) - } - // args should be list - cmd = exec.Command(cmdName, args...) - } - cmd.Env = []string{ - fmt.Sprintf( - "PATH=%s:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin", - os.Getenv("PATH"), - ), - } - //logger.Info("PATH:%s cmd.Env:%v", os.Getenv("PATH"), cmd.Env) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - logger.Error("stdout:%s, stderr:%s, cmd:%s", stdout.String(), stderr.String(), cmd.String()) - return stdout.String(), stdout.String(), errors.Wrap(err, cmd.String()) - } - return stdout.String(), stderr.String(), nil -} From 3f9bc20d62f3cd7e488f87f9277356fde3b0e88e Mon Sep 17 00:00:00 2001 From: lukemakeit <2302063437@qq.com> Date: Fri, 14 Jul 2023 17:03:48 +0800 Subject: [PATCH 151/476] =?UTF-8?q?fix(redis):=20=E4=BC=98=E5=8C=96redis?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB=E4=B8=AD=20tb=5Ftendis=5Fd?= =?UTF-8?q?ts=5Fjob=E7=9A=84=E5=AE=9A=E4=B9=89=20#501?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db_services/redis_dts/constants.py | 67 ---------- .../db_services/redis_dts/enums/__init__.py | 23 ++++ .../db_services/redis_dts/enums/type_enums.py | 124 ++++++++++++++++++ .../redis_dts/models/tb_tendis_dts_job.py | 84 ++++++------ .../redis_dts/models/tb_tendis_dts_task.py | 9 +- dbm-ui/backend/db_services/redis_dts/util.py | 2 +- .../bamboo/scene/redis/atom_jobs/redis_dts.py | 2 +- .../redis/redis_cluster_data_check_repair.py | 10 +- .../scene/redis/redis_cluster_data_copy.py | 10 +- .../components/collections/redis/redis_dts.py | 44 ++++--- .../builders/redis/redis_toolbox_data_copy.py | 2 +- 11 files changed, 234 insertions(+), 143 deletions(-) create mode 100644 dbm-ui/backend/db_services/redis_dts/enums/__init__.py create mode 100644 dbm-ui/backend/db_services/redis_dts/enums/type_enums.py diff --git a/dbm-ui/backend/db_services/redis_dts/constants.py b/dbm-ui/backend/db_services/redis_dts/constants.py index 85e4c3197d..85028c5951 100644 --- a/dbm-ui/backend/db_services/redis_dts/constants.py +++ b/dbm-ui/backend/db_services/redis_dts/constants.py @@ -46,73 +46,6 @@ class DtsOperateType(str, StructuredEnum): FORCE_KILL_SUCC = EnumField("ForceKillTaskSucc", _("强制暂停任务成功")) -class DtsCopyType(str, StructuredEnum): - """DTS 数据复制 类型""" - - REDIS_CLUSTER_SHARD_NUM_UPDATE = EnumField("REDIS_CLUSTER_SHARD_NUM_UPDATE", _("redis集群分片数变更")) - REDIS_CLUSTER_TYPE_UPDATE = EnumField("REDIS_CLUSTER_TYPE_UPDATE", _("redis集群类型变更")) - REDIS_CLUSTER_DATA_COPY = EnumField("REDIS_CLUSTER_DATA_COPY", _("redis集群数据复制")) - - ONE_APP_DIFF_CLUSTER = EnumField("one_app_diff_cluster", _("同一业务不同集群")) - DIFF_APP_DIFF_CLUSTER = EnumField("diff_app_diff_cluster", _("不同业务不同集群")) - COPY_TO_OTHER_SYSTEM = EnumField("copy_to_other_system", _("复制到其他系统")) - COPY_FROM_ROLLBACK_INSTANCE = EnumField("copy_from_rollback_instance", _("从回档实例复制数据")) - USER_BUILT_TO_DBM = EnumField("user_built_to_dbm", _("用户自建redis迁移到DBM")) - - -class DTS_ONLINE_SWITCH_TYPE(str, StructuredEnum): - """DTS在线切换类型""" - - AUTO = EnumField("auto", _("自动切换")) - USER_CONFIRM = EnumField("user_confirm", _("用户确认切换")) - - -class DtsCommonsVarS(str, StructuredEnum): - """DTS公共变量""" - - # 数据修复模式 - AUTO_REPAIR = EnumField("auto_repair", _("自动修复")) - MANUAL_CONFIRM = EnumField("manual_confirm", _("用户确认")) - - AUTO_EXECUTION = EnumField("auto_execution", _("自动执行")) - SCHEDULED_EXECUTION = EnumField("scheduled_execution", _("定时执行")) - - AUTO_DISCONNECT_AFTER_REPLICATION = EnumField("auto_disconnect_after_replication", _("复制完成后自动断开同步关系")) - KEEP_SYNC_WITH_REMINDER = EnumField("keep_sync_with_reminder", _("复制完成后保持同步关系,定时发送断开同步提醒")) - - # 校验修复类型 - DATA_CHECK_AND_REPAIR = EnumField("data_check_and_repair", _("数据校验并修复")) - DATA_CHECK_ONLY = EnumField("data_check_only", _("仅进行数据校验,不进行修复")) - NO_CHECK_NO_REPAIR = EnumField("no_check_no_repair", _("不校验不修复")) - - # 频率 - ONCE_AFTER_REPLICATION = EnumField("once_after_replication", _("复制完成后执行一次")) - ONCE_DAILY = EnumField("once_daily", _("每天一次")) - ONCE_EVERY_THREE_DAYS = EnumField("once_every_three_days", _("每三天一次")) - ONCE_WEEKLY = EnumField("once_weekly", _("每周一次")) - - # 写入模式 - DELETE_AND_WRITE_TO_REDIS = EnumField( - "delete_and_write_to_redis", _("先删除同名redis key, 再执行写入 (如: del $key + hset $key)") - ) - KEEP_AND_APPEND_TO_REDIS = EnumField("keep_and_append_to_redis", _("保留同名redis key, 追加写入 (如: hset $key)")) - FLUSHALL_AND_WRITE_TO_REDIS = EnumField("flushall_and_write_to_redis", _("先清空目标集群所有数据,在写入")) - - -class TimeoutVars(str, StructuredEnum): - """ - 超时时间 - """ - - NEVER = EnumField("never", _("永不超时")) - ONE_HOUR = EnumField("1hour", _("1小时")) - THREE_HOURS = EnumField("3hours", _("3小时")) - SIX_HOURS = EnumField("6hours", _("6小时")) - ONE_DAY = EnumField("1day", _("1天")) - TWO_DAYS = EnumField("2days", _("2天")) - ONE_WEEK = EnumField("1week", _("1周")) - - # DTS在线切换twemproxy前置检查脚本 DTS_SWITCH_TWEMPROXY_PRECHECK = """ srcProxyIP={{SRC_PROXY_IP}} diff --git a/dbm-ui/backend/db_services/redis_dts/enums/__init__.py b/dbm-ui/backend/db_services/redis_dts/enums/__init__.py new file mode 100644 index 0000000000..bcd96e7b04 --- /dev/null +++ b/dbm-ui/backend/db_services/redis_dts/enums/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from .type_enums import ( + DtsBillType, + DtsCopyType, + DtsDataCheckFreq, + DtsDataCheckType, + DtsDataRepairMode, + DtsOnlineSwitchType, + DtsSyncDisconnReminderFreq, + DtsSyncDisconnType, + DtsWriteMode, + ExecuteMode, + TimeoutVars, +) diff --git a/dbm-ui/backend/db_services/redis_dts/enums/type_enums.py b/dbm-ui/backend/db_services/redis_dts/enums/type_enums.py new file mode 100644 index 0000000000..ad9923911e --- /dev/null +++ b/dbm-ui/backend/db_services/redis_dts/enums/type_enums.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from blue_krill.data_types.enum import EnumField, StructuredEnum +from django.utils.translation import gettext_lazy as _ + + +class DtsBillType(str, StructuredEnum): + """ + DTS单据类型 + """ + + REDIS_CLUSTER_SHARD_NUM_UPDATE = EnumField("REDIS_CLUSTER_SHARD_NUM_UPDATE", _("集群节点数变更")) + REDIS_CLUSTER_TYPE_UPDATE = EnumField("REDIS_CLUSTER_TYPE_UPDATE", _("集群类型变更")) + REDIS_CLUSTER_DATA_COPY = EnumField("REDIS_CLUSTER_DATA_COPY", _("集群数据复制")) + + +class DtsCopyType(str, StructuredEnum): + """ + DTS数据复制类型(此时 dts_bill_type=REDIS_CLUSTER_DATA_COPY) + """ + + ONE_APP_DIFF_CLUSTER = EnumField("one_app_diff_cluster", _("同一业务不同集群")) + DIFF_APP_DIFF_CLUSTER = EnumField("diff_app_diff_cluster", _("不同业务不同集群")) + COPY_FROM_ROLLBACK_TEMP = EnumField("copy_from_rollback_temp", _("从回滚临时环境复制数据")) + COPY_TO_OTHER_SYSTEM = EnumField("copy_to_other_system", _("同步到其他系统,如迁移到腾讯云")) + USER_BUILT_TO_DBM = EnumField("user_built_to_dbm", _("业务自建迁移到dbm系统")) + COPY_FROM_ROLLBACK_INSTANCE = EnumField("copy_from_rollback_instance", _("从回档实例复制数据")) + + +class DtsWriteMode(str, StructuredEnum): + """ + 写入模式 + """ + + DELETE_AND_WRITE_TO_REDIS = EnumField( + "delete_and_write_to_redis", _("先删除同名redis key, 再执行写入(如:del $key + hset $key)") + ) + KEEP_AND_APPEND_TO_REDIS = EnumField("keep_and_append_to_redis", _("保留同名redis key,追加写入(如hset $key)")) + FLUSHALL_AND_WRITE_TO_REDIS = EnumField("flushall_and_write_to_redis", _("先清空目标集群所有数据,在写入(如flushall + hset $key)")) + + +class ExecuteMode(str, StructuredEnum): + """ + 执行模式 + """ + + AUTO_EXECUTION = EnumField("auto_execution", _("自动执行")) + SCHEDULED_EXECUTION = EnumField("scheduled_execution", _("定时执行")) + + +class DtsOnlineSwitchType(str, StructuredEnum): + """DTS在线切换类型""" + + AUTO_SWITCH = EnumField("auto_switch", _("自动切换")) + MANUAL_CONFIRM = EnumField("manual_confirm", _("用户确认切换")) + + +class DtsSyncDisconnType(str, StructuredEnum): + """ + 同步断开类型 + """ + + AUTO_DISCONNECT_AFTER_REPLICATION = EnumField("auto_disconnect_after_replication", _("复制完成后自动断开同步关系")) + KEEP_SYNC_WITH_REMINDER = EnumField("keep_sync_with_reminder", _("复制完成后保持同步关系,定时发送断开同步提醒")) + + +class DtsSyncDisconnReminderFreq(str, StructuredEnum): + """ + Dts复制同步提醒频率 + """ + + ONCE_DAILY = EnumField("once_daily", _("每天一次")) + ONCE_WEEKLY = EnumField("once_weekly", _("每周一次")) + + +class DtsDataCheckType(str, StructuredEnum): + """ + 数据校验修复类型 + """ + + DATA_CHECK_AND_REPAIR = EnumField("data_check_and_repair", _("数据校验并修复")) + DATA_CHECK_ONLY = EnumField("data_check_only", _("仅进行数据校验,不进行修复")) + NO_CHECK_NO_REPAIR = EnumField("no_check_no_repair", _("不校验不修复")) + + +class DtsDataCheckFreq(str, StructuredEnum): + """ + Dts数据校验修复频率 + """ + + ONCE_AFTER_REPLICATION = EnumField("once_after_replication", _("复制完成后执行一次")) + ONCE_EVERY_THREE_DAYS = EnumField("once_every_three_days", _("每三天一次")) + ONCE_WEEKLY = EnumField("once_weekly", _("每周一次")) + + +class DtsDataRepairMode(str, StructuredEnum): + """ + Dts数据修复模式 + """ + + AUTO_REPAIR = EnumField("auto_repair", _("自动修复")) + MANUAL_CONFIRM = EnumField("manual_confirm", _("用户确认")) + + +class TimeoutVars(str, StructuredEnum): + """ + 超时时间 + """ + + NEVER = EnumField("never", _("永不超时")) + ONE_HOUR = EnumField("1hour", _("1小时")) + THREE_HOURS = EnumField("3hours", _("3小时")) + SIX_HOURS = EnumField("6hours", _("6小时")) + ONE_DAY = EnumField("1day", _("1天")) + TWO_DAYS = EnumField("2days", _("2天")) + ONE_WEEK = EnumField("1week", _("1周")) diff --git a/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_job.py b/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_job.py index 7260cb914b..997c6c74ff 100644 --- a/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_job.py +++ b/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_job.py @@ -11,6 +11,17 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from backend.db_services.redis_dts.enums import ( + DtsBillType, + DtsCopyType, + DtsDataCheckFreq, + DtsDataCheckType, + DtsOnlineSwitchType, + DtsSyncDisconnReminderFreq, + DtsSyncDisconnType, + DtsWriteMode, +) + class TbTendisDTSJob(models.Model): id = models.BigAutoField(primary_key=True) @@ -18,46 +29,39 @@ class TbTendisDTSJob(models.Model): app = models.CharField(max_length=64, default="", verbose_name=_("业务bk_biz_id")) bk_cloud_id = models.BigIntegerField(default=0, verbose_name=_("云区域id")) user = models.CharField(max_length=64, default="", verbose_name=_("申请人")) - # DTS单据类型, 值如下: - # - REDIS_CLUSTER_SHARD_NUM_UPDATE(集群节点数变更) - # - REDIS_CLUSTER_TYPE_UPDATE(集群类型变更) - # - REDIS_CLUSTER_DATA_COPY(集群数据复制) - dts_bill_type = models.CharField(max_length=64, default="", verbose_name=_("DTS单据类型")) - # DTS数据复制类型, 值如下(此时 dts_bill_type=REDIS_CLUSTER_DATA_COPY): - # - one_app_diff_cluster(同一业务不同集群) - # - diff_app_diff_cluster(不同业务不同集群) - # - copy_from_rollback_temp(从回滚临时环境复制数据) - # - copy_to_other_system(同步到其他系统,如迁移到腾讯云) - # - user_built_to_dbm(业务自建迁移到dbm系统) - dts_copy_type = models.CharField(max_length=64, default="", verbose_name=_("DTS数据复制类型")) - # 写入模式,值包括 - # - delete_and_write_to_redis 先删除同名redis key, 再执行写入 (如: del $key + hset $key) - # - keep_and_append_to_redis 保留同名redis key,追加写入 - # - flushall_and_write_to_redis 先清空目标集群所有数据,在写入 - write_mode = models.CharField(max_length=64, default="", verbose_name=_("写入模式")) - # DTS 在线切换类型,值包括 - # - auto(自动切换) - # - manual_confirm(用户确认切换) - online_switch_type = models.CharField(max_length=64, default="", verbose_name=_("在线切换类型")) - # DTS 同步断开类型,值包括 - # - auto_disconnect_after_replication: 数据复制完成后自动断开同步关系 - # - keep_sync_with_reminder: 数据复制完成后保持同步关系,定时发送断开同步提醒 - sync_disconnect_type = models.CharField(max_length=64, default="", verbose_name=_("同步断开类型")) - # DTS 同步断开提醒频率,值包括 - # - once_daily - # - once_weekly - sync_disconnect_reminder_frequency = models.CharField(max_length=64, default="", verbose_name=_("同步断开提醒频率")) - - # DTS 数据校验修复类型,值包括 - # - data_check_and_repair: 数据校验并修复 - # - data_check_only: 数据校验 - # - no_check_no_repair: 不校验不修复 - data_check_repair_type = models.CharField(max_length=64, default="", verbose_name=_("数据校验修复类型")) - # DTS 数据校验修复执行频率,值包括 - # - once_after_replication - # - once_every_three_days - # - once_weekly - data_check_repair_execution_frequency = models.CharField(max_length=64, default="", verbose_name=_("数据校验修复执行频率")) + dts_bill_type = models.CharField( + max_length=64, choices=DtsBillType.get_choices(), default="", verbose_name=_("DTS单据类型") + ) + dts_copy_type = models.CharField( + max_length=64, choices=DtsCopyType.get_choices(), default="", verbose_name=_("DTS数据复制类型") + ) + write_mode = models.CharField( + max_length=64, choices=DtsWriteMode.get_choices(), default="", verbose_name=_("写入模式") + ) + online_switch_type = models.CharField( + max_length=64, + choices=DtsOnlineSwitchType.get_choices(), + default=DtsOnlineSwitchType.MANUAL_CONFIRM, + verbose_name=_("在线切换类型"), + ) + sync_disconnect_type = models.CharField( + max_length=64, choices=DtsSyncDisconnType.get_choices(), default="", verbose_name=_("同步断开类型") + ) + sync_disconnect_reminder_frequency = models.CharField( + max_length=64, choices=DtsSyncDisconnReminderFreq.get_choices(), default="", verbose_name=_("同步断开提醒频率") + ) + data_check_repair_type = models.CharField( + max_length=64, + choices=DtsDataCheckType.get_choices(), + default=DtsDataCheckType.DATA_CHECK_AND_REPAIR, + verbose_name=_("数据校验修复类型"), + ) + data_check_repair_execution_frequency = models.CharField( + max_length=64, + choices=DtsDataCheckFreq.get_choices(), + default=DtsDataCheckFreq.ONCE_AFTER_REPLICATION, + verbose_name=_("数据校验修复执行频率"), + ) # 最近一次数据校验与修复 flow id last_data_check_repair_flow_id = models.CharField(max_length=64, default="", verbose_name=_("最近一次数据校验与修复 flow id")) # 最近一次数据校验与修复 单据执行时间 diff --git a/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_task.py b/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_task.py index 5f7ae3605f..69f62cbe50 100644 --- a/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_task.py +++ b/dbm-ui/backend/db_services/redis_dts/models/tb_tendis_dts_task.py @@ -11,6 +11,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from backend.db_services.redis_dts.enums import DtsWriteMode from backend.utils.time import datetime2str @@ -21,11 +22,9 @@ class TbTendisDtsTask(models.Model): app = models.CharField(max_length=64, default="", verbose_name=_("业务bk_biz_id")) bk_cloud_id = models.BigIntegerField(default=0, verbose_name=_("云区域id")) dts_server = models.CharField(max_length=128, default="", verbose_name=_("执行迁移任务的dts_server")) - # 写入模式,值包括 - # - delete_and_write_to_redis 先删除同名redis key, 再执行写入 (如: del $key + hset $key) - # - keep_and_append_to_redis 保留同名redis key,追加写入 - # - flushall_and_write_to_redis 先清空目标集群所有数据,在写入 - write_mode = models.CharField(max_length=64, default="", verbose_name=_("写入模式")) + write_mode = models.CharField( + max_length=64, choices=DtsWriteMode.get_choices(), default="", verbose_name=_("写入模式") + ) src_cluster = models.CharField(max_length=128, default="", verbose_name=_("源集群")) src_cluster_priority = models.IntegerField(default=0, verbose_name=_("源集群优先级,值越大,优先级越高")) src_ip = models.CharField(max_length=128, default="", verbose_name=_("源slave_ip")) diff --git a/dbm-ui/backend/db_services/redis_dts/util.py b/dbm-ui/backend/db_services/redis_dts/util.py index af3f4f1cfe..3fa149c632 100644 --- a/dbm-ui/backend/db_services/redis_dts/util.py +++ b/dbm-ui/backend/db_services/redis_dts/util.py @@ -19,7 +19,7 @@ from backend.components.dbconfig.constants import FormatType, LevelName from backend.db_meta.enums import ClusterType, InstanceRole, InstanceStatus from backend.db_meta.models import Cluster -from backend.db_services.redis_dts.constants import DtsCopyType, DtsTaskType +from backend.db_services.redis_dts.enums import DtsCopyType from backend.flow.consts import DEFAULT_TENDISPLUS_KVSTORECOUNT, GB, MB, ConfigTypeEnum from backend.flow.utils.redis.redis_cluster_nodes import get_masters_with_slots from backend.flow.utils.redis.redis_context_dataclass import ActKwargs diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dts.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dts.py index b40bb81f4e..2c4fde0d14 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dts.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/atom_jobs/redis_dts.py @@ -16,7 +16,7 @@ from django.utils.translation import ugettext as _ from backend.configuration.constants import DBType -from backend.db_services.redis_dts.constants import DtsCopyType +from backend.db_services.redis_dts.enums import DtsCopyType from backend.flow.consts import RedisBackupEnum, WriteContextOpType from backend.flow.engine.bamboo.scene.common.builder import SubBuilder from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_check_repair.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_check_repair.py index 9749ee3b7b..6421e1f6fa 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_check_repair.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_check_repair.py @@ -17,7 +17,7 @@ from django.utils.translation import ugettext as _ from backend.configuration.constants import DBType -from backend.db_services.redis_dts.constants import DtsCommonsVarS +from backend.db_services.redis_dts.enums import DtsDataRepairMode, ExecuteMode from backend.db_services.redis_dts.models.tb_tendis_dts_job import TbTendisDTSJob from backend.db_services.redis_dts.models.tb_tendis_dts_task import TbTendisDtsTask from backend.flow.engine.bamboo.scene.common.builder import Builder, SubBuilder @@ -52,7 +52,7 @@ def redis_cluster_data_check_repair_flow(self): for info in self.data["infos"]: sub_pipeline = SubBuilder(root_id=self.root_id, data={**self.data, **execution_time}) - if self.data["execute_mode"] == DtsCommonsVarS.SCHEDULED_EXECUTION: + if self.data["execute_mode"] == ExecuteMode.SCHEDULED_EXECUTION: # 定时执行 sub_pipeline.add_act( act_name=_("定时"), @@ -89,7 +89,7 @@ def redis_cluster_data_check_repair_flow(self): sub_pipeline.add_parallel_acts(acts_list) if self.data["data_repair_enabled"]: - if self.data["repair_mode"] == DtsCommonsVarS.MANUAL_CONFIRM: + if self.data["repair_mode"] == DtsDataRepairMode.MANUAL_CONFIRM: # 人工确认 sub_pipeline.add_act(act_name=_("数据修复人工确认"), act_component_code=PauseComponent.code, kwargs={}) @@ -115,9 +115,9 @@ def redis_cluster_data_check_repair_flow(self): return redis_pipeline.run_pipeline() def __get_exection_time(self) -> dict: - if self.data["execute_mode"] == DtsCommonsVarS.AUTO_EXECUTION: + if self.data["execute_mode"] == ExecuteMode.AUTO_EXECUTION: return {} - elif self.data["execute_mode"] == DtsCommonsVarS.SCHEDULED_EXECUTION: + elif self.data["execute_mode"] == ExecuteMode.SCHEDULED_EXECUTION: return {"timing": self.data["specified_execution_time"]} def __get_dts_job_data(self, info: dict) -> dict: diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_copy.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_copy.py index 8e2fa0fa42..4077145cfa 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_copy.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_data_copy.py @@ -14,7 +14,7 @@ from django.utils.translation import ugettext as _ from backend.configuration.constants import DBType -from backend.db_services.redis_dts.constants import DtsCommonsVarS, DtsCopyType +from backend.db_services.redis_dts.enums import DtsBillType, DtsCopyType, DtsWriteMode from backend.db_services.redis_dts.util import complete_redis_dts_kwargs_dst_data, complete_redis_dts_kwargs_src_data from backend.flow.engine.bamboo.scene.common.builder import Builder from backend.flow.engine.bamboo.scene.common.get_file_list import GetFileList @@ -56,7 +56,7 @@ def redis_cluster_data_copy_flow(self): if ( dts_copy_type != DtsCopyType.COPY_TO_OTHER_SYSTEM - and write_mode == DtsCommonsVarS.FLUSHALL_AND_WRITE_TO_REDIS + and write_mode == DtsWriteMode.FLUSHALL_AND_WRITE_TO_REDIS ): redis_pipeline.add_sub_pipeline(RedisDtsDstClusterBackupAndFlush(self.root_id, self.data, act_kwargs)) @@ -66,8 +66,8 @@ def redis_cluster_data_copy_flow(self): def __get_dts_copy_type(self) -> str: if self.data["ticket_type"] in [ - DtsCopyType.REDIS_CLUSTER_SHARD_NUM_UPDATE.value, - DtsCopyType.REDIS_CLUSTER_TYPE_UPDATE.value, + DtsBillType.REDIS_CLUSTER_SHARD_NUM_UPDATE.value, + DtsBillType.REDIS_CLUSTER_TYPE_UPDATE.value, ]: return "" else: @@ -75,7 +75,7 @@ def __get_dts_copy_type(self) -> str: def __get_dts_biz_id(self, info: dict) -> int: if ( - self.data["ticket_type"] == DtsCopyType.REDIS_CLUSTER_DATA_COPY + self.data["ticket_type"] == DtsBillType.REDIS_CLUSTER_DATA_COPY and self.data["dts_copy_type"] == DtsCopyType.DIFF_APP_DIFF_CLUSTER ): return info["dst_bk_biz_id"] diff --git a/dbm-ui/backend/flow/plugins/components/collections/redis/redis_dts.py b/dbm-ui/backend/flow/plugins/components/collections/redis/redis_dts.py index 48e07f417a..1393bbfc8f 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/redis/redis_dts.py +++ b/dbm-ui/backend/flow/plugins/components/collections/redis/redis_dts.py @@ -26,11 +26,15 @@ from backend.components import DBConfigApi, DRSApi from backend.db_meta.enums import ClusterType, InstanceStatus from backend.db_meta.models import Cluster -from backend.db_services.redis_dts.constants import ( - DtsCommonsVarS, +from backend.db_services.redis_dts.constants import DtsOperateType, DtsTaskType +from backend.db_services.redis_dts.enums import ( DtsCopyType, - DtsOperateType, - DtsTaskType, + DtsDataCheckFreq, + DtsDataCheckType, + DtsDataRepairMode, + DtsSyncDisconnReminderFreq, + DtsSyncDisconnType, + ExecuteMode, TimeoutVars, ) from backend.db_services.redis_dts.models.tb_tendis_dts_job import TbTendisDTSJob @@ -622,10 +626,10 @@ def __is_check_time_interval_satisfied(self, execution_frequency: str, last_exec 判断是否满足校验时间间隔 """ current_time = datetime.datetime.now() - if execution_frequency == DtsCommonsVarS.ONCE_EVERY_THREE_DAYS: + if execution_frequency == DtsDataCheckFreq.ONCE_EVERY_THREE_DAYS: if (current_time - last_execute_time).days < 3: return False - if execution_frequency == DtsCommonsVarS.ONCE_WEEKLY: + if execution_frequency == DtsDataCheckFreq.ONCE_WEEKLY: if (current_time - last_execute_time).days < 7: return False return True @@ -634,14 +638,14 @@ def __is_able_to_new_check_repair(self, global_data: dict, dts_job: TbTendisDTSJ """ 判断是否可以进行数据校验修复 """ - if global_data["data_check_repair_setting"]["type"] == DtsCommonsVarS.NO_CHECK_NO_REPAIR: + if global_data["data_check_repair_setting"]["type"] == DtsDataCheckType.NO_CHECK_NO_REPAIR: return False - if global_data["sync_disconnect_setting"]["type"] == DtsCommonsVarS.AUTO_DISCONNECT_AFTER_REPLICATION: + if global_data["sync_disconnect_setting"]["type"] == DtsSyncDisconnType.AUTO_DISCONNECT_AFTER_REPLICATION: if dts_job.last_data_check_repair_flow_id == "": return True - if global_data["sync_disconnect_setting"]["type"] == DtsCommonsVarS.KEEP_SYNC_WITH_REMINDER: + if global_data["sync_disconnect_setting"]["type"] == DtsSyncDisconnType.KEEP_SYNC_WITH_REMINDER: if dts_job.last_data_check_repair_flow_id == "": # 第一次发起校验修复 return True @@ -652,7 +656,7 @@ def __is_able_to_new_check_repair(self, global_data: dict, dts_job: TbTendisDTSJ # 上次校验修复已完成 if ( global_data["data_check_repair_setting"]["execution_frequency"] - == DtsCommonsVarS.ONCE_AFTER_REPLICATION + == DtsDataCheckFreq.ONCE_AFTER_REPLICATION ): # 复制完成后执行一次校验修复 return False @@ -669,9 +673,11 @@ def __is_able_to_disconnect(self, global_data: dict, dts_job: TbTendisDTSJob) -> """ if global_data["sync_disconnect_setting"][ "type" - ] == DtsCommonsVarS.AUTO_DISCONNECT_AFTER_REPLICATION and global_data["data_check_repair_setting"]["type"] in [ - DtsCommonsVarS.DATA_CHECK_AND_REPAIR, - DtsCommonsVarS.DATA_CHECK_ONLY, + ] == DtsSyncDisconnType.AUTO_DISCONNECT_AFTER_REPLICATION and global_data["data_check_repair_setting"][ + "type" + ] in [ + DtsDataCheckType.DATA_CHECK_AND_REPAIR, + DtsDataCheckType.DATA_CHECK_ONLY, ]: # 复制完成后自动断开同步关系,并且需要进行数据校验修复,则需要等待数据校验修复完成后再断开同步关系 if dts_job.last_data_check_repair_flow_id != "": @@ -681,8 +687,8 @@ def __is_able_to_disconnect(self, global_data: dict, dts_job: TbTendisDTSJob) -> return False if ( - global_data["sync_disconnect_setting"]["type"] == DtsCommonsVarS.AUTO_DISCONNECT_AFTER_REPLICATION - and global_data["data_check_repair_setting"]["type"] == DtsCommonsVarS.NO_CHECK_NO_REPAIR + global_data["sync_disconnect_setting"]["type"] == DtsSyncDisconnType.AUTO_DISCONNECT_AFTER_REPLICATION + and global_data["data_check_repair_setting"]["type"] == DtsDataCheckType.NO_CHECK_NO_REPAIR ): # 复制完成后自动断开同步关系,并且不需要进行数据校验修复,则可以直接断开同步关系 return True @@ -723,17 +729,19 @@ def __is_all_tasks_incr_sync(self, tasks: List[TbTendisDtsTask]) -> bool: return True def __new_data_check_repair_job(self, global_data: dict, dts_job: TbTendisDTSJob): - repair_enabled: bool = global_data["data_check_repair_setting"]["type"] == DtsCommonsVarS.DATA_CHECK_AND_REPAIR + repair_enabled: bool = ( + global_data["data_check_repair_setting"]["type"] == DtsDataCheckType.DATA_CHECK_AND_REPAIR + ) ticket_data: dict = { "uid": global_data["uid"], "bk_biz_id": global_data["bk_biz_id"], "created_by": global_data["created_by"], "ticket_type": TicketType.REDIS_DATACOPY_CHECK_REPAIR.value, - "execute_mode": DtsCommonsVarS.AUTO_EXECUTION.value, + "execute_mode": ExecuteMode.AUTO_EXECUTION.value, "specified_execution_time": "", "global_timeout": TimeoutVars.NEVER.value, "data_repair_enabled": repair_enabled, - "repair_mode": DtsCommonsVarS.AUTO_REPAIR.value, + "repair_mode": DtsDataRepairMode.AUTO_REPAIR.value, "infos": [ { "bill_id": dts_job.bill_id, diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_data_copy.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_data_copy.py index 897da8b3cb..ac9755341d 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_data_copy.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_data_copy.py @@ -13,7 +13,7 @@ from rest_framework import serializers from backend.db_services.dbbase.constants import IpSource -from backend.db_services.redis_dts.constants import DtsCopyType +from backend.db_services.redis_dts.enums import DtsCopyType from backend.ticket.builders.redis.base import DataCheckRepairSettingSerializer from backend.ticket.constants import RemindFrequencyType, SyncDisconnectSettingType, WriteModeType From fd40ea56b165cfb9f10825c50770fc3b28860dfe Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Fri, 14 Jul 2023 18:48:14 +0800 Subject: [PATCH 152/476] =?UTF-8?q?refactor(dbm-services):=20=E8=AE=B0?= =?UTF-8?q?=E5=BD=95sql=E6=89=A7=E8=A1=8C=E8=BF=87=E7=A8=8B=E5=88=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E5=B9=B6=E4=BC=98=E5=8C=96=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E9=83=A8=E5=88=86=E6=97=A0=E7=94=A8=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=20close=20#494?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/subcmd/mysqlcmd/cmd.go | 15 +- .../subcmd/mysqlcmd/semantic_check.go | 103 ---- .../pkg/components/mysql/dbbackup/types.go | 105 ---- .../pkg/components/mysql/excute_sql_file.go | 34 +- .../components/mysql/execute_partition_sql.go | 22 +- .../components/mysql/semantic_check_run.go | 454 ------------------ .../dbactuator/pkg/core/codes/codes.go | 62 --- .../db-tools/dbactuator/pkg/core/cst/const.go | 31 -- .../db-tools/dbactuator/pkg/core/cst/cst.go | 40 ++ .../pkg/util/mysqlutil/mysqlclient_exec.go | 34 +- .../util/mysqlutil/mysqlclient_exec_test.go | 10 + .../dbactuator/pkg/util/osutil/osutil.go | 35 +- .../pkg/util/templates/cmd_groups.go | 10 + 13 files changed, 129 insertions(+), 826 deletions(-) delete mode 100644 dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_check.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/dbbackup/types.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_check_run.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/core/codes/codes.go delete mode 100644 dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/const.go diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go index f1c2ff428b..13e0cbbb1e 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/cmd.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysqlcmd import ( @@ -25,7 +35,7 @@ func NewMysqlCommand() *cobra.Command { NewExecSQLFileCommand(), CloneClientGrantCommand(), NewBackupTruncateDatabaseCommand(), - //NewBackupDatabaseTableCommand(), + // NewBackupDatabaseTableCommand(), MycnfChangeCommand(), FindLocalBackupCommand(), MycnfCloneCommand(), @@ -37,7 +47,7 @@ func NewMysqlCommand() *cobra.Command { NewPtTableChecksumCommand(), NewInstallMySQLChecksumCommand(), NewInstallNewDbBackupCommand(), - //NewFullBackupCommand(), + // NewFullBackupCommand(), NewInstallRotateBinlogCommand(), NewInstallDBAToolkitCommand(), NewDeployMySQLCrondCommand(), @@ -52,7 +62,6 @@ func NewMysqlCommand() *cobra.Command { { Message: "mysql semantic check operation sets", Commands: []*cobra.Command{ - NewSenmanticCheckCommand(), NewSenmanticDumpSchemaCommand(), }, }, diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_check.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_check.go deleted file mode 100644 index 15f7084fa2..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_check.go +++ /dev/null @@ -1,103 +0,0 @@ -package mysqlcmd - -import ( - "fmt" - - "dbm-services/common/go-pubpkg/logger" - "dbm-services/mysql/db-tools/dbactuator/internal/subcmd" - "dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql" - "dbm-services/mysql/db-tools/dbactuator/pkg/util" - - "github.com/spf13/cobra" -) - -// SenmanticCheckAct TODO -type SenmanticCheckAct struct { - *subcmd.BaseOptions - Payload mysql.SemanticCheckComp - Clean bool -} - -// NewSenmanticCheckCommand godoc -// -// @Summary 运行语义检查 -// @Description 运行语义检查 -// @Tags mysql -// @Accept json -// @Produce json -// @Param body body mysql.SemanticCheckComp true "short description" -// @Router /mysql/semantic-check [post] -func NewSenmanticCheckCommand() *cobra.Command { - act := SenmanticCheckAct{ - BaseOptions: subcmd.GBaseOptions, - Payload: mysql.SemanticCheckComp{}, - } - cmd := &cobra.Command{ - Use: "semantic-check", - Short: "运行语义检查", - Example: fmt.Sprintf( - `dbactuator mysql senmantic-check %s %s`, - subcmd.CmdBaseExampleStr, subcmd.ToPrettyJson(act.Payload.Example()), - ), - Run: func(cmd *cobra.Command, args []string) { - util.CheckErr(act.Validate()) - if act.RollBack { - util.CheckErr(act.Rollback()) - return - } - util.CheckErr(act.Init()) - if act.Clean { - util.CheckErr(act.Payload.Clean()) - return - } - util.CheckErr(act.Run()) - }, - } - cmd.Flags().BoolVarP(&act.Clean, "clean", "c", act.Clean, "清理语义检查实例") - return cmd -} - -// Validate TODO -func (d *SenmanticCheckAct) Validate() (err error) { - return d.BaseOptions.Validate() -} - -// Init TODO -func (d *SenmanticCheckAct) Init() (err error) { - if err = d.Deserialize(&d.Payload.Params); err != nil { - logger.Error("DeserializeAndValidate failed, %v", err) - return err - } - d.Payload.GeneralParam = subcmd.GeneralRuntimeParam - return nil -} - -// Rollback TODO -func (d *SenmanticCheckAct) Rollback() (err error) { - return -} - -// Run TODO -func (d *SenmanticCheckAct) Run() (err error) { - steps := subcmd.Steps{ - { - FunName: "precheck", - Func: d.Payload.Precheck, - }, { - FunName: "init", - Func: func() error { - return d.Payload.Init(d.Uid) - }, - }, - { - FunName: "运行语义分析", - Func: d.Payload.Run, - }, - } - if err := steps.Run(); err != nil { - return err - } - - logger.Info("运行语义检查成功") - return nil -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/dbbackup/types.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/dbbackup/types.go deleted file mode 100644 index 5da73c2de9..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/dbbackup/types.go +++ /dev/null @@ -1,105 +0,0 @@ -package dbbackup - -//// LogicBackupDataOption TODO -//type LogicBackupDataOption struct { -// // "grant,schema,data" -// DataSchemaGrant string `json:"DataSchemaGrant"` -//} -// -//// cfg the config of dumping backup -//type cfg struct { -// Public CnfShared `json:"Public" ini:"Public" validate:"required"` -// BackupClient CnfBackupClient `json:"BackupClient" ini:"BackupClient" validate:"required"` -// LogicalBackup CnfLogicalBackup `json:"LogicalBackup" ini:"LogicalBackup" validate:"required"` -// // LogicalLoad CnfLogicalLoad `json:"LogicalLoad" ini:"LogicalLoad"` -// PhysicalBackup CnfPhysicalBackup `json:"PhysicalBackup" ini:"PhysicalBackup"` -//} -// -//// CnfShared TODO -//type CnfShared struct { -// BkBizId string `ini:"BkBizId"` -// BkCloudId string `ini:"BkCloudId"` -// BillId string `ini:"BillId"` -// BackupId string `ini:"BackupId"` -// ClusterAddress string `ini:"ClusterAddress"` -// ClusterId string `ini:"ClusterId"` -// ShardValue int `ini:"ShardValue"` -// MysqlHost string `ini:"MysqlHost"` -// MysqlPort string `ini:"MysqlPort"` -// MysqlUser string `ini:"MysqlUser"` -// MysqlPasswd string `ini:"MysqlPasswd"` -// DataSchemaGrant string `ini:"DataSchemaGrant"` -// BackupDir string `ini:"BackupDir" validate:"required"` -// MysqlRole string `ini:"MysqlRole"` -// MysqlCharset string `ini:"MysqlCharset"` -// BackupTimeOut string `ini:"BackupTimeout" validate:"required,time"` -// BackupType string `ini:"BackupType"` -// OldFileLeftDay string `ini:"OldFileLeftDay"` -// // TarSizeThreshold tar file will be split to this package size. MB -// TarSizeThreshold uint64 `ini:"TarSizeThreshold" validate:"required,gte=128"` -// // IOLimitMBPerSec tar or split default io limit, mb/s. 0 means no limit -// IOLimitMBPerSec int `ini:"IOLimitMBPerSec"` -// ResultReportPath string `ini:"ResultReportPath"` -// StatusReportPath string `ini:"StatusReportPath"` -//} -// -//// CnfBackupClient TODO -//type CnfBackupClient struct { -// FileTag string `ini:"FileTag"` -// RemoteFileSystem string `ini:"RemoteFileSystem"` -// DoChecksum string `ini:"DoChecksum"` -//} -// -//// CnfLogicalBackup the config of logical backup -//type CnfLogicalBackup struct { -// // ChunkFileSize Split tables into chunks of this output file size. This value is in MB -// ChunkFileSize uint64 `ini:"ChunkFileSize"` -// Regex string `ini:"Regex"` -// Threads int `ini:"Threads"` -// DisableCompress bool `ini:"DisableCompress"` -// FlushRetryCount int `ini:"FlushRetryCount"` -// DefaultsFile string `ini:"DefaultsFile"` -// // ExtraOpt other mydumper options string to be appended -// ExtraOpt string `ini:"ExtraOpt"` -//} -// -//// CnfPhysicalBackup the config of physical backup -//type CnfPhysicalBackup struct { -// // Threads –parallel to copy files -// Threads int `ini:"Threads"` -// // SplitSpeed tar split limit in MB/s, default 300 -// SplitSpeed int64 `ini:"SplitSpeed"` -// // Throttle limits the number of chunks copied per second. The chunk size is 10 MB, 0 means no limit -// Throttle int `ini:"Throttle"` -// DefaultsFile string `ini:"DefaultsFile" validate:"required,file"` -// // ExtraOpt other xtrabackup options string to be appended -// ExtraOpt string `ini:"ExtraOpt"` -//} -// -//// CnfLogicalLoad the config of logical loading -//type CnfLogicalLoad struct { -// MysqlHost string `ini:"MysqlHost"` -// MysqlPort string `ini:"MysqlPort"` -// MysqlUser string `ini:"MysqlUser"` -// MysqlPasswd string `ini:"MysqlPasswd"` -// MysqlCharset string `ini:"MysqlCharset"` -// MysqlLoadDir string `ini:"MysqlLoadDir"` -// Threads int `ini:"Threads"` -// Regex string `ini:"Regex"` -// EnableBinlog bool `ini:"EnableBinlog"` -// IndexFilePath string `ini:"IndexFilePath" validate:"required"` -// // ExtraOpt other myloader options string to be appended -// ExtraOpt string `json:"ExtraOpt"` -//} -// -//// CnfPhysicalLoad the config of physical loading -//type CnfPhysicalLoad struct { -// MysqlLoadDir string `ini:"MysqlLoadDir" validate:"required"` -// Threads int `ini:"Threads"` -// // CopyBack use copy-back or move-back -// CopyBack bool `ini:"CopyBack"` -// IndexFilePath string `ini:"IndexFilePath" validate:"required,file"` -// DefaultsFile string `ini:"DefaultsFile" validate:"required"` -// // ExtraOpt other xtrabackup recover options string to be appended -// ExtraOpt string `json:"ExtraOpt"` -//} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/excute_sql_file.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/excute_sql_file.go index 65ccb2fc84..b84366552d 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/excute_sql_file.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/excute_sql_file.go @@ -1,8 +1,17 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package mysql TODO // -// package -// ignore_dbnames: 变更时候需要忽略的dbname,支持正则匹配 [db1,db2,db3%] -// dbnames: 变更时候 需要指定的变更的库 +// ignore_dbnames: 变更时候需要忽略的dbname,支持正则匹配 [db1,db2,db3%] +// dbnames: 变更时候 需要指定的变更的库 package mysql import ( @@ -135,25 +144,6 @@ func (e *ExcuteSQLFileComp) Init() (err error) { return nil } -// MvFile2TaskDir 将gse的文件move 到taskdir -// -// @receiver e -// @receiver err -// func (e *ExcuteSQLFileComp) MvFile2TaskDir(taskdir string) (err error) { -// e.taskdir = path.Join(cst.BK_PKG_INSTALL_PATH, taskdir) -// if err = os.MkdirAll(e.taskdir, os.ModePerm); err != nil { -// logger.Error("初始化任务目录失败%s:%s", e.taskdir, err.Error()) -// return -// } -// for _, o := range e.Params.ExcuteObjects { -// if err = os.Rename(path.Join(cst.BK_PKG_INSTALL_PATH, o.SQLFile), path.Join(e.taskdir, o.SQLFile)); err != nil { -// logger.Error("将SQL文件%s移动到%s 错误:%s", o.SQLFile, e.taskdir, err.Error()) -// return -// } -// } -// return err -// } - // Excute TODO func (e *ExcuteSQLFileComp) Excute() (err error) { for _, port := range e.ports { diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/execute_partition_sql.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/execute_partition_sql.go index 031d17bca8..db01f93384 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/execute_partition_sql.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/execute_partition_sql.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysql import ( @@ -140,8 +150,12 @@ func (e *ExcutePartitionSQLComp) Excute() (err error) { param = "&tc_admin=0" } - dbw, err := InitDB(ip, port, user, pwd, param) - defer dbw.Close() + dbw, err := initDB(ip, port, user, pwd, param) + defer func() { + if dbw != nil { + dbw.Close() + } + }() c := make(chan struct{}, 4) wg := &sync.WaitGroup{} errs := []string{} @@ -269,8 +283,8 @@ func (e *ExcutePartitionSQLComp) excuteOne( return nil } -// InitDB TODO -func InitDB(host string, port int, user string, pwd string, param string) (dbw *sql.DB, err error) { +// initDB TODO +func initDB(host string, port int, user string, pwd string, param string) (dbw *sql.DB, err error) { tcpdsn := fmt.Sprintf("%s:%d", host, port) dsn := fmt.Sprintf( "%s:%s@tcp(%s)/?charset=utf8&parseTime=True&loc=Local&timeout=30s&readTimeout=30s&lock_wait_timeout=5%s", user, diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_check_run.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_check_run.go deleted file mode 100644 index 6b71924f54..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_check_run.go +++ /dev/null @@ -1,454 +0,0 @@ -package mysql - -import ( - "fmt" - "os" - "os/exec" - "path" - "regexp" - "sync" - - "dbm-services/common/go-pubpkg/logger" - "dbm-services/mysql/db-tools/dbactuator/pkg/components" - "dbm-services/mysql/db-tools/dbactuator/pkg/components/computil" - "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" - "dbm-services/mysql/db-tools/dbactuator/pkg/native" - "dbm-services/mysql/db-tools/dbactuator/pkg/util" - "dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil" - "dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil" - - ants "github.com/panjf2000/ants/v2" -) - -/* - Prepare: - 1、下发备份表结构命名到目标实例,完成备份表结构 - 2、将备份的表结构文件&待语义检查的SQL文件下发到语义检查的机器上 - 3、选择一个于目标实例版本一致的语义检查的实例,锁定 - ------------------------------------------------------------- - Doing: - 4、将处理后的表结构导入到临时实例上 - 5、导入待检查的SQL文件 - 6、分析语义检查的结果 - ------------------------------------------------------------- - Ending: - 7、Clean 语义检查临时实例,并释放 -*/ - -// SemanticCheckComp TODO -type SemanticCheckComp struct { - GeneralParam *components.GeneralParam `json:"general"` - Params SenmanticCheckParam `json:"extend"` - SenmanticCheckRunTimeCtx `json:"-"` -} - -// SenmanticCheckParam TODO -type SenmanticCheckParam struct { - Host string `json:"host" validate:"required,ip"` // 语义检查实例的主机地址 - Port int `json:"port" validate:"required,lt=65536,gte=3306"` // 语义检查实例的端口 - SchemaFile string `json:"schemafile" validate:"required"` // 表结构文件 - ExcuteObjects []ExcuteSQLFileObj `json:"execute_objects"` - // 用于获取目标实例的字符集,默认存储引擎 - RemoteHost string `json:"remote_host" validate:"required,ip"` // 获取表结构的源实例IP - RemotePort int `json:"remote_port" validate:"required,lt=65536,gte=3306"` // 获取表结构的源实例Port -} - -// SenmanticCheckRunTimeCtx TODO -type SenmanticCheckRunTimeCtx struct { - dbConn *native.DbWorker - adminUser string - adminPwd string - socket string - version string - remoteDefaultEngineIsTokudb bool - remoteVersion string - remoteCharset string - afterdealSchemafile string // schema sqlfile 处理之后的文件 - taskdir string - schemafilename string -} - -// Precheck 前置检查 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) Precheck() (err error) { - if !osutil.FileExist(c.Params.SchemaFile) { - return fmt.Errorf("%s文件不存在", c.Params.SchemaFile) - } - for _, o := range c.Params.ExcuteObjects { - if !osutil.FileExist(path.Join(cst.BK_PKG_INSTALL_PATH, o.SQLFile)) { - return fmt.Errorf("%s文件不存在", o.SQLFile) - } - } - return nil -} - -// Example TODO -func (c *SemanticCheckComp) Example() interface{} { - comp := SemanticCheckComp{ - Params: SenmanticCheckParam{ - Host: "1.1.1.1", - Port: 3306, - SchemaFile: "db_schema.sql", - ExcuteObjects: []ExcuteSQLFileObj{ - { - SQLFile: "test1.sql", - IgnoreDbNames: []string{"db9"}, - DbNames: []string{"db_100*", "db8"}, - }, - { - SQLFile: "test2.sql", - IgnoreDbNames: []string{"db90"}, - DbNames: []string{"db_200*", "db7"}, - }, - }, - RemoteHost: "2.2.2.2", - RemotePort: 3306, - }, - } - return comp -} - -// Init TODO -// -// @receiver c -// @receiver uid -// @return err -func (c *SemanticCheckComp) Init(uid string) (err error) { - c.taskdir = path.Join(cst.BK_PKG_INSTALL_PATH, fmt.Sprintf("semantic_check_%s", uid)) - if err = os.MkdirAll(c.taskdir, os.ModePerm); err != nil { - logger.Error("初始化任务目录失败%s:%s", c.taskdir, err.Error()) - return - } - - c.schemafilename = path.Base(c.Params.SchemaFile) - // 将表结构文件移动到target dir - if err = os.Rename(c.Params.SchemaFile, path.Join(c.taskdir, c.schemafilename)); err != nil { - logger.Error("将表结构文件移动到%s 错误:%s", c.taskdir, err.Error()) - return - } - if err = c.initLocalRuntimeCtxParam(); err != nil { - return - } - return c.initRemoteRuntimeCtxParam() -} - -// initRemoteRuntimeCtxParam TODO -// -// initRuntimeCtxParam 初始化运行时参数 -// @receiver c -// @return err -func (c *SemanticCheckComp) initRemoteRuntimeCtxParam() (err error) { - remotedbConn, err := native.InsObject{ - Host: c.Params.RemoteHost, - Port: c.Params.RemotePort, - User: c.GeneralParam.RuntimeAccountParam.MonitorAccessAllUser, - Pwd: c.GeneralParam.RuntimeAccountParam.MonitorAccessAllPwd, - }.Conn() - if err != nil { - logger.Error("Connect %s:%d failed:%s", c.Params.RemoteHost, c.Params.Port, err.Error()) - return err - } - defer func() { - if remotedbConn.Db != nil { - remotedbConn.Db.Close() - } - }() - if c.remoteCharset, err = remotedbConn.ShowServerCharset(); err != nil { - logger.Error("获取源实例的字符集失败:%s", err.Error()) - return err - } - if c.remoteVersion, err = remotedbConn.SelectVersion(); err != nil { - logger.Error("获取源实例的Version:%s", err.Error()) - return err - } - if c.remoteDefaultEngineIsTokudb, err = remotedbConn.IsSupportTokudb(); err != nil { - logger.Error("判断源实例是否支持:%s", err.Error()) - return err - } - return err -} - -func (c *SemanticCheckComp) initLocalRuntimeCtxParam() (err error) { - c.adminUser = c.GeneralParam.RuntimeAccountParam.AdminUser - c.adminPwd = c.GeneralParam.RuntimeAccountParam.AdminPwd - c.dbConn, err = native.InsObject{ - Host: c.Params.Host, - Port: c.Params.Port, - User: c.adminUser, - Pwd: c.adminPwd, - }.Conn() - if err != nil { - logger.Error("Connect %d failed:%s", c.Params.Port, err.Error()) - return err - } - c.socket, err = c.dbConn.ShowSocket() - if err != nil { - logger.Warn("获取本实例socket val 失败") - } - c.version, err = c.dbConn.SelectVersion() - if err != nil { - logger.Error("获取本实例Version失败:%s", err.Error()) - return err - } - return nil -} - -// dealWithSchemaFile 导入前处理导入文件 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) dealWithSchemaFile() (err error) { - script := fmt.Sprintf("cat %s ", path.Join(c.taskdir, c.schemafilename)) - if c.remoteDefaultEngineIsTokudb { - script += ` | sed -e 's/ROW_FORMAT=TOKUDB_ZLIB/ROW_FORMAT=default/'` - } - // 将没有包含"CREATE TABLE IF NOT EXISTS"的行做替换(直接替换会导致替换结果出现两次IF NOT EXISTS) - script += ` | sed '/CREATE TABLE IF NOT EXISTS /! s/^CREATE TABLE /CREATE TABLE IF NOT EXISTS /'` - engine := "INNODB" - if c.remoteDefaultEngineIsTokudb { - engine = "MYISAM" - } - switch { - case regexp.MustCompile(`tspider-3`).MatchString(c.remoteVersion): - script += ` | sed -e 's/99106 ROW_FORMAT=GCS_DYNAMIC/99104 ROW_FORMAT=DYNAMIC/i'` - script += ` | sed -e 's/99104 COMPRESSED/99999 COMPRESSED/i'` - script += ` | sed -e 's/ROW_FORMAT=FIXED//i'` - script += fmt.Sprintf(" | sed -e 's/ENGINE=SPIDER /ENGINE=%s ROW_FORMAT=DYNAMIC /i'", engine) - script += " | sed '/^ PARTITION `pt/d' " - script += fmt.Sprintf(" | sed 's/ENGINE = SPIDER,$/ENGINE = %s) ;/g'", engine) - script += ` | sed 's/MOD [0-9]*)$/MOD 1)/g'` - case regexp.MustCompile(`spider`).MatchString(c.remoteVersion): - script += ` | sed -e 's/99106 ROW_FORMAT=GCS_DYNAMIC/99104 ROW_FORMAT=DYNAMIC/i'` - script += ` | sed -e 's/99104 COMPRESSED/99999 COMPRESSED/i'` - script += ` | sed -e 's/ROW_FORMAT=FIXED//i'` - script += fmt.Sprintf(" | sed -e 's/ENGINE=SPIDER /ENGINE=%s ROW_FORMAT=DYNAMIC /i'", engine) - script += ` | sed '/^ PARTITION pt/d'` - script += "| sed '/^ PARTITION `pt/d'" - script += fmt.Sprintf(" | sed 's/ENGINE = SPIDER,$/ENGINE = %s) \\\\*\\\\/;/g'", engine) - script += `| sed 's/%[0-9]*)$/\%1)/g'` - default: - script += " | sed -e 's/99106 ROW_FORMAT=GCS_DYNAMIC/99104 ROW_FORMAT=DYNAMIC/i'" - script += " | sed -e 's/99104 COMPRESSED/99999 COMPRESSED/i'" - script += " | sed -e 's/ROW_FORMAT=FIXED//i'" - script += " | sed -e 's/ENGINE=SPIDER DEFAULT CHARSET=/ENGINE=INNODB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=/i'" - } - logger.Info("导入前预处理命令:%s", script) - stdOutFileName := path.Join(c.taskdir, c.schemafilename+".new") - stdOutFile, err := os.OpenFile(stdOutFileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return fmt.Errorf("open file %s failed, err:%w", stdOutFileName, err) - } - defer func() { - if err := stdOutFile.Close(); err != nil { - logger.Warn("close file %s failed, err:%s", stdOutFileName, err.Error()) - } - }() - - stdErrFileName := path.Join(c.taskdir, c.schemafilename+".new.err") - stdErrFile, err := os.OpenFile(stdErrFileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return fmt.Errorf("open %s failed, err:%+v", stdErrFileName, err) - } - defer func() { - if err := stdErrFile.Close(); err != nil { - logger.Warn("close file %s failed, err:%s", stdErrFileName, err.Error()) - } - }() - logger.Info( - "预处理导出的表结构[doing]: 源文件(%s) ==> 预处理后文件(%s), 错误输出(%s)", - c.Params.SchemaFile, - stdOutFileName, - stdErrFileName, - ) - cmd := exec.Command("/bin/bash", "-c", script) - cmd.Stdout = stdOutFile - cmd.Stderr = stdErrFile - if err := cmd.Run(); err != nil { - logger.Error("运行预处理失败%s", err.Error()) - return err - } - logger.Info( - "预处理导出的表结构[doing]: 源文件(%s) ==> 预处理后文件(%s), 错误输出(%s)", - c.Params.SchemaFile, - stdOutFileName, - stdErrFileName, - ) - c.afterdealSchemafile = stdOutFileName - return nil -} - -// LoadSchema 导入远程表结构 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) LoadSchema() (err error) { - if err = c.dealWithSchemaFile(); err != nil { - logger.Error("预处理导入文件失败:%s", err.Error()) - return err - } - return mysqlutil.ExecuteSqlAtLocal{ - Host: c.Params.Host, - Port: c.Params.Port, - Charset: c.remoteCharset, - Socket: c.socket, - User: c.adminUser, - Password: c.adminPwd, - }.ExcuteSqlByMySQLClient(c.afterdealSchemafile, []string{native.TEST_DB}) -} - -// Run 运行语义检查 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) Run() (err error) { - if err = c.LoadSchema(); err != nil { - logger.Error("导入目标实例%s:%d表结构失败", c.Params.RemoteHost, c.Params.RemotePort) - return err - } - e := ExcuteSQLFileComp{ - GeneralParam: c.GeneralParam, - Params: &ExcuteSQLFileParam{ - Host: c.Params.Host, - Ports: []int{c.Params.Port}, - CharSet: c.remoteCharset, - ExcuteObjects: c.Params.ExcuteObjects, - Force: false, - }, - ExcuteSQLFileRunTimeCtx: ExcuteSQLFileRunTimeCtx{}, - } - if err = e.Init(); err != nil { - return err - } - if err = e.Excute(); err != nil { - return err - } - return nil -} - -// Clean 清理并重启语义实例 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) Clean() (err error) { - logger.Info("开始清除语义检查的实例...") - if err = c.initLocalRuntimeCtxParam(); err != nil { - return err - } - if err = c.cleandata(); err != nil { - logger.Warn("清理语义实例失败:%s", err.Error()) - return - } - if err = c.restart(); err != nil { - logger.Error("重启语义实例失败:%s", err.Error()) - return - } - logger.Info("清理语义检查实例成功~") - return -} - -// restart TODO -// shutdown 重启语义检查实例 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) restart() (err error) { - err = computil.ShutdownMySQLParam{ - MySQLUser: c.adminUser, - MySQLPwd: c.adminPwd, - Socket: c.socket, - }.ShutdownMySQLBySocket() - if err != nil { - logger.Error("关闭实例失败:%s", err.Error()) - return err - } - p := &computil.StartMySQLParam{ - MyCnfName: util.GetMyCnfFileName(c.Params.Port), - MySQLUser: c.adminUser, - MySQLPwd: c.adminPwd, - Socket: c.socket, - } - _, err = p.StartMysqlInstance() - if err != nil { - logger.Error("启动实例失败:%s", err.Error()) - return err - } - return -} - -// cleandata TODO -// DropSenmanticInstanceDatabases 清楚语义实例的数据库 -// -// @receiver c -// @return err -func (c *SemanticCheckComp) cleandata() (err error) { - alldbs, err := c.dbConn.ShowDatabases() - if err != nil { - logger.Error("清理实例:获取语义检查实例本地实例失败%s", err.Error()) - return err - } - testTbls, err := c.dbConn.ShowTables(native.TEST_DB) - if err != nil { - logger.Error("清理实例:获取test库内的表失败:%s", err.Error()) - return err - } - dbInfobaseTbls, err := c.dbConn.ShowTables(native.INFODBA_SCHEMA) - if err != nil { - logger.Error("清理实例:获取 infodba_schema 库内的表失败:%s", err.Error()) - return err - } - - var wg sync.WaitGroup - errChan := make(chan error, 1) - pool, _ := ants.NewPool(100) - defer pool.Release() - - dropdbs := util.FilterOutStringSlice(alldbs, computil.GetGcsSystemDatabases(c.version)) - logger.Info("will drop databases is:%v", dropdbs) - f := func(db string) func() { - return func() { - _, err := c.dbConn.Exec(fmt.Sprintf("drop database `%s`;", db)) - if err != nil { - errChan <- fmt.Errorf("drop database %s,err:%w", db, err) - } - wg.Done() - } - } - for _, db := range dropdbs { - wg.Add(1) - pool.Submit(f(db)) - } - type db = string - type tables = []string - var specialDbTbls map[db]tables - specialDbTbls = make(map[string][]string) - specialDbTbls[native.INFODBA_SCHEMA] = util.FilterOutStringSlice(testTbls, []string{"conn_log", "free_space"}) - specialDbTbls[native.INFODBA_SCHEMA] = util.FilterOutStringSlice( - dbInfobaseTbls, - []string{"QUERY_RESPONSE_TIME", "check_heartbeat", "checksum", "master_slave_heartbeat", "spes_status"}, - ) - ff := func(db, tbl string) func() { - return func() { - _, err := c.dbConn.Exec(fmt.Sprintf("drop table if exists `%s`.`%s`;", db, tbl)) - if err != nil { - errChan <- fmt.Errorf("drop table if exists `%s`.`%s`,err:%w", db, tbl, err) - } - wg.Done() - } - } - for db, tbls := range specialDbTbls { - for _, tbl := range tbls { - wg.Add(1) - pool.Submit(ff(db, tbl)) - } - } - wg.Wait() - select { - case err := <-errChan: - logger.Error("drop db failed: %s", err.Error()) - return err - default: - } - return nil -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/core/codes/codes.go b/dbm-services/mysql/db-tools/dbactuator/pkg/core/codes/codes.go deleted file mode 100644 index 478a7aee7e..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/core/codes/codes.go +++ /dev/null @@ -1,62 +0,0 @@ -// Package codes TODO -package codes - -/* -@description: 相关错误码及对应错误类型 -@rules: -1. 初始化类的错误码使用 30000-39999 -2. 操作系统的错误码使用 40000-49999 -3. MySQL、Redis、Mongo实例操作的错误码 50000-59999 -*/ - -const ( - // Unauthorized TODO - Unauthorized = 10001 - // UnmarshalFailed TODO - UnmarshalFailed = 10002 - // NotExistMountPoint TODO - NotExistMountPoint = 20001 - // NotExistUser TODO - NotExistUser = 20002 - // PermissionDeny TODO - PermissionDeny = 20003 - - // RenderConfigFailed TODO - RenderConfigFailed = 30001 - // InitParamFailed TODO - InitParamFailed = 30002 - // InitMySQLDirFailed TODO - InitMySQLDirFailed = 30003 - - // InstallMySQLFailed TODO - InstallMySQLFailed = 40001 - // ExecuteShellFailed TODO - ExecuteShellFailed = 40002 - // DecompressPkgFailed TODO - DecompressPkgFailed = 40003 - // StartMySQLFailed TODO - StartMySQLFailed = 40004 - // NotAvailableMem TODO - NotAvailableMem = 40005 - - // ImportPrivAndSchemaFailed TODO - ImportPrivAndSchemaFailed = 50001 -) - -// ErrorCodes TODO -var ErrorCodes = map[int]string{ - Unauthorized: "没有进行用户认证", - UnmarshalFailed: "反序列化失败", - NotExistMountPoint: "没有可用的挂载点", - NotExistUser: "用户不存在", - PermissionDeny: "权限不足", - RenderConfigFailed: "初始化配置失败", - InitParamFailed: "初始化参数失败", - InitMySQLDirFailed: "初始化MySQL目录失败", - InstallMySQLFailed: "安装实例失败", - ExecuteShellFailed: "执行Shell脚本失败", - DecompressPkgFailed: "解压文件失败", - StartMySQLFailed: "启动MySQL失败", - NotAvailableMem: "内存不可用", - ImportPrivAndSchemaFailed: "导入权限和库失败", -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/const.go b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/const.go deleted file mode 100644 index c6e7d32def..0000000000 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/const.go +++ /dev/null @@ -1,31 +0,0 @@ -package cst - -import "time" - -const ( - // Environment TODO - Environment = "enviroment" - // Test TODO - Test = "test" -) - -const ( - // TIMELAYOUT TODO - TIMELAYOUT = "2006-01-02 15:04:05" - // TIMELAYOUTSEQ TODO - TIMELAYOUTSEQ = "2006-01-02_15:04:05" - // TimeLayoutDir TODO - TimeLayoutDir = "20060102150405" -) - -const ( - // BK_PKG_INSTALL_PATH 默认文件下发路径 - BK_PKG_INSTALL_PATH = "/data/install" - // MYSQL_TOOL_INSTALL_PATH 默认工具安装路径 - MYSQL_TOOL_INSTALL_PATH = "/home/mysql" -) - -// GetNowTimeLayoutStr 20060102150405 -func GetNowTimeLayoutStr() string { - return time.Now().Format(TimeLayoutDir) -} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/cst.go b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/cst.go index 1dab3e254a..b5c7682370 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/cst.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/core/cst/cst.go @@ -1,2 +1,42 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package cst 常量 package cst + +import "time" + +const ( + // Environment TODO + Environment = "enviroment" + // Test TODO + Test = "test" +) + +const ( + // TIMELAYOUT TODO + TIMELAYOUT = "2006-01-02 15:04:05" + // TIMELAYOUTSEQ TODO + TIMELAYOUTSEQ = "2006-01-02_15:04:05" + // TimeLayoutDir TODO + TimeLayoutDir = "20060102150405" +) + +const ( + // BK_PKG_INSTALL_PATH 默认文件下发路径 + BK_PKG_INSTALL_PATH = "/data/install" + // MYSQL_TOOL_INSTALL_PATH 默认工具安装路径 + MYSQL_TOOL_INSTALL_PATH = "/home/mysql" +) + +// GetNowTimeLayoutStr 20060102150405 +func GetNowTimeLayoutStr() string { + return time.Now().Format(TimeLayoutDir) +} diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go index f07865bd0d..e8bf7e5b6c 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec.go @@ -11,6 +11,7 @@ package mysqlutil import ( + "bytes" "database/sql" "fmt" "io" @@ -23,7 +24,6 @@ import ( "dbm-services/common/go-pubpkg/logger" "dbm-services/mysql/db-tools/dbactuator/pkg/core/cst" "dbm-services/mysql/db-tools/dbactuator/pkg/util" - "dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil" ) // ExecuteSqlAtLocal TODO @@ -101,30 +101,29 @@ func (e ExecuteSqlAtLocal) ExcuteSqlByMySQLClientOne(sqlfile string, db string) // ExcuteCommand TODO func (e ExecuteSqlAtLocal) ExcuteCommand(command string) (err error) { + var stderrBuf bytes.Buffer var errStdout, errStderr error logger.Info("The Command Is %s", ClearSensitiveInformation(command)) cmd := exec.Command("/bin/bash", "-c", command) stdoutIn, _ := cmd.StdoutPipe() stderrIn, _ := cmd.StderrPipe() - stdout := osutil.NewCapturingPassThroughWriter(os.Stdout) - stderr := osutil.NewCapturingPassThroughWriter(os.Stderr) - defer func() { - // 写入error 文件 - ef, errO := os.OpenFile(e.ErrFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) - if errO != nil { - logger.Warn("打开日志时失败! %s", errO.Error()) - return - } - defer ef.Close() - _, errW := ef.Write(stderr.Bytes()) - if errW != nil { - logger.Warn("写错误日志时失败! %s", err.Error()) - } - }() + + // 写入error 文件 + ef, errO := os.OpenFile(e.ErrFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if errO != nil { + logger.Warn("打开日志时失败! %s", errO.Error()) + return + } + defer ef.Close() + defer ef.Sync() + stdout := io.MultiWriter(os.Stdout) + stderr := io.MultiWriter(os.Stderr, &stderrBuf, ef) + if err = cmd.Start(); err != nil { logger.Error("start command failed:%s", err.Error()) return } + var wg sync.WaitGroup wg.Add(1) @@ -142,10 +141,11 @@ func (e ExecuteSqlAtLocal) ExcuteCommand(command string) (err error) { } if err = cmd.Wait(); err != nil { - errStr := string(stderr.Bytes()) + errStr := string(stderrBuf.Bytes()) logger.Error("exec failed:%s,stderr: %s", err.Error(), errStr) return } + return nil } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec_test.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec_test.go index c5e4d521af..0327890311 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec_test.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/mysqlutil/mysqlclient_exec_test.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysqlutil_test import ( diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil/osutil.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil/osutil.go index f65b7657d9..352872d057 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil/osutil.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/osutil/osutil.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package osutil TODO package osutil @@ -619,31 +629,6 @@ func PrintFileSizeIncr( } } -// CapturingPassThroughWriter is a writer that remembers -// data written to it and passes it to w -type CapturingPassThroughWriter struct { - buf bytes.Buffer - w io.Writer -} - -// NewCapturingPassThroughWriter creates new CapturingPassThroughWriter -func NewCapturingPassThroughWriter(w io.Writer) *CapturingPassThroughWriter { - return &CapturingPassThroughWriter{ - w: w, - } -} - -// Write 用于常见IO -func (w *CapturingPassThroughWriter) Write(d []byte) (int, error) { - w.buf.Write(d) - return w.w.Write(d) -} - -// Bytes returns bytes written to the writer -func (w *CapturingPassThroughWriter) Bytes() []byte { - return w.buf.Bytes() -} - // ReadFileString TODO func ReadFileString(filename string) (string, error) { if body, err := os.ReadFile(filename); err != nil { diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/util/templates/cmd_groups.go b/dbm-services/mysql/db-tools/dbactuator/pkg/util/templates/cmd_groups.go index e153e2ee69..827e6185f2 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/util/templates/cmd_groups.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/util/templates/cmd_groups.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package templates import ( From 0dc8feb1886258a173439a275c3d87875ac36812 Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Mon, 17 Jul 2023 15:19:08 +0800 Subject: [PATCH 153/476] =?UTF-8?q?fix(dbm-services):=20add=20=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=BF=BD=E7=95=A5=E7=9A=84mysql=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=B4=A6=E6=88=B7=20close=20#508?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dbactuator/pkg/components/base.go | 27 +++++++--- .../pkg/components/mysql/clean_mysql.go | 52 ++++++++++++------- .../pkg/components/mysql/cutover/cutover.go | 15 +++++- .../pkg/components/mysql/uninstall_mysql.go | 12 ++++- .../spiderctl/backend_migrate_cutover.go | 3 +- .../components/spiderctl/backend_switch.go | 3 +- 6 files changed, 77 insertions(+), 35 deletions(-) diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go index c2f1ebc68d..da2ca53ef8 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/base.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package components // BaseInputParam TODO @@ -25,14 +35,15 @@ type RuntimeAccountParam struct { } // GetAllSysAccount TODO -func (g *RuntimeAccountParam) GetAllSysAccount() (accounts []string) { - accounts = append(accounts, g.AdminUser) - accounts = append(accounts, g.DbBackupUser) - accounts = append(accounts, g.MonitorAccessAllUser) - accounts = append(accounts, g.MonitorUser) - accounts = append(accounts, g.ReplUser) - accounts = append(accounts, g.YwUser) - accounts = append(accounts, g.TdbctlUser) +func (g *GeneralParam) GetAllSysAccount() (accounts []string) { + accounts = g.RuntimeExtend.MySQLSysUsers + accounts = append(accounts, g.RuntimeAccountParam.AdminUser) + accounts = append(accounts, g.RuntimeAccountParam.DbBackupUser) + accounts = append(accounts, g.RuntimeAccountParam.MonitorAccessAllUser) + accounts = append(accounts, g.RuntimeAccountParam.MonitorUser) + accounts = append(accounts, g.RuntimeAccountParam.ReplUser) + accounts = append(accounts, g.RuntimeAccountParam.YwUser) + accounts = append(accounts, g.RuntimeAccountParam.TdbctlUser) return } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/clean_mysql.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/clean_mysql.go index 94d0491d2f..2a5395f556 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/clean_mysql.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/clean_mysql.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysql import ( @@ -19,6 +29,7 @@ import ( type CleanMysqlComp struct { GeneralParam *components.GeneralParam `json:"general"` Params CleanMysqlParam `json:"extend"` + ctx } // Example TODO @@ -55,50 +66,51 @@ type CleanMysqlParam struct { CheckIntervalSec int `json:"check_interval_sec"` // 清空目标实例 TgtInstance *native.Instance `json:"tgt_instance" validate:"required"` +} +type ctx struct { + sysUsers []string checkDuration time.Duration - - myCnf *util.CnfFile - dbworker *native.DbWorker - instObj *native.InsObject - // account *components.RuntimeAccountParam + myCnf *util.CnfFile + dbworker *native.DbWorker + instObj *native.InsObject } // Init TODO func (c *CleanMysqlComp) Init() error { f := util.GetMyCnfFileName(c.Params.TgtInstance.Port) - c.Params.myCnf = &util.CnfFile{FileName: f} - if err := c.Params.myCnf.Load(); err != nil { + c.myCnf = &util.CnfFile{FileName: f} + if err := c.myCnf.Load(); err != nil { return err } - dbSocket, err := c.Params.myCnf.GetMySQLSocket() + dbSocket, err := c.myCnf.GetMySQLSocket() if err != nil { return err } - c.Params.instObj = &native.InsObject{ + c.instObj = &native.InsObject{ Host: c.Params.TgtInstance.Host, Port: c.Params.TgtInstance.Port, User: c.GeneralParam.RuntimeAccountParam.AdminUser, Pwd: c.GeneralParam.RuntimeAccountParam.AdminPwd, Socket: dbSocket, } - if dbw, err := c.Params.instObj.ConnBySocket(); err != nil { + if dbw, err := c.instObj.ConnBySocket(); err != nil { return err } else { - c.Params.dbworker = dbw + c.dbworker = dbw } if c.Params.CheckIntervalSec == 0 { c.Params.CheckIntervalSec = 31 } - c.Params.checkDuration = time.Duration(c.Params.CheckIntervalSec) * time.Second + c.checkDuration = time.Duration(c.Params.CheckIntervalSec) * time.Second return nil } // PreCheck 前置检查 // 会初始化 needRestart func (c *CleanMysqlComp) PreCheck() error { - if err := c.Params.instObj.CheckInstanceConnIdle(c.GeneralParam.RuntimeExtend.MySQLSysUsers, - c.Params.checkDuration); err != nil { + if err := c.instObj.CheckInstanceConnIdle(c.GeneralParam.GetAllSysAccount(), + c.checkDuration); err != nil { logger.Warn("clean_mysql precheck error %w", err) if c.Params.Force { return nil @@ -111,12 +123,12 @@ func (c *CleanMysqlComp) PreCheck() error { // Start TODO func (c *CleanMysqlComp) Start() error { if c.Params.StopSlave { - if err := c.Params.dbworker.StopSlave(); err != nil { + if err := c.dbworker.StopSlave(); err != nil { return errors.WithMessage(err, "stop slave") } } if c.Params.ResetSlave { - if err := c.Params.dbworker.ResetSlave(); err != nil { + if err := c.dbworker.ResetSlave(); err != nil { return errors.WithMessage(err, "reset slave") } } @@ -125,8 +137,8 @@ func (c *CleanMysqlComp) Start() error { inStr, _ := mysqlutil.UnsafeBuilderStringIn(native.DBSys, "'") dbsSql := fmt.Sprintf("select SCHEMA_NAME from information_schema.SCHEMATA where SCHEMA_NAME not in (%s)", inStr) - if databases, err := c.Params.dbworker.Query(dbsSql); err != nil { - if c.Params.dbworker.IsNotRowFound(err) { + if databases, err := c.dbworker.Query(dbsSql); err != nil { + if c.dbworker.IsNotRowFound(err) { return nil } else { return err @@ -136,7 +148,7 @@ func (c *CleanMysqlComp) Start() error { dropSQL := fmt.Sprintf("DROP DATABASE `%s`;", dbName["SCHEMA_NAME"]) logger.Warn("run sql %s", dropSQL) if c.Params.DropDatabase { - if _, err := c.Params.dbworker.Exec(dropSQL); err != nil { + if _, err := c.dbworker.Exec(dropSQL); err != nil { return errors.WithMessage(err, dropSQL) } } else { @@ -144,7 +156,7 @@ func (c *CleanMysqlComp) Start() error { } } if c.Params.DropDatabase && c.Params.Restart { - if err := computil.RestartMysqlInstanceNormal(*c.Params.instObj); err != nil { + if err := computil.RestartMysqlInstanceNormal(*c.instObj); err != nil { return err } } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go index 9be13ac50c..7fad97f841 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/cutover/cutover.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // Package cutover 主故障切换 // 下发到Slave节点的机器 执行 package cutover @@ -42,6 +52,7 @@ type runCtx struct { replPwd string backupUser string cluster *MySQLClusterDetail + sysUsers []string // 是否是成对切换 isCutOverPair bool } @@ -57,6 +68,7 @@ func (m *CutOverToSlaveComp) Init() (err error) { m.replPwd = m.GeneralParam.RuntimeAccountParam.ReplPwd m.backupUser = m.GeneralParam.RuntimeAccountParam.DbBackupUser m.checkVars = []string{"character_set_server", "lower_case_table_names"} + m.sysUsers = m.GeneralParam.GetAllSysAccount() if err = m.cluster.InitProxyConn(m.proxyAdminUser, m.proxyAdminPwd); err != nil { logger.Error("connect alt proxies failed,err:%s ", err.Error()) @@ -176,8 +188,7 @@ func (m *CutOverToSlaveComp) PreCheck() (err error) { if err = m.cluster.AltSlaveIns.CheckCheckSum(); err != nil { return err } - prcsls, err := m.cluster.AltSlaveIns.dbConn.ShowApplicationProcesslist( - m.GeneralParam.RuntimeExtend.MySQLSysUsers) + prcsls, err := m.cluster.AltSlaveIns.dbConn.ShowApplicationProcesslist(m.sysUsers) if err != nil { logger.Error("show processlist failed %s", err.Error()) return err diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/uninstall_mysql.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/uninstall_mysql.go index 68ac4cf8c7..1203d679f9 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/uninstall_mysql.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/uninstall_mysql.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + // 下架MySQL实例 // 因为下架需要操作数据目录和日志目录 // 这个两个参数是从my.cnf里面读取的 @@ -114,7 +124,7 @@ func (u *UnInstallMySQLComp) PreCheck() (err error) { if !u.Params.Force && !u.insMyObj[port].IsShutdown { // 非强制下架,且实例正常的情况下,需要判断实例是否有业务连接, // todo 这里重新去创建连接,如果检测实例状态和连接业务访问之间出现实例异常,则会触发bug,后续考虑怎么优化这点 - if err := inst.CheckInstanceConnIdle(u.GeneralParam.RuntimeExtend.MySQLSysUsers, time.Second*1); err != nil { + if err := inst.CheckInstanceConnIdle(u.GeneralParam.GetAllSysAccount(), time.Second*1); err != nil { logger.Warn("try connent this mysql instance [%p] failed:%s", port, err.Error()) u.insMyObj[port].IsShutdown = true } diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go index 9b77fb6484..84281e9f9e 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_migrate_cutover.go @@ -205,8 +205,7 @@ func (s *SpiderClusterBackendMigrateCutoverComp) Init() (err error) { if err = s.connDest(); err != nil { return err } - s.getSysUsers(servers, append(s.GeneralParam.RuntimeExtend.MySQLSysUsers, - s.GeneralParam.RuntimeAccountParam.GetAllSysAccount()...)) + s.getSysUsers(servers, s.GeneralParam.GetAllSysAccount()) ipPortServersMap, svrNameServersMap := transServersToMap(servers) s.ipPortServersMap = ipPortServersMap s.svrNameServersMap = svrNameServersMap diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go index 26fda4de08..3532c3dafb 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/spiderctl/backend_switch.go @@ -142,8 +142,7 @@ func (r *SpiderClusterBackendSwitchComp) Init() (err error) { return err } logger.Info("get all sys users ...") - r.getSysUsers(servers, append(r.GeneralParam.RuntimeExtend.MySQLSysUsers, - r.GeneralParam.RuntimeAccountParam.GetAllSysAccount()...)) + r.getSysUsers(servers, r.GeneralParam.GetAllSysAccount()) ipPortServersMap, svrNameServersMap := transServersToMap(servers) r.ipPortServersMap = ipPortServersMap r.svrNameServersMap = svrNameServersMap From 903096c7d5dc2c491a271a7c5311bd86abdbc815 Mon Sep 17 00:00:00 2001 From: fanfanyangyang Date: Mon, 17 Jul 2023 15:11:10 +0800 Subject: [PATCH 154/476] =?UTF-8?q?fix(dbm-services):=20=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=85=8B=E9=9A=86=E5=BF=BD=E7=95=A5tdbctl=E7=94=A8=E6=88=B7=20?= =?UTF-8?q?#511?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/clone_instance_priv_base_func.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/dbm-services/mysql/db-priv/service/clone_instance_priv_base_func.go b/dbm-services/mysql/db-priv/service/clone_instance_priv_base_func.go index d648dcc2ad..2d3104e317 100644 --- a/dbm-services/mysql/db-priv/service/clone_instance_priv_base_func.go +++ b/dbm-services/mysql/db-priv/service/clone_instance_priv_base_func.go @@ -62,7 +62,8 @@ func GetRemotePrivilege(address string, host string, bkCloudId int64, instanceTy if host != "" { selectUser += fmt.Sprintf(` where host='%s'`, host) } - queryRequestOuter := QueryRequest{[]string{address}, []string{selectUser}, true, 30, bkCloudId} + queryRequestOuter := QueryRequest{[]string{address}, []string{selectUser}, + true, 30, bkCloudId} repsOuter, errOuter = OneAddressExecuteSql(queryRequestOuter) if errOuter != nil { return nil, errOuter @@ -181,11 +182,14 @@ func (m *CloneInstancePrivPara) DealWithPrivileges(userGrants []UserGrant, insta if instanceType == machineTypeBackend || instanceType == machineTypeSingle || instanceType == machineTypeRemote { - if MySQLVersionParse(sourceVersion, "")/1000 == 8000 && MySQLVersionParse(targetVersion, "")/1000 == 5007 { + if MySQLVersionParse(sourceVersion, "")/1000 == 8000 && + MySQLVersionParse(targetVersion, "")/1000 == 5007 { mysql80Tomysql57 = true - } else if MySQLVersionParse(sourceVersion, "")/1000 == 5007 && MySQLVersionParse(targetVersion, "")/1000 == 5006 { + } else if MySQLVersionParse(sourceVersion, "")/1000 == 5007 && + MySQLVersionParse(targetVersion, "")/1000 == 5006 { mysql57Tomysql56 = true - } else if MySQLVersionParse(sourceVersion, "")/1000 < 8000 && MySQLVersionParse(targetVersion, "")/1000 >= 8000 { + } else if MySQLVersionParse(sourceVersion, "")/1000 < 8000 && + MySQLVersionParse(targetVersion, "")/1000 >= 8000 { mysql5Tomysql8 = true } } @@ -193,7 +197,8 @@ func (m *CloneInstancePrivPara) DealWithPrivileges(userGrants []UserGrant, insta wg := sync.WaitGroup{} errorChan := make(chan error, 1) finishChan := make(chan bool, 1) - var userExcluded = []string{"ADMIN", "mysql.session", "mysql.sys", "mysql.infoschema"} // Delete system user + // Delete system user + var userExcluded = []string{"ADMIN", "mysql.session", "mysql.sys", "mysql.infoschema", "tdbctl"} for _, row := range userGrants { wg.Add(1) go func(row UserGrant, targetIp, sourceIp string) { From c8813dc47cb31812a71912728c2c46a511646f7f Mon Sep 17 00:00:00 2001 From: iSecloud <869820505@qq.com> Date: Tue, 6 Jun 2023 17:50:29 +0800 Subject: [PATCH 155/476] =?UTF-8?q?feat(backend):=20spider=E9=83=A8?= =?UTF-8?q?=E7=BD=B2&=E5=B7=A5=E5=85=B7=E7=AE=B1=E5=8D=95=E6=8D=AE?= =?UTF-8?q?=E5=BC=80=E5=8F=91=20#496?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/components/domains.py | 2 +- .../backend/components/sql_import/client.py | 10 +- .../configuration/migrations/0001_initial.py | 3 +- .../migrations/0002_auto_20230605_2027.py | 26 +++ ...o_20230605_2027_0002_functioncontroller.py | 13 ++ .../configuration/models/ip_whitelist.py | 9 +- .../configuration/models/password_policy.py | 5 +- dbm-ui/backend/configuration/serializers.py | 9 +- .../configuration/views/ip_whitelist.py | 2 +- .../api/cluster/tendbcluster/detail.py | 9 +- .../api/cluster/tendbcluster/handler.py | 28 ++- .../db_meta/api/cluster/tendbha/handler.py | 8 +- .../api/cluster/tendbsingle/handler.py | 6 +- dbm-ui/backend/db_meta/models/spec.py | 11 + .../db_services/dbresource/serializers.py | 13 +- .../db_services/dbresource/views/sepc.py | 30 ++- .../db_services/mysql/cluster/handlers.py | 119 +++++++++-- .../db_services/mysql/cluster/serializers.py | 13 ++ .../db_services/mysql/cluster/views.py | 19 +- .../mysql/fixpoint_rollback/handlers.py | 190 ++++++++++++++++-- .../mysql/permission/authorize/handlers.py | 5 +- .../mysql/permission/clone/handlers.py | 33 +-- .../mysql/permission/clone/serializers.py | 28 ++- .../mysql/permission/clone/views.py | 1 + .../db_services/mysql/permission/constants.py | 1 + .../mysql/permission/db_account/handlers.py | 80 ++++---- .../permission/db_account/serializers.py | 116 ++++++----- .../mysql/permission/db_account/views.py | 8 +- .../mysql/remote_service/handlers.py | 21 +- .../mysql/resources/spider/query.py | 6 +- .../db_services/mysql/sql_import/constants.py | 2 +- .../db_services/mysql/sql_import/dataclass.py | 1 + .../db_services/mysql/sql_import/handlers.py | 181 +++++++++++------ .../db_services/mysql/sql_import/mock_data.py | 2 +- .../mysql/sql_import/serializers.py | 24 ++- .../db_services/mysql/sql_import/views.py | 7 +- dbm-ui/backend/env/apigw_domains.py | 2 +- dbm-ui/backend/flow/consts.py | 9 + .../bamboo/scene/mysql/mysql_clone_rules.py | 1 - .../scene/spider/import_sqlfile_flow.py | 2 +- .../bamboo/scene/spider/spider_checksum.py | 2 +- .../spider/spider_cluster_db_table_backup.py | 2 +- .../spider/spider_cluster_full_backup.py | 2 +- .../spider_cluster_truncate_database.py | 2 +- .../bamboo/scene/spider/spider_partition.py | 2 +- .../spider/spider_rename_database_flow.py | 2 +- .../collections/mysql/clone_rules.py | 15 +- dbm-ui/backend/flow/urls.py | 2 +- .../views/spider_cluster_truncate_database.py | 2 +- .../mysql/permission/test_account_handler.py | 2 +- dbm-ui/backend/ticket/builders/common/base.py | 9 +- .../ticket/builders/common/constants.py | 9 + dbm-ui/backend/ticket/builders/mysql/base.py | 21 +- .../builders/mysql/mysql_clone_rules.py | 4 + .../ticket/builders/mysql/mysql_flashback.py | 2 + .../builders/mysql/mysql_import_sqlfile.py | 59 ++---- dbm-ui/backend/ticket/builders/spider/base.py | 14 +- .../builders/spider/spider_add_nodes.py | 65 ++++++ .../builders/spider/spider_partition.py | 8 +- .../builders/spider/spider_slave_apply.py | 70 +++++++ .../ticket/builders/spider/tendb_apply.py | 21 +- .../ticket/builders/spider/tendb_backup.py | 55 +++++ .../ticket/builders/spider/tendb_checksum.py | 138 +++++++++++++ .../{spider_destory.py => tendb_destroy.py} | 5 +- .../{spider_disable.py => tendb_disable.py} | 3 +- .../ticket/builders/spider/tendb_enable.py | 3 +- .../ticket/builders/spider/tendb_flashback.py | 39 ++++ .../builders/spider/tendb_full_backup.py | 58 ++++++ .../builders/spider/tendb_import_sqlfile.py | 126 ++++++++++++ .../builders/spider/tendb_master_fail_over.py | 22 +- .../spider/tendb_master_slave_switch.py | 34 +++- .../ticket/builders/spider/tendb_mnt_apply.py | 55 +++++ .../builders/spider/tendb_node_reblance.py | 60 ++++++ .../ticket/builders/spider/tendb_rename.py | 40 ++++ dbm-ui/backend/ticket/constants.py | 43 ++-- 75 files changed, 1681 insertions(+), 370 deletions(-) create mode 100644 dbm-ui/backend/configuration/migrations/0002_auto_20230605_2027.py create mode 100644 dbm-ui/backend/configuration/migrations/0003_merge_0002_auto_20230605_2027_0002_functioncontroller.py create mode 100644 dbm-ui/backend/ticket/builders/spider/spider_add_nodes.py create mode 100644 dbm-ui/backend/ticket/builders/spider/spider_slave_apply.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_backup.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_checksum.py rename dbm-ui/backend/ticket/builders/spider/{spider_destory.py => tendb_destroy.py} (87%) rename dbm-ui/backend/ticket/builders/spider/{spider_disable.py => tendb_disable.py} (91%) create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_flashback.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_full_backup.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_import_sqlfile.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_mnt_apply.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_node_reblance.py create mode 100644 dbm-ui/backend/ticket/builders/spider/tendb_rename.py diff --git a/dbm-ui/backend/components/domains.py b/dbm-ui/backend/components/domains.py index edda897583..275a32387d 100644 --- a/dbm-ui/backend/components/domains.py +++ b/dbm-ui/backend/components/domains.py @@ -38,7 +38,7 @@ BKMONITORV3_APIGW_DOMAIN = env.BKMONITORV3_APIGW_DOMAIN or APIGW_DOMAIN_PREFIX_FORMAT.format( "monitor_v3" if settings.RUN_VER == "open" else "bkmonitorv3" ) -MYSQL_SIMULATION_DONAIN = env.MYSQL_SIMULATION_DONAIN or APIGW_DOMAIN_PREFIX_FORMAT.format("db_simulation") +MYSQL_SIMULATION_DOMAIN = env.MYSQL_SIMULATION_DONAIN or APIGW_DOMAIN_PREFIX_FORMAT.format("db_simulation") NAMESERVICE_APIGW_DOMAIN = env.NAMESERVICE_APIGW_DOMAIN or APIGW_DOMAIN_PREFIX_FORMAT.format("nameservice") HADB_APIGW_DOMAIN = env.HADB_APIGW_DOMAIN or APIGW_DOMAIN_PREFIX_FORMAT.format("hadb") DBRESOURCE_APIGW_DOMAIN = env.DBRESOURCE_APIGW_DOMAIN or APIGW_DOMAIN_PREFIX_FORMAT.format("dbresource") diff --git a/dbm-ui/backend/components/sql_import/client.py b/dbm-ui/backend/components/sql_import/client.py index db5db5a14b..b912ebcde6 100644 --- a/dbm-ui/backend/components/sql_import/client.py +++ b/dbm-ui/backend/components/sql_import/client.py @@ -12,7 +12,7 @@ from django.utils.translation import ugettext_lazy as _ from ..base import DataAPI -from ..domains import MYSQL_SIMULATION_DONAIN +from ..domains import MYSQL_SIMULATION_DOMAIN class _SQLImportApi(object): @@ -22,7 +22,7 @@ class _SQLImportApi(object): def __init__(self): self.grammar_check = DataAPI( method="POST", - base=MYSQL_SIMULATION_DONAIN, + base=MYSQL_SIMULATION_DOMAIN, url="/syntax/check/file", module=self.MODULE, description=_("sql语法检查"), @@ -36,7 +36,7 @@ class _SQLSimulation(object): def __init__(self): self.mysql_simulation = DataAPI( method="POST", - base=MYSQL_SIMULATION_DONAIN, + base=MYSQL_SIMULATION_DOMAIN, url="/mysql/simulation", module=self.MODULE, description=_("容器化SQL模拟执行"), @@ -44,7 +44,7 @@ def __init__(self): self.query_simulation_task = DataAPI( method="POST", - base=MYSQL_SIMULATION_DONAIN, + base=MYSQL_SIMULATION_DOMAIN, url="/mysql/task", module=self.MODULE, description=_("查询模拟执行任务状态也"), @@ -52,7 +52,7 @@ def __init__(self): self.spider_simulation = DataAPI( method="POST", - base=MYSQL_SIMULATION_DONAIN, + base=MYSQL_SIMULATION_DOMAIN, url="/spider/simulation", module=self.MODULE, description=_("容器化SQL模拟执行"), diff --git a/dbm-ui/backend/configuration/migrations/0001_initial.py b/dbm-ui/backend/configuration/migrations/0001_initial.py index fa569f8b0e..6ea7a1f357 100644 --- a/dbm-ui/backend/configuration/migrations/0001_initial.py +++ b/dbm-ui/backend/configuration/migrations/0001_initial.py @@ -3,6 +3,7 @@ from django.db import migrations, models from backend.configuration.constants import DBType +from backend.db_services.mysql.permission.constants import AccountType class Migration(migrations.Migration): @@ -35,7 +36,7 @@ class Migration(migrations.Migration): ( "account_type", models.CharField( - choices=DBType.get_choices(), + choices=AccountType.get_choices(), max_length=32, primary_key=True, serialize=False, diff --git a/dbm-ui/backend/configuration/migrations/0002_auto_20230605_2027.py b/dbm-ui/backend/configuration/migrations/0002_auto_20230605_2027.py new file mode 100644 index 0000000000..29ddea31fe --- /dev/null +++ b/dbm-ui/backend/configuration/migrations/0002_auto_20230605_2027.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.19 on 2023-06-05 12:27 + +from django.db import migrations, models + +from backend.configuration.constants import DBType + + +class Migration(migrations.Migration): + + dependencies = [ + ("configuration", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="ipwhitelist", + name="db_type", + field=models.CharField( + choices=DBType.get_choices(), + default="mysql", + max_length=32, + verbose_name="数据库类型", + ), + preserve_default=False, + ) + ] diff --git a/dbm-ui/backend/configuration/migrations/0003_merge_0002_auto_20230605_2027_0002_functioncontroller.py b/dbm-ui/backend/configuration/migrations/0003_merge_0002_auto_20230605_2027_0002_functioncontroller.py new file mode 100644 index 0000000000..8efb3ee021 --- /dev/null +++ b/dbm-ui/backend/configuration/migrations/0003_merge_0002_auto_20230605_2027_0002_functioncontroller.py @@ -0,0 +1,13 @@ +# Generated by Django 3.2.19 on 2023-07-14 04:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("configuration", "0002_auto_20230605_2027"), + ("configuration", "0002_functioncontroller"), + ] + + operations = [] diff --git a/dbm-ui/backend/configuration/models/ip_whitelist.py b/dbm-ui/backend/configuration/models/ip_whitelist.py index adde3d7351..b410053a44 100644 --- a/dbm-ui/backend/configuration/models/ip_whitelist.py +++ b/dbm-ui/backend/configuration/models/ip_whitelist.py @@ -16,12 +16,13 @@ from django.forms.models import model_to_dict from django.utils.translation import ugettext_lazy as _ -from backend.bk_web.constants import LEN_LONG +from backend.bk_web.constants import LEN_LONG, LEN_SHORT from backend.bk_web.models import AuditedModel -from backend.configuration.constants import PLAT_BIZ_ID +from backend.configuration.constants import PLAT_BIZ_ID, DBType class IPWhitelist(AuditedModel): + db_type = models.CharField(_("数据库类型"), choices=DBType.get_choices(), max_length=LEN_SHORT) bk_biz_id = models.IntegerField(_("业务ID")) remark = models.CharField(_("备注"), max_length=LEN_LONG) ips = models.JSONField(_("ip列表")) @@ -36,7 +37,9 @@ def list_ip_whitelist(cls, filter_data: Dict[str, Any]) -> List[Dict[str, Any]]: 根据业务ID获取平台以及该业务下的白名单 :param filter_data: 过滤的字段 """ - ips_filters = Q(bk_biz_id=PLAT_BIZ_ID) | Q(bk_biz_id=filter_data["bk_biz_id"]) + ips_filters = (Q(bk_biz_id=PLAT_BIZ_ID) | Q(bk_biz_id=filter_data["bk_biz_id"])) & Q( + db_type=filter_data["db_type"] + ) if filter_data.get("ip"): ips_filters = ips_filters & Q(ips__contains=filter_data["ip"]) diff --git a/dbm-ui/backend/configuration/models/password_policy.py b/dbm-ui/backend/configuration/models/password_policy.py index 1d119229df..2c0912632c 100644 --- a/dbm-ui/backend/configuration/models/password_policy.py +++ b/dbm-ui/backend/configuration/models/password_policy.py @@ -16,10 +16,13 @@ from backend.bk_web.constants import LEN_SHORT from backend.configuration.constants import INIT_PASSWORD_POLICY, DBType +from backend.db_services.mysql.permission.constants import AccountType class PasswordPolicy(models.Model): - account_type = models.CharField(_("账号类型"), choices=DBType.get_choices(), max_length=LEN_SHORT, primary_key=True) + account_type = models.CharField( + _("账号类型"), choices=AccountType.get_choices(), max_length=LEN_SHORT, primary_key=True + ) policy = models.JSONField(_("密码安全策略")) class Meta: diff --git a/dbm-ui/backend/configuration/serializers.py b/dbm-ui/backend/configuration/serializers.py index a228a545db..bad0b52d46 100644 --- a/dbm-ui/backend/configuration/serializers.py +++ b/dbm-ui/backend/configuration/serializers.py @@ -20,6 +20,7 @@ from backend.configuration.models.function_controller import FunctionController from backend.configuration.models.ip_whitelist import IPWhitelist from backend.configuration.models.system import SystemSettings +from backend.db_services.mysql.permission.constants import AccountType class SystemSettingsSerializer(serializers.ModelSerializer): @@ -53,7 +54,7 @@ class UpsertDBAdminSerializer(serializers.Serializer): class PasswordPolicySerializer(serializers.Serializer): - account_type = serializers.ChoiceField(help_text=_("账号类型"), choices=DBType.get_choices()) + account_type = serializers.ChoiceField(help_text=_("账号类型"), choices=AccountType.get_choices()) policy = serializers.JSONField(help_text=_("密码安全策略")) class Meta: @@ -70,13 +71,14 @@ def validate(self, attrs): class GetPasswordPolicySerializer(serializers.Serializer): - account_type = serializers.ChoiceField(help_text=_("账号类型"), choices=DBType.get_choices()) + account_type = serializers.ChoiceField(help_text=_("账号类型"), choices=AccountType.get_choices()) class IPWhitelistSerializer(AuditedSerializer, serializers.ModelSerializer): bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) remark = serializers.CharField(help_text=_("备注")) ips = serializers.ListSerializer(help_text=_("ip列表"), child=serializers.CharField()) + db_type = serializers.ChoiceField(help_text=_("DB类型"), choices=DBType.get_choices(), default=DBType.MySQL) class Meta: model = IPWhitelist @@ -93,6 +95,9 @@ class ListIPWhitelistSerializer(serializers.Serializer): bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) ip = serializers.CharField(help_text=_("代过滤IP"), required=False, allow_null=True, allow_blank=True) ids = serializers.ListField(child=serializers.IntegerField(help_text=_("待过滤白名单ID")), required=False) + db_type = serializers.ChoiceField( + help_text=_("数据库类型"), choices=DBType.get_choices(), required=False, default=DBType.MySQL + ) class FunctionControllerSerializer(serializers.Serializer): diff --git a/dbm-ui/backend/configuration/views/ip_whitelist.py b/dbm-ui/backend/configuration/views/ip_whitelist.py index bca6fa42ae..ea52f47f1f 100644 --- a/dbm-ui/backend/configuration/views/ip_whitelist.py +++ b/dbm-ui/backend/configuration/views/ip_whitelist.py @@ -41,7 +41,7 @@ class IPWhitelistViewSet(viewsets.AuditedModelViewSet): pagination_class = AuditedLimitOffsetPagination def _get_custom_permissions(self): - bk_biz_id = self.request.query_params.get("bk_biz_id", 0) or self.request.data.get("bk_biz_id", 0) + bk_biz_id = self.request.query_params.get("bk_biz_id") or self.request.data.get("bk_biz_id") if bk_biz_id: return [DBManageIAMPermission()] diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/detail.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/detail.py index 65cd85d5f5..5a3808ea88 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/detail.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/detail.py @@ -63,6 +63,11 @@ def build_spider_remote_relations(role, spider_group, remote_group_name): entry_group_id=_("spider_slave_entry_bind"), entry_group_name=_("访问入口(从)"), ) + + # 建立spider_master和spider_slave之间的关系 + if spider_master_group and spider_slave_group: + graph.add_line(source=spider_master_group, target=spider_slave_group, label=LineLabel.Access) + # 建立spider master与remote db的关系 __, remote_db_group = build_spider_remote_relations( InstanceRole.REMOTE_MASTER, spider_group=spider_master_group, remote_group_name=_("RemoteDB") @@ -77,8 +82,8 @@ def build_spider_remote_relations(role, spider_group, remote_group_name): cluster, TenDBClusterSpiderRole.SPIDER_MNT, group_name=_("Spider 运维节点") ) if spider_mnt_insts: - graph.add_line(source=spider_mnt_insts, target=remote_db_group, label=LineLabel.Access) - graph.add_line(source=spider_mnt_insts, target=remote_dr_group, label=LineLabel.Access) + graph.add_line(source=spider_mnt_group, target=remote_db_group, label=LineLabel.Access) + graph.add_line(source=spider_mnt_group, target=remote_dr_group, label=LineLabel.Access) # 收纳中控节点 TODO: 如何表示关系 controller_group = Group(node_id=_("controller_group"), group_name=_("中控节点")) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py index b84afe98c0..b81909ecef 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbcluster/handler.py @@ -27,9 +27,9 @@ MachineType, TenDBClusterSpiderRole, ) -from backend.db_meta.models import Cluster, ClusterEntry, StorageInstanceTuple +from backend.db_meta.models import Cluster, ClusterEntry, ProxyInstance, StorageInstanceTuple from backend.db_package.models import Package -from backend.flow.consts import MediumEnum +from backend.flow.consts import MediumEnum, TenDBBackUpLocation from backend.flow.engine.bamboo.scene.common.get_real_version import get_mysql_real_version, get_spider_real_version from backend.flow.utils.mysql.bk_module_operate import create_bk_module_for_cluster_id, transfer_host_in_cluster_module from backend.flow.utils.spider.spider_act_dataclass import ShardInfo @@ -325,3 +325,27 @@ def remote_switch(cls, cluster_id: int, switch_tuples: list): "labels": {"instance_role": InstanceRole.BACKEND_SLAVE.value}, } ) + + def get_remote_address(self, role) -> str: + """ + 查询DRS访问远程数据库的地址 + """ + if role == TenDBBackUpLocation.SPIDER_MNT: + return ( + ProxyInstance.objects.filter( + cluster=self.cluster, tendbclusterspiderext__spider_role=TenDBClusterSpiderRole.SPIDER_MNT + ) + .first() + .ip_port + ) + else: + # TODO: 这部分存疑,该访问哪个实例(spider_master/remote)查询数据库?或者通过域名查询? + # cluster_id = self.cluster.id + # return ClusterEntry.get_cluster_entry_map_by_cluster_ids([cluster_id])[cluster_id]["master_domain"] + return ( + ProxyInstance.objects.filter( + cluster=self.cluster, tendbclusterspiderext__spider_role=TenDBClusterSpiderRole.SPIDER_MASTER + ) + .first() + .ip_port + ) diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbha/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbha/handler.py index 85b3da9ea5..7db730b120 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbha/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbha/handler.py @@ -161,6 +161,8 @@ def add_slaves(self, slaves: List[Dict]): def delete_slaves(self, slaves: List[Dict]): delete_slaves(self.cluster, slaves) - def get_exec_inst(self) -> StorageInstance: - """查询集群可执行的实例""" - return StorageInstance.objects.get(cluster=self.cluster, instance_inner_role=InstanceInnerRole.MASTER.value) + def get_remote_address(self) -> StorageInstance: + """查询DRS访问远程数据库的地址""" + return StorageInstance.objects.get( + cluster=self.cluster, instance_inner_role=InstanceInnerRole.MASTER.value + ).ip_port diff --git a/dbm-ui/backend/db_meta/api/cluster/tendbsingle/handler.py b/dbm-ui/backend/db_meta/api/cluster/tendbsingle/handler.py index b0ec6e51b4..fb308e000e 100644 --- a/dbm-ui/backend/db_meta/api/cluster/tendbsingle/handler.py +++ b/dbm-ui/backend/db_meta/api/cluster/tendbsingle/handler.py @@ -105,6 +105,6 @@ def topo_graph(self): """「必须」提供集群关系拓扑图""" return api.cluster.tendbsingle.scan_cluster(self.cluster).to_dict() - def get_exec_inst(self) -> StorageInstance: - """查询集群可执行的实例""" - return StorageInstance.objects.get(cluster=self.cluster) + def get_remote_address(self) -> StorageInstance: + """查询DRS访问远程数据库的地址""" + return StorageInstance.objects.get(cluster=self.cluster).ip_port diff --git a/dbm-ui/backend/db_meta/models/spec.py b/dbm-ui/backend/db_meta/models/spec.py index 58222024d0..7d651b354a 100644 --- a/dbm-ui/backend/db_meta/models/spec.py +++ b/dbm-ui/backend/db_meta/models/spec.py @@ -122,6 +122,17 @@ def get_spec_info(self): "storage_spec": self.storage_spec, } + def compare_to(self, spec: "Spec", compare_flag: bool): + """比较规格""" + # 比较存储配置里磁盘的最小值 TODO: TendisCache可能是内存比较 + self_min_config = min([storage.get("size", 0) for storage in self.storage_spec]) + spec_min_config = min([storage.get("size", 0) for storage in spec.storage_spec]) + + if compare_flag: + return self_min_config >= spec_min_config + else: + return self_min_config <= spec_min_config + class SnapshotSpec(AuditedModel): """ diff --git a/dbm-ui/backend/db_services/dbresource/serializers.py b/dbm-ui/backend/db_services/dbresource/serializers.py index 8e00680515..2a4b652a98 100644 --- a/dbm-ui/backend/db_services/dbresource/serializers.py +++ b/dbm-ui/backend/db_services/dbresource/serializers.py @@ -106,7 +106,18 @@ def format_fields(attrs, fields): def validate(self, attrs): self.format_fields( attrs, - fields=["for_bizs", "resource_types", "device_class", "hosts", "city", "subzones", "cpu", "mem", "disk"], + fields=[ + "for_bizs", + "resource_types", + "device_class", + "hosts", + "city", + "subzones", + "cpu", + "mem", + "disk", + "mount_point", + ], ) return attrs diff --git a/dbm-ui/backend/db_services/dbresource/views/sepc.py b/dbm-ui/backend/db_services/dbresource/views/sepc.py index 12d8d1e38c..87f6a91a6e 100644 --- a/dbm-ui/backend/db_services/dbresource/views/sepc.py +++ b/dbm-ui/backend/db_services/dbresource/views/sepc.py @@ -79,6 +79,13 @@ def _remove_spec_fields(self, machine_type, data): def create(self, request, *args, **kwargs): return super().create(request, *args, **kwargs) + @common_swagger_auto_schema( + operation_summary=_("规格详情"), + tags=[SWAGGER_TAG], + ) + def retrieve(self, request, *args, **kwargs): + return super().retrieve(request, *args, **kwargs) + @common_swagger_auto_schema( operation_summary=_("更新规格"), tags=[SWAGGER_TAG], @@ -160,13 +167,30 @@ def recommend_spec(self, request): cluster = Cluster.objects.get(id=data["cluster_id"]) filter_params = Q(cluster=cluster) & Q(role=data["role"]) - spec_ids = list( + # 根据角色获取StorageInstance关联的规格 + storage_spec_ids = ( StorageInstance.objects.annotate(role=F("instance_role")) .filter(filter_params) - .union(ProxyInstance.objects.annotate(role=F("access_layer")).filter(filter_params)) .values_list("machine__spec_id", flat=True) ) - spec_data = SpecSerializer(Spec.objects.filter(spec_id__in=spec_ids), many=True).data + + # 根据角色获取ProxyInstance关联的规格 + proxy_spec_ids = ( + ProxyInstance.objects.annotate(role=F("access_layer")) + .filter(filter_params) + .values_list("machine__spec_id", flat=True) + ) + + # 根据spider角色获取接入层关联的规格 + spider_spec_ids = ( + ProxyInstance.objects.prefetch_related("tendbclusterspiderext") + .filter(cluster=cluster, tendbclusterspiderext__spider_role=data["role"]) + .values_list("machine__spec_id", flat=True) + ) + + spec_data = SpecSerializer( + Spec.objects.filter(spec_id__in=[*storage_spec_ids, *proxy_spec_ids, *spider_spec_ids]), many=True + ).data return Response(spec_data) diff --git a/dbm-ui/backend/db_services/mysql/cluster/handlers.py b/dbm-ui/backend/db_services/mysql/cluster/handlers.py index 6d2496922a..6d1eef80ce 100644 --- a/dbm-ui/backend/db_services/mysql/cluster/handlers.py +++ b/dbm-ui/backend/db_services/mysql/cluster/handlers.py @@ -8,14 +8,23 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ +import itertools from collections import defaultdict from typing import Any, Dict, List, Set from django.db.models import Prefetch, Q +from django.db.models.query import QuerySet from django.forms import model_to_dict from django.utils.translation import ugettext_lazy as _ -from backend.db_meta.enums import AccessLayer, ClusterType, InstanceInnerRole +from backend.db_meta.enums import ( + AccessLayer, + ClusterType, + InstanceInnerRole, + InstanceRole, + InstanceStatus, + TenDBClusterSpiderRole, +) from backend.db_meta.exceptions import InstanceNotExistException from backend.db_meta.models import Cluster, DBModule, ProxyInstance, StorageInstance from backend.db_meta.models.machine import Machine @@ -126,15 +135,55 @@ def query_clusters(self, cluster_filters: List[ClusterFilter]) -> List[Dict[str, 根据过滤条件查询集群,默认是精确匹配 """ + def _fill_mysql_instance_info(_cluster: Cluster, _cluster_info: Dict): + _cluster_info["masters"] = [] + _cluster_info["slaves"] = [] + _cluster_info["repeaters"] = [] + # 录入proxy instance的信息和storage instance的信息 + _cluster_info["proxies"] = [inst.simple_desc for inst in _cluster.proxyinstance_set.all()] + for inst in _cluster.storageinstance_set.all(): + role = ( + "masters" if _cluster.cluster_type == ClusterType.TenDBSingle else f"{inst.instance_inner_role}s" + ) + _cluster_info[role].append(inst.simple_desc) + + def _fill_spider_instance_info(_cluster: Cluster, _cluster_info: Dict): + # 更新remote db/remote dr的信息 + _cluster_info.update( + { + "remote_db": [ + m.simple_desc + for m in _cluster.storageinstance_set.all() + if m.instance_inner_role == InstanceInnerRole.MASTER + ], + "remote_dr": [ + m.simple_desc + for m in _cluster.storageinstance_set.all() + if m.instance_inner_role == InstanceInnerRole.SLAVE + ], + } + ) + # 更新spider角色信息 + _cluster_info.update( + { + role: [ + inst.simple_desc + for inst in _cluster.proxyinstance_set.all() + if inst.tendbclusterspiderext.spider_role == role + ] + for role in TenDBClusterSpiderRole.get_values() + } + ) + filter_conditions = Q() for cluster_filter in cluster_filters: filter_conditions |= Q(**cluster_filter.export_filter_conditions()) - clusters = Cluster.objects.prefetch_related("storageinstance_set", "proxyinstance_set").filter( + clusters: QuerySet = Cluster.objects.prefetch_related("storageinstance_set", "proxyinstance_set").filter( filter_conditions ) - cluster_db_module_ids = [cluster.db_module_id for cluster in clusters] - db_module_names = { + cluster_db_module_ids: List[int] = [cluster.db_module_id for cluster in clusters] + db_module_names: Dict[int, str] = { module.db_module_id: module.db_module_name for module in DBModule.objects.filter(db_module_id__in=cluster_db_module_ids) } @@ -148,21 +197,20 @@ def query_clusters(self, cluster_filters: List[ClusterFilter]) -> List[Dict[str, cluster_info["instance_count"] = ( cluster.storageinstance_set.all().count() + cluster.proxyinstance_set.all().count() ) - cluster_info["masters"] = [] - cluster_info["slaves"] = [] - cluster_info["repeaters"] = [] - # 录入proxy instance的信息和storage instance的信息 - cluster_info["proxies"] = [inst.simple_desc for inst in cluster.proxyinstance_set.all()] - for inst in cluster.storageinstance_set.all(): - role = "masters" if cluster.cluster_type == ClusterType.TenDBSingle else f"{inst.instance_inner_role}s" - cluster_info[role].append(inst.simple_desc) + if cluster.cluster_type == ClusterType.TenDBCluster: + _fill_spider_instance_info(cluster, cluster_info) + else: + _fill_mysql_instance_info(cluster, cluster_info) filter_cluster_list.append(cluster_info) return filter_cluster_list - def get_intersected_machines_from_clusters(self, cluster_ids: List[int], role: str): + def get_intersected_machines_from_clusters(self, cluster_ids: List[int], role: str, is_stand_by: bool): """ + @param cluster_ids: 查询的集群ID列表 + @param role: 角色 + @param is_stand_by: 是否只过滤is_stand_by标志的实例,仅用于slave 获取关联集群特定实例角色的交集 cluster1: slave1, slave2, slave3 cluster2: slave1, slave2 @@ -184,6 +232,9 @@ def get_intersected_machines_from_clusters(self, cluster_ids: List[int], role: s instances = StorageInstance.objects.select_related("machine").filter( cluster__id__in=cluster_ids, instance_inner_role=role ) + if is_stand_by: + # 如果带有is_stand_by标志,则过滤出可用于切换的slave实例 + instances = instances.filter(is_stand_by=True, status=InstanceStatus.RUNNING) clusters: List[Cluster] = Cluster.objects.prefetch_related( Prefetch(lookup_field, queryset=instances, to_attr="instances") @@ -205,6 +256,48 @@ def get_intersected_machines_from_clusters(self, cluster_ids: List[int], role: s return intersected_machines_info + def get_remote_related_machines(self, cluster_ids: List[int]): + """ + 根据tendbcluster集群查询remote机器信息 + @param cluster_ids: 集群的ID列表 + ] + """ + # 获取remote master对应的机器 + clusters: QuerySet[Cluster] = Cluster.objects.prefetch_related("storageinstance_set").filter( + id__in=cluster_ids + ) + machine_ids: List[int] = list( + itertools.chain( + *[ + list( + cluster.storageinstance_set.select_related("machine") + .filter(instance_role=InstanceRole.REMOTE_MASTER) + .values_list("machine__bk_host_id", flat=True) + ) + for cluster in clusters + ] + ) + ) + master_machines: QuerySet[Machine] = Machine.objects.prefetch_related("storageinstance_set").filter( + bk_host_id__in=machine_ids + ) + + cluster_id__remote_machines: Dict[int, List[Dict]] = defaultdict(list) + for master_machine in master_machines: + # 查询master machine和slave machine + slave_instance: StorageInstance = master_machine.storageinstance_set.first().as_ejector.first().receiver + slave_machine: Machine = slave_instance.machine + cluster_id: int = slave_instance.cluster.first().id + cluster_id__remote_machines[cluster_id].append( + {"remote_master": model_to_dict(master_machine), "remote_slave": model_to_dict(slave_machine)} + ) + + remote_machine_infos: List[Dict[str, Any]] = [ + {"cluster_id": cluster_id, "remote_machines": cluster_id__remote_machines[cluster_id]} + for cluster_id in cluster_id__remote_machines.keys() + ] + return remote_machine_infos + def _format_cluster_field(self, cluster_info: Dict[str, Any]): cluster_info["cluster_name"] = cluster_info.pop("name") cluster_info["master_domain"] = cluster_info.pop("immute_domain") diff --git a/dbm-ui/backend/db_services/mysql/cluster/serializers.py b/dbm-ui/backend/db_services/mysql/cluster/serializers.py index db142a208b..ccbeb6be86 100644 --- a/dbm-ui/backend/db_services/mysql/cluster/serializers.py +++ b/dbm-ui/backend/db_services/mysql/cluster/serializers.py @@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from backend.db_meta.enums import InstanceRole from backend.db_services.mysql.cluster.mock_data import ( FIND_RELATED_CLUSTERS_BY_ID_REQUEST_DATA, FIND_RELATED_CLUSTERS_BY_ID_RESPONSE_DATA, @@ -77,6 +78,9 @@ class Meta: class GetIntersectedSlavaMachinesSerializer(serializers.Serializer): cluster_ids = serializers.ListField(help_text=_("集群ID列表"), child=serializers.IntegerField()) + is_stand_by = serializers.BooleanField( + help_text=_("is_stand_by标志(默认获取带有is_stand_by标志的slave)"), required=False, default=True + ) class Meta: swagger_schema_fields = {"example": FIND_RELATED_CLUSTERS_BY_ID_REQUEST_DATA} @@ -85,3 +89,12 @@ class Meta: class GetIntersectedSlavaMachinesResponseSerializer(serializers.Serializer): class Meta: swagger_schema_fields = {"example": GET_INTERSECTED_SLAVE_MACHINES_RESPONSE_DATA} + + +class GetTendbRemoteMachinesSerializer(serializers.Serializer): + cluster_ids = serializers.ListField(help_text=_("集群ID列表"), child=serializers.IntegerField()) + + +class GetTendbRemoteMachinesResponseSerializer(serializers.Serializer): + class Meta: + swagger_schema_fields = {"example": ""} diff --git a/dbm-ui/backend/db_services/mysql/cluster/views.py b/dbm-ui/backend/db_services/mysql/cluster/views.py index 60974242e4..72a45bd971 100644 --- a/dbm-ui/backend/db_services/mysql/cluster/views.py +++ b/dbm-ui/backend/db_services/mysql/cluster/views.py @@ -24,6 +24,8 @@ FindRelatedClustersByInstancesResponseSerializer, GetIntersectedSlavaMachinesResponseSerializer, GetIntersectedSlavaMachinesSerializer, + GetTendbRemoteMachinesResponseSerializer, + GetTendbRemoteMachinesSerializer, QueryClustersRequestSerializer, QueryClustersResponseSerializer, ) @@ -91,6 +93,21 @@ def get_intersected_slave_machines_from_clusters(self, request, bk_biz_id): validated_data = self.params_validate(self.get_serializer_class()) return Response( ClusterServiceHandler(bk_biz_id).get_intersected_machines_from_clusters( - cluster_ids=validated_data["cluster_ids"], role=InstanceInnerRole.SLAVE.value + cluster_ids=validated_data["cluster_ids"], + role=InstanceInnerRole.SLAVE.value, + is_stand_by=validated_data["is_stand_by"], ) ) + + @common_swagger_auto_schema( + operation_summary=_("查询tendbcluster集群的remote相关角色机器"), + request_body=GetTendbRemoteMachinesSerializer(), + tags=[SWAGGER_TAG], + responses={status.HTTP_200_OK: GetTendbRemoteMachinesResponseSerializer()}, + ) + @action(methods=["POST"], detail=False, serializer_class=GetTendbRemoteMachinesSerializer) + def get_remote_related_machines(self, request, bk_biz_id): + validated_data = self.params_validate(self.get_serializer_class()) + return Response( + ClusterServiceHandler(bk_biz_id).get_remote_related_machines(cluster_ids=validated_data["cluster_ids"]) + ) diff --git a/dbm-ui/backend/db_services/mysql/fixpoint_rollback/handlers.py b/dbm-ui/backend/db_services/mysql/fixpoint_rollback/handlers.py index 9d2ced42d2..686afee810 100644 --- a/dbm-ui/backend/db_services/mysql/fixpoint_rollback/handlers.py +++ b/dbm-ui/backend/db_services/mysql/fixpoint_rollback/handlers.py @@ -26,7 +26,7 @@ from backend.components import JobApi from backend.components.bklog.client import BKLogApi from backend.constants import DATETIME_PATTERN -from backend.db_meta.enums import InstanceInnerRole +from backend.db_meta.enums import ClusterType, InstanceInnerRole, TenDBClusterSpiderRole from backend.db_meta.models import StorageInstance from backend.db_meta.models.cluster import Cluster from backend.db_services.mysql.fixpoint_rollback.constants import BACKUP_LOG_ROLLBACK_TIME_RANGE_DAYS @@ -99,8 +99,15 @@ def _batch_make_job_requests(job_func: Callable, job_payloads: List[Dict]): return task_results - @staticmethod - def _format_job_backup_log(raw_backup_logs: List[str]) -> List[Dict[str, Any]]: + def _check_fixpoint_backup_log(self, log) -> bool: + if str(log["data_schema_grant"]).lower() == "all" or ( + "schema" in str(log["data_schema_grant"]).lower() and "data" in str(log["data_schema_grant"]).lower() + ): + return True + + return False + + def _format_job_backup_log(self, raw_backup_logs: List[str]) -> List[Dict[str, Any]]: """ 格式化本地备份记录日志 :param raw_backup_logs: 原始日志信息 @@ -114,10 +121,7 @@ def _format_job_backup_log(raw_backup_logs: List[str]) -> List[Dict[str, Any]]: log["mysql_role"] = log.pop("db_role") # 过滤适用于定点回档的备份 - if str(log["data_schema_grant"]).lower() == "all" or ( - "schema" in str(log["data_schema_grant"]).lower() - and "data" in str(log["data_schema_grant"]).lower() - ): + if self._check_fixpoint_backup_log(log): backup_logs.append(log) return backup_logs @@ -151,9 +155,36 @@ def _get_log_from_bklog(self, collector, start_time, end_time, query_string="*") return backup_logs @staticmethod - def aggregate_backup_log_by_id(backup_logs: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + def _format_backup_for_tendb(raw_log: Dict[str, Any], backup_log: Dict[str, Any]) -> Dict[str, Any]: + """ + 对tendb cluster的日志进行进一步的格式化 + @param backup_log: 通过aggregate_backup_log_by_id已经聚合后的日志 """ - 按照backup_id聚合备份记录 + # 初始化相关角色集合,并舍弃无用的字段信息 + if "remote_node" not in backup_log: + backup_log["remote_node"] = {} + backup_log["spider_node"], backup_log["spider_slave"] = [], [] + delete_fields = [ + "mysql_host", + "mysql_port", + "master_host", + "master_port", + "mysql_role", + "binlog_info", + "data_schema_grant", + ] + for field in delete_fields: + backup_log.pop(field) + + # 同一个backid中,取最小的backup_begin_time,最大的backup_end_time和最大的consistent_backup_time。 + # 因为是字典序比较,所以可以直接用来比较时间 + backup_log["backup_begin_time"] = min(backup_log["backup_begin_time"], raw_log["backup_begin_time"]) + backup_log["backup_end_time"] = min(backup_log["backup_end_time"], raw_log["backup_end_time"]) + backup_log["backup_time"] = max(backup_log["backup_time"], raw_log["consistent_backup_time"]) + + def aggregate_backup_log_by_id(self, backup_logs: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + 按照backup_id聚合mysql备份记录 :param backup_logs: 备份记录列表 """ backup_id__backup_logs_map = defaultdict(dict) @@ -166,7 +197,7 @@ def aggregate_backup_log_by_id(backup_logs: List[Dict[str, Any]]) -> List[Dict[s backup_id__backup_logs_map[backup_id]["file_list_details"] = [] # 丢弃一些聚合后无用字段 - delete_fields = ["consistent_backup_time", "file_name", "file_size", "task_id"] + delete_fields = ["consistent_backup_time", "file_name", "file_size", "task_id", "file_type"] for field in delete_fields: backup_id__backup_logs_map[backup_id].pop(field) @@ -180,6 +211,124 @@ def aggregate_backup_log_by_id(backup_logs: List[Dict[str, Any]]) -> List[Dict[s return list(backup_id__backup_logs_map.values()) + def aggregate_tendb_backup_log_by_id(self, backup_logs: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + 按照backup_id聚合tendb备份记录 + :param backup_logs: 备份记录列表 + """ + + def insert_time_field(_back_log, _log): + # 如果不具有时间字段则插入,否则更新 + if "backup_begin_time" not in _back_log: + _back_log["backup_begin_time"] = _log["backup_begin_time"] + _back_log["backup_end_time"] = _log["backup_end_time"] + _back_log["backup_time"] = _log["backup_time"] + else: + _back_log["backup_begin_time"] = min(_back_log["backup_begin_time"], _log["backup_begin_time"]) + _back_log["backup_end_time"] = max(_back_log["backup_end_time"], _log["backup_end_time"]) + _back_log["backup_time"] = max(_back_log["backup_time"], _log["backup_time"]) + + def insert_log_into_node(_backup_node, _log): + if _log["mysql_role"] in ["master", "slave"] and not self._check_fixpoint_backup_log(log): + return None + + if not _backup_node or ( + _log["mysql_host"] not in _backup_node + and ( + # 能覆盖的条件: + # 1. 如果是remote角色,则master能覆盖slave记录。同种角色可以时间接近rollback_time可以覆盖 + # 2. 如果是spider角色,则时间接近rollback_time可以覆盖 + ( + _log["mysql_role"] in ["spider_master", "spider_slave"] + and _log["consistent_backup_time"] > _backup_node["backup_time"] + ) + or ( + _log["mysql_role"] in ["master", "slave"] + and _log["mysql_role"] == "master" + and _backup_node.get("mysql_role", "slave") == "slave" + ) + or ( + _log["mysql_role"] in ["master", "slave"] + and _log["mysql_role"] == _backup_node["mysql_role"] + and _log["consistent_backup_time"] > _backup_node.get("backup_time", "") + ) + ) + ): + # 初始化该角色的备份信息 + insert_time_field(_backup_node, _log) + _backup_node["mysql_role"] = _log["mysql_role"] + _backup_node["host"], _backup_node["port"] = _log["mysql_host"], _log["mysql_port"] + _backup_node["file_list_details"] = [] + + # 更新备份时间,并插入文件列表信息 + insert_time_field(_backup_node, _log) + _backup_node["file_list_details"].append( + {"file_name": log["file_name"], "size": log["file_size"], "task_id": log["task_id"]} + ) + return _backup_node + + backup_id__backup_logs_map = defaultdict(dict) + for log in backup_logs: + log["backup_time"] = log["consistent_backup_time"] + backup_id = log["backup_id"] + if not backup_id__backup_logs_map.get(backup_id): + backup_id__backup_logs_map[backup_id].update(copy.deepcopy(log)) + # 初始化整体的角色信息 + backup_id__backup_logs_map[backup_id]["spider_node"] = {} + backup_id__backup_logs_map[backup_id]["spider_slave"] = {} + backup_id__backup_logs_map[backup_id]["remote_node"] = defaultdict(dict) + + # 丢弃一些聚合后无用字段 + delete_fields = [ + "consistent_backup_time", + "file_name", + "file_size", + "task_id", + "file_type", + "shard_value", + "mysql_host", + "mysql_port", + "master_host", + "master_port", + "binlog_info", + "data_schema_grant", + "backup_type", + ] + for field in delete_fields: + backup_id__backup_logs_map[backup_id].pop(field) + + # 把该日志插入对应的角色字典中 + if log["mysql_role"] in ["master", "slave"]: + backup_node = backup_id__backup_logs_map[backup_id]["remote_node"][log["shard_value"]] + backup_node = insert_log_into_node(backup_node, log) + else: + node_role = "spider_node" if log["mysql_role"] == "spider_master" else "spider_slave" + backup_node = backup_id__backup_logs_map[backup_id][node_role] + backup_node = insert_log_into_node(backup_node, log) + + # 更新备份时间 + if backup_node: + insert_time_field(backup_id__backup_logs_map[backup_id], backup_node) + + # 获取合法的备份记录 + cluster_shard_num = StorageInstance.objects.filter( + cluster=self.cluster, instance_inner_role=InstanceInnerRole.MASTER + ).count() + backup_id__valid_backup_logs = defaultdict(dict) + for backup_id, backup_log in backup_id__backup_logs_map.items(): + shard_value_list = list(backup_log["remote_node"].keys()) + # 如果分片数不完整,则忽略 + if sorted(shard_value_list) != list(range(0, cluster_shard_num)): + continue + + # 如果存在多条完整的backup记录,则保留最接近rollback time的记录 + if backup_id not in backup_id__valid_backup_logs or ( + backup_id__valid_backup_logs[backup_id]["backup_time"] < backup_log["backup_time"] + ): + backup_id__valid_backup_logs[backup_id] = backup_log + + return list(backup_id__valid_backup_logs.values()) + def query_backup_log_from_bklog(self, start_time: str, end_time: str) -> List[Dict]: """ 通过日志平台查询集群的时间范围内的备份记录 @@ -194,14 +343,25 @@ def query_backup_log_from_bklog(self, start_time: str, end_time: str) -> List[Di end_time=end_time, query_string=f'log: "cluster_address: \\"{cluster_domain}\\""', ) - return self.aggregate_backup_log_by_id(backup_logs) - def query_binlog_from_bklog(self, start_time: datetime, end_time: datetime, host_ip: str = None) -> Dict: + if self.cluster.cluster_type == ClusterType.TenDBCluster: + return self.aggregate_tendb_backup_log_by_id(backup_logs) + else: + return self.aggregate_backup_log_by_id(backup_logs) + + def query_binlog_from_bklog( + self, + start_time: Union[datetime, str], + end_time: Union[datetime, str], + host_ip: str = None, + minute_range: int = 20, + ) -> Dict: """ 通过日志平台查询集群的时间范围内的binlog记录 :param start_time: 开始时间 :param end_time: 结束时间 :param host_ip: 过滤的主机IP + :param minute_range: 前后时间范围 """ start_time, end_time = str2datetime(start_time), str2datetime(end_time) @@ -211,8 +371,8 @@ def query_binlog_from_bklog(self, start_time: datetime, end_time: datetime, host binlogs = self._get_log_from_bklog( collector="mysql_binlog_result", # 时间范围前后放大20min,避免日志平台上传延迟 - start_time=datetime2str(start_time - timedelta(minutes=20)), - end_time=datetime2str(end_time + timedelta(minutes=20)), + start_time=datetime2str(start_time - timedelta(minutes=minute_range)), + end_time=datetime2str(end_time + timedelta(minutes=minute_range)), query_string=f'log: "host: \\"{host_ip}\\""', ) @@ -227,7 +387,7 @@ def query_binlog_from_bklog(self, start_time: datetime, end_time: datetime, host "port": binlogs[0]["port"], "file_list_details": [], } - collector_fields = ["file_mtime", "start_time", "stop_time", "size", "backup_taskid"] + collector_fields = ["file_mtime", "start_time", "stop_time", "size", "task_id"] for log in binlogs: if str2datetime(log["stop_time"]) > end_time or str2datetime(log["stop_time"]) < start_time: continue diff --git a/dbm-ui/backend/db_services/mysql/permission/authorize/handlers.py b/dbm-ui/backend/db_services/mysql/permission/authorize/handlers.py index 0e78609c08..a529a0b6fb 100644 --- a/dbm-ui/backend/db_services/mysql/permission/authorize/handlers.py +++ b/dbm-ui/backend/db_services/mysql/permission/authorize/handlers.py @@ -118,9 +118,11 @@ def pre_check_excel_rules(self, excel_authorize: ExcelAuthorizeMeta) -> Dict: pre_check: bool = True for future in as_completed(tasks): + # 获取线程执行的授权结果 task_result = future.result() uid, __, index = task_result["authorize_uid"], task_result["message"], task_result["task_index"] + # 将缓存数据取出放到excel缓存数据的切片中 data = cache.get(uid)[0] pre_check &= task_result["pre_check"] @@ -128,10 +130,9 @@ def pre_check_excel_rules(self, excel_authorize: ExcelAuthorizeMeta) -> Dict: to_cache_data_list[index] = data raw_authorize_data_list[index] = task_result["authorize_data"] - # 缓存授权数据,用于授权单据创建,并返回校验结果 + # 缓存excel授权数据,删除线程中pre_check产生的缓存,并返回校验结果 cache.delete_many(to_delete_cache_uid_list) authorize_uid = data_cache(key=None, data=to_cache_data_list, cache_time=AUTHORIZE_DATA_EXPIRE_TIME) - excel_url = ( f"{env.BK_SAAS_HOST}/apis/mysql/bizs/{self.bk_biz_id}/permission/authorize" f"/get_authorize_info_excel/?authorize_uid={authorize_uid}" diff --git a/dbm-ui/backend/db_services/mysql/permission/clone/handlers.py b/dbm-ui/backend/db_services/mysql/permission/clone/handlers.py index 2bf18fd4b7..15cd493e9a 100644 --- a/dbm-ui/backend/db_services/mysql/permission/clone/handlers.py +++ b/dbm-ui/backend/db_services/mysql/permission/clone/handlers.py @@ -17,6 +17,7 @@ from backend import env from backend.components.mysql_priv_manager.client import MySQLPrivManagerApi +from backend.db_meta.models import Machine from backend.db_services.dbbase.instances.handlers import InstanceHandler from backend.db_services.mysql.permission.clone.dataclass import CloneMeta from backend.db_services.mysql.permission.clone.models import MySQLPermissionCloneRecord @@ -35,7 +36,7 @@ class CloneHandler(object): 封装权限克隆相关的处理操作 """ - def __init__(self, bk_biz_id: int, operator: str, clone_type: str, context: Dict = None): + def __init__(self, bk_biz_id: int, operator: str, clone_type: str, cluster_type: str, context: Dict = None): """ :param bk_biz_id: 业务ID :param context: 上下文数据 @@ -43,14 +44,15 @@ def __init__(self, bk_biz_id: int, operator: str, clone_type: str, context: Dict self.bk_biz_id = bk_biz_id self.clone_type = clone_type + self.cluster_type = cluster_type self.context = context self.operator = operator - def get_address__machine_map(self, clone_instance_list): + def get_address__machine_map(self, clone_instance_list) -> Dict[str, Machine]: """根据克隆数据得到address/ip_port与机器信息的字典关系""" # 如果不存在相应的数据和键,则直接返回 if not clone_instance_list or "source" not in clone_instance_list[0]: - return None + return {} address_list = [] for clone_data in clone_instance_list: @@ -88,41 +90,46 @@ def _get_instance_check_records(self, clone_data_list): ] return clone_priv_records - def pre_check_clone(self, clone: CloneMeta) -> Dict: + def pre_check_clone(self, clone: CloneMeta) -> Dict[str, Any]: """ - - 实例间权限克隆前置检查 + - 客户端/实例 权限克隆前置检查 :param clone: 实例间权限克隆元数据 """ # 前置校验参数字段名格式化 - pre_check, message = True, "ok" if self.clone_type == CloneType.CLIENT: clone_priv_records = self._get_client_check_records(clone.clone_list) else: clone_priv_records = self._get_instance_check_records(clone.clone_list) # 对克隆参数进行前置校验 - clone_api_field = f"pre_check_clone_{self.clone_type}" - clone_priv_records_field = f"clone_{self.clone_type}_priv_records" - params = {"bk_biz_id": self.bk_biz_id, clone_priv_records_field: clone_priv_records} + params: Dict[str, Any] = { + "bk_biz_id": self.bk_biz_id, + "cluster_type": self.cluster_type, + f"clone_{self.clone_type}_priv_records": clone_priv_records, + } try: - raw_resp = getattr(MySQLPrivManagerApi, clone_api_field)(params=params, raw=True) + raw_resp = getattr(MySQLPrivManagerApi, f"pre_check_clone_{self.clone_type}")(params=params, raw=True) if raw_resp["message"]: # 捕获接口返回结果异常,更新克隆权限错误信息 pre_check, message = False, raw_resp["message"] - error_pattern = re.compile(r"line ([0-9]+):(.*)") - error_msg_list = error_pattern.findall(message) + error_msg_list: List[str] = re.compile(r"line ([0-9]+):(.*)").findall(message) + for err_index, err_msg in error_msg_list: clone.clone_list[int(err_index) - 1].update({"message": err_msg}) except Exception as e: # pylint: disable=broad-except # 捕获接口其他未知异常 pre_check, message = False, _("「接口调用异常」{}").format(e) + for clone_data in clone.clone_list: clone_data.update({"message": message}) - clone_uid = data_cache(key=None, data=clone.clone_list, cache_time=CLONE_DATA_EXPIRE_TIME) + else: + pre_check, message = True, "ok" + # 缓存后返回当前的校验结果 + clone_uid: str = data_cache(key=None, data=clone.clone_list, cache_time=CLONE_DATA_EXPIRE_TIME) return { "pre_check": pre_check, "message": message, diff --git a/dbm-ui/backend/db_services/mysql/permission/clone/serializers.py b/dbm-ui/backend/db_services/mysql/permission/clone/serializers.py index 1b914e597a..a075be30d0 100644 --- a/dbm-ui/backend/db_services/mysql/permission/clone/serializers.py +++ b/dbm-ui/backend/db_services/mysql/permission/clone/serializers.py @@ -12,24 +12,27 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from backend.configuration.constants import DBType from backend.db_meta.request_validator import validate_instance_in_biz from backend.db_services.mysql.permission.clone import mock_data from backend.db_services.mysql.permission.constants import CLONE_EXCEL_HEADER_MAP, CloneType from backend.utils.excel import ExcelHandler -class CloneElementSerializer(serializers.Serializer): - source = serializers.CharField(help_text=_("旧实例/旧客户端IP")) - target = serializers.CharField(help_text=_("新实例/新客户端IP")) - bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) - module = serializers.CharField(help_text=_("模块名"), required=False) - cluster_domain = serializers.CharField(help_text=_("集群域名"), required=False) - - class Meta: - swagger_schema_fields = {"example": mock_data.CLONE_INSTANCE_DATA} - - class PreCheckCloneSerializer(serializers.Serializer): + class CloneElementSerializer(serializers.Serializer): + source = serializers.CharField(help_text=_("旧实例/旧客户端IP")) + target = serializers.CharField(help_text=_("新实例/新客户端IP")) + bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) + module = serializers.CharField(help_text=_("模块名"), required=False) + cluster_domain = serializers.CharField(help_text=_("集群域名"), required=False) + + class Meta: + swagger_schema_fields = {"example": mock_data.CLONE_INSTANCE_DATA} + + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=DBType.get_choices(), required=False, default=DBType.MySQL + ) clone_type = serializers.ChoiceField(help_text=_("权限克隆类型"), choices=CloneType.get_choices()) clone_list = serializers.ListField( help_text=_("克隆元素列表"), child=CloneElementSerializer(help_text=_("克隆元素信息")), min_length=1 @@ -82,6 +85,9 @@ class Meta: class PreCheckExcelCloneSerializere(serializers.Serializer): clone_file = serializers.FileField(help_text=_("克隆实例/客户端excel文件")) clone_type = serializers.ChoiceField(help_text=_("权限克隆类型"), choices=CloneType.get_choices()) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=DBType.get_choices(), required=False, default=DBType.MySQL + ) def validate(self, attrs): clone_excel_file = attrs["clone_file"].file diff --git a/dbm-ui/backend/db_services/mysql/permission/clone/views.py b/dbm-ui/backend/db_services/mysql/permission/clone/views.py index 03eb9ae002..96aaa95183 100644 --- a/dbm-ui/backend/db_services/mysql/permission/clone/views.py +++ b/dbm-ui/backend/db_services/mysql/permission/clone/views.py @@ -52,6 +52,7 @@ def _view_common_handler( "bk_biz_id": bk_biz_id, "operator": request.user.username, "clone_type": validated_data["clone_type"], + "account_type": validated_data.pop("account_type", None), "context": {}, } meta_init_data = meta.from_dict(validated_data) diff --git a/dbm-ui/backend/db_services/mysql/permission/constants.py b/dbm-ui/backend/db_services/mysql/permission/constants.py index 969271d8d3..656c9e6072 100644 --- a/dbm-ui/backend/db_services/mysql/permission/constants.py +++ b/dbm-ui/backend/db_services/mysql/permission/constants.py @@ -45,6 +45,7 @@ class AccountType(str, StructuredEnum): """账号类型枚举""" MYSQL = EnumField("mysql", _("MySQL")) + Tendb = EnumField("tendbcluster", _("TendbCluster")) class AuthorizeExcelTypeID(str, StructuredEnum): diff --git a/dbm-ui/backend/db_services/mysql/permission/db_account/handlers.py b/dbm-ui/backend/db_services/mysql/permission/db_account/handlers.py index 914c017a75..220fb32d40 100644 --- a/dbm-ui/backend/db_services/mysql/permission/db_account/handlers.py +++ b/dbm-ui/backend/db_services/mysql/permission/db_account/handlers.py @@ -15,6 +15,7 @@ from backend.configuration.models.password_policy import PasswordPolicy from backend.core.encrypt.constants import RSAConfigType from backend.core.encrypt.handlers import RSAHandler +from backend.db_meta.enums import ClusterType from backend.db_services.mysql.permission.constants import AccountType from backend.db_services.mysql.permission.db_account.dataclass import AccountMeta, AccountRuleMeta from backend.db_services.mysql.permission.db_account.policy import DBPasswordPolicy @@ -25,26 +26,26 @@ class AccountHandler(object): 封装账号相关的处理操作 """ - def __init__(self, bk_biz_id: int, operator: str = None, context: Dict = None): + def __init__(self, bk_biz_id: int, cluster_type: AccountType, operator: str = None, context: Dict = None): """ - :param bk_biz_id: 业务ID - :param operator: 操作者 - :param context: 上下文数据 + @param bk_biz_id: 业务ID + @param account_type: 账号类型,目前区分与mysql和tendbcluster + @param operator: 操作者 + @param context: 上下文数据 """ - self.bk_biz_id = bk_biz_id + self.cluster_type = cluster_type self.operator = operator self.context = context @staticmethod - def _check_pwd_strength(password: str, rule_data: Dict) -> Tuple[bool, Dict[str, bool]]: + def _check_password_strength(password: str, rule_data: Dict) -> Tuple[bool, Dict[str, bool]]: """ - 检查密码是否符合平台预设强度 - :param password: 待校验密码 - :param rule_data: 密码强度规则 - :returns: 密码校验是否成功和校验信息 + @param password: 待校验密码 + @param rule_data: 密码强度规则 + @returns: 密码校验是否成功和校验信息 """ - # 完善密码强度规则信息 follow = rule_data.pop("follow") for rule in follow.keys(): @@ -54,34 +55,29 @@ def _check_pwd_strength(password: str, rule_data: Dict) -> Tuple[bool, Dict[str, rule_data[f"follow_{rule}"] = follow["limit"] if follow[rule] else rule_data["max_length"] policy = DBPasswordPolicy(**rule_data) - - is_validity = policy.validate(password) - validity_map = policy.get_validity_map() + is_validity, validity_map = policy.validate(password), policy.get_validity_map() return is_validity, validity_map @staticmethod - def _cipher_password(password: str) -> str: + def _encrypt_password(password: str) -> str: """ - - 将password利用公钥加密 + - 获取后台公钥,将password利用公钥加密 :param password: 待加密密码 """ - public_key = MySQLPrivManagerApi.fetch_public_key() return RSAHandler.encrypt_password(public_key=public_key, password=password, salt=None) @staticmethod def _decrypt_password(password: str) -> str: """ - - 将password利用私钥解密 + - 获取saas侧私钥,将password利用私钥解密 :param password: 待解密密码 """ - rsa_private_key = RSAHandler.get_or_generate_rsa_in_db(name=RSAConfigType.MYSQL.value).rsa_private_key return RSAHandler.decrypt_password(private_key=rsa_private_key.content, password=password, salt=None) def _format_account_rules(self, account_rules_list: Dict) -> Dict: """格式化账号权限列表信息""" - for account_rules in account_rules_list["items"]: account_rules["account"]["account_id"] = account_rules["account"].pop("id") @@ -92,18 +88,16 @@ def _format_account_rules(self, account_rules_list: Dict) -> Dict: return account_rules_list - @classmethod - def verify_password_strength(cls, account: AccountMeta) -> Dict: + def verify_password_strength(self, account: AccountMeta) -> Dict: """ - 校验密码强度 :param account: 账号元信息 """ - - password = cls._decrypt_password(account.password) - password_policy = PasswordPolicy.safe_get(AccountType.MYSQL.value) + password = self._decrypt_password(account.password) + password_policy = PasswordPolicy.safe_get(self.cluster_type) if password_policy: - is_strength, password_verify_info = cls._check_pwd_strength(password, password_policy.policy) + is_strength, password_verify_info = self._check_password_strength(password, password_policy.policy) return {"is_strength": is_strength, "password_verify_info": password_verify_info, "password": password} return {"is_strength": True, "password_verify_info": {}, "password": password} @@ -111,15 +105,15 @@ def verify_password_strength(cls, account: AccountMeta) -> Dict: def create_account(self, account: AccountMeta) -> Optional[Any]: """ - 新建一个账号 - :param account: 账号元信息 + @param account: 账号元信息 """ - resp = MySQLPrivManagerApi.create_account( { + "cluster_type": self.cluster_type, "bk_biz_id": self.bk_biz_id, "operator": self.operator, "user": account.user, - "psw": self._cipher_password(account.password), + "psw": self._encrypt_password(account.password), } ) return resp @@ -127,26 +121,30 @@ def create_account(self, account: AccountMeta) -> Optional[Any]: def delete_account(self, account: AccountMeta) -> Optional[Any]: """ - 删除账号(仅在账号不存在存量规则时) - :param account: 账号元信息 + @param account: 账号元信息 """ - resp = MySQLPrivManagerApi.delete_account( - {"bk_biz_id": self.bk_biz_id, "operator": self.operator, "id": account.account_id} + { + "bk_biz_id": self.bk_biz_id, + "operator": self.operator, + "cluster_type": self.cluster_type, + "id": account.account_id, + } ) return resp def update_password(self, account: AccountMeta) -> Optional[Any]: """ - 修改账号密码 - :param account: 账号元信息 + @param account: 账号元信息 """ - resp = MySQLPrivManagerApi.update_password( { + "cluster_type": self.cluster_type, "bk_biz_id": self.bk_biz_id, "operator": self.operator, "id": account.account_id, - "psw": self._cipher_password(account.password), + "psw": self._encrypt_password(account.password), } ) return resp @@ -154,13 +152,13 @@ def update_password(self, account: AccountMeta) -> Optional[Any]: def add_account_rule(self, account_rule: AccountRuleMeta) -> Optional[Any]: """ - 添加账号规则 - :param account_rule: 账号规则元信息 + @param account_rule: 账号规则元信息 """ - resp = MySQLPrivManagerApi.add_account_rule( { "bk_biz_id": self.bk_biz_id, "creator": self.operator, + "cluster_type": self.cluster_type, "account_id": account_rule.account_id, "priv": account_rule.privilege, "dbname": account_rule.access_db, @@ -171,7 +169,9 @@ def add_account_rule(self, account_rule: AccountRuleMeta) -> Optional[Any]: def query_account_rules(self, account_rule: AccountRuleMeta): """查询某个账号下的权限""" - account_rules_list = MySQLPrivManagerApi.list_account_rules({"bk_biz_id": self.bk_biz_id}) + account_rules_list = MySQLPrivManagerApi.list_account_rules( + {"bk_biz_id": self.bk_biz_id, "cluster_type": self.cluster_type} + ) account_rules_list = self._format_account_rules(account_rules_list) # 根据账号名和准许db过滤规则 @@ -192,7 +192,9 @@ def query_account_rules(self, account_rule: AccountRuleMeta): def list_account_rules(self, rule_filter: AccountRuleMeta) -> Dict: """列举规则清单""" - account_rules_list = MySQLPrivManagerApi.list_account_rules({"bk_biz_id": self.bk_biz_id}) + account_rules_list = MySQLPrivManagerApi.list_account_rules( + {"bk_biz_id": self.bk_biz_id, "cluster_type": self.cluster_type} + ) account_rules_list = self._format_account_rules(account_rules_list) # 不存在过滤条件则直接返回 @@ -235,6 +237,7 @@ def modify_account_rule(self, account_rule: AccountRuleMeta) -> Optional[Any]: { "bk_biz_id": self.bk_biz_id, "operator": self.operator, + "cluster_type": self.cluster_type, "id": account_rule.rule_id, "account_id": account_rule.account_id, "dbname": account_rule.access_db, @@ -253,6 +256,7 @@ def delete_account_rule(self, account_rule: AccountRuleMeta) -> Optional[Any]: { "bk_biz_id": self.bk_biz_id, "operator": self.operator, + "cluster_type": self.cluster_type, "id": [account_rule.rule_id], } ) diff --git a/dbm-ui/backend/db_services/mysql/permission/db_account/serializers.py b/dbm-ui/backend/db_services/mysql/permission/db_account/serializers.py index 2217b5df8b..84b27df6b7 100644 --- a/dbm-ui/backend/db_services/mysql/permission/db_account/serializers.py +++ b/dbm-ui/backend/db_services/mysql/permission/db_account/serializers.py @@ -14,35 +14,36 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers -from backend.db_services.mysql.permission.constants import PrivilegeType +from backend.db_services.mysql.permission.constants import AccountType, PrivilegeType from backend.db_services.mysql.permission.db_account import mock_data from backend.db_services.mysql.permission.db_account.dataclass import AccountMeta from backend.db_services.mysql.permission.db_account.handlers import AccountHandler class DBAccountBaseSerializer(serializers.Serializer): - user = serializers.CharField(help_text=_("账号名称")) + user = serializers.CharField(help_text=_("账号名称"), required=False) password = serializers.CharField(help_text=_("账号密码")) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) - def validate_user(self, value): - """校验账号是否符合规则""" - - pattern = re.compile(r"^[0-9a-zA-Z][0-9a-zA-Z\-._]{0,31}$") - - if not re.match(pattern, value): - raise serializers.ValidationError(_("账号名称不符合要求, 请重新账号名")) - - return value - - def validate_password(self, value): - """将密码进行解密并校验密码强度""" - - account = AccountMeta(password=value) - verify_result = AccountHandler.verify_password_strength(account) + def validate(self, attrs): + # 校验账号是否符合规则 + if attrs.get("user"): + user_pattern = re.compile(r"^[0-9a-zA-Z][0-9a-zA-Z\-._]{0,31}$") + if not re.match(user_pattern, attrs["user"]): + raise serializers.ValidationError(_("账号名称不符合要求, 请重新账号名")) + + # 将密码进行解密并校验密码强度 + account = AccountMeta(password=attrs["password"]) + verify_result = AccountHandler(bk_biz_id=0, cluster_type=attrs["cluster_type"]).verify_password_strength( + account + ) if not verify_result["is_strength"]: - raise serializers.ValidationError(_("密码强度不符合要求, 请重新输入密码")) + raise serializers.ValidationError(_("密码强度不符合要求,请重新输入密码。")) - return verify_result["password"] + attrs["password"] = verify_result["password"] + return attrs class CreateMySQLAccountSerializer(DBAccountBaseSerializer): @@ -51,6 +52,9 @@ class Meta: class VerifyPasswordStrengthSerializer(serializers.Serializer): + cluster_type = serializers.ChoiceField( + help_text=_("集群类型(默认为mysql)"), choices=AccountType.get_choices(), required=False, default=AccountType.MYSQL + ) password = serializers.CharField(help_text=_("待校验密码")) class Meta: @@ -67,6 +71,9 @@ class Meta: class DeleteMySQLAccountSerializer(serializers.Serializer): account_id = serializers.IntegerField(help_text=_("账号ID")) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) class Meta: swagger_schema_fields = {"example": mock_data.DELETE_ACCOUNT_REQUEST} @@ -80,25 +87,23 @@ class Meta: swagger_schema_fields = {"example": mock_data.UPDATE_ACCOUNT_REQUEST} -class MySQLAccountInfoSerializer(DBAccountBaseSerializer): - bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) - user = serializers.CharField(help_text=_("账号名称")) - account_id = serializers.IntegerField(help_text=_("账号ID")) - creator = serializers.CharField(help_text=_("创建者")) - create_time = serializers.DateTimeField(help_text=_("创建时间")) - - -class MySQLAccountRulesInfoSerializer(serializers.Serializer): - rule_id = serializers.IntegerField(help_text=_("规则ID")) - account_id = serializers.IntegerField(help_text=_("账号ID")) - bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) - access_db = serializers.CharField(help_text=_("访问DB")) - privilege = serializers.CharField(help_text=_("规则列表")) - creator = serializers.CharField(help_text=_("创建者")) - create_time = serializers.DateTimeField(help_text=_("创建时间")) - - class MySQLAccountRulesDetailSerializer(serializers.Serializer): + class MySQLAccountInfoSerializer(DBAccountBaseSerializer): + bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) + user = serializers.CharField(help_text=_("账号名称")) + account_id = serializers.IntegerField(help_text=_("账号ID")) + creator = serializers.CharField(help_text=_("创建者")) + create_time = serializers.DateTimeField(help_text=_("创建时间")) + + class MySQLAccountRulesInfoSerializer(serializers.Serializer): + rule_id = serializers.IntegerField(help_text=_("规则ID")) + account_id = serializers.IntegerField(help_text=_("账号ID")) + bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) + access_db = serializers.CharField(help_text=_("访问DB")) + privilege = serializers.CharField(help_text=_("规则列表")) + creator = serializers.CharField(help_text=_("创建者")) + create_time = serializers.DateTimeField(help_text=_("创建时间")) + account = MySQLAccountInfoSerializer(help_text=_("账号信息")) rules = serializers.ListSerializer( help_text=_("权限列表信息"), allow_empty=True, child=MySQLAccountRulesInfoSerializer() @@ -109,11 +114,17 @@ class FilterMySQLAccountRulesSerializer(serializers.Serializer): user = serializers.CharField(help_text=_("账号名称"), required=False) access_db = serializers.CharField(help_text=_("访问DB"), required=False) privilege = serializers.CharField(help_text=_("规则列表"), required=False) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) class QueryMySQLAccountRulesSerializer(serializers.Serializer): user = serializers.CharField(help_text=_("账号名称")) access_dbs = serializers.ListField(help_text=_("访问DB列表"), child=serializers.CharField(), required=False) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) class ListMySQLAccountRulesSerializer(serializers.Serializer): @@ -126,22 +137,26 @@ class Meta: swagger_schema_fields = {"example": mock_data.LIST_MYSQL_ACCOUNT_RULE_RESPONSE} -class MySQLRuleTypeSerializer(serializers.Serializer): - dml = serializers.ListField( - help_text=_("dml"), child=serializers.ChoiceField(choices=PrivilegeType.DML.get_choices()), required=False - ) - ddl = serializers.ListField( - help_text=_("dml"), child=serializers.ChoiceField(choices=PrivilegeType.DDL.get_choices()), required=False - ) - glob = serializers.ListField( - help_text=_("glob"), child=serializers.ChoiceField(choices=PrivilegeType.GLOBAL.get_choices()), required=False - ) - - class AddMySQLAccountRuleSerializer(serializers.Serializer): + class MySQLRuleTypeSerializer(serializers.Serializer): + dml = serializers.ListField( + help_text=_("dml"), child=serializers.ChoiceField(choices=PrivilegeType.DML.get_choices()), required=False + ) + ddl = serializers.ListField( + help_text=_("dml"), child=serializers.ChoiceField(choices=PrivilegeType.DDL.get_choices()), required=False + ) + glob = serializers.ListField( + help_text=_("glob"), + child=serializers.ChoiceField(choices=PrivilegeType.GLOBAL.get_choices()), + required=False, + ) + account_id = serializers.IntegerField(help_text=_("账号ID")) access_db = serializers.CharField(help_text=_("访问DB")) privilege = MySQLRuleTypeSerializer() + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) class Meta: swagger_schema_fields = {"example": mock_data.ADD_MYSQL_ACCOUNT_RULE_REQUEST} @@ -156,6 +171,9 @@ class Meta: class DeleteMySQLAccountRuleSerializer(serializers.Serializer): rule_id = serializers.IntegerField(help_text=_("规则ID")) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=AccountType.get_choices(), default=AccountType.MYSQL + ) class Meta: swagger_schema_fields = {"example": mock_data.DELETE_MYSQL_ACCOUNT_RULE_REQUEST} diff --git a/dbm-ui/backend/db_services/mysql/permission/db_account/views.py b/dbm-ui/backend/db_services/mysql/permission/db_account/views.py index aaec38dab8..6779e55c63 100644 --- a/dbm-ui/backend/db_services/mysql/permission/db_account/views.py +++ b/dbm-ui/backend/db_services/mysql/permission/db_account/views.py @@ -51,9 +51,13 @@ def _view_common_handler( :param meta: 元信息数据结构 :param func: handler的回调函数名称 """ - - base_info = {"bk_biz_id": bk_biz_id, "operator": request.user.username, "context": {}} validated_data = self.params_validate(self.get_serializer_class()) + base_info = { + "bk_biz_id": bk_biz_id, + "operator": request.user.username, + "cluster_type": validated_data.pop("cluster_type", None), + "context": {}, + } meta_init_data = meta.from_dict(validated_data) return Response(getattr(AccountHandler(**base_info), func)(meta_init_data)) diff --git a/dbm-ui/backend/db_services/mysql/remote_service/handlers.py b/dbm-ui/backend/db_services/mysql/remote_service/handlers.py index 6f8609ea97..73b9ec5a79 100644 --- a/dbm-ui/backend/db_services/mysql/remote_service/handlers.py +++ b/dbm-ui/backend/db_services/mysql/remote_service/handlers.py @@ -22,8 +22,14 @@ class RemoteServiceHandler: def __init__(self, bk_biz_id: int): self.bk_biz_id = bk_biz_id - def show_databases(self, cluster_ids: List[int]) -> List[Dict[str, Union[int, List[str]]]]: - """批量查询集群的数据库列表""" + def show_databases( + self, cluster_ids: List[int], cluster_id__role_map: Dict[int, str] = None + ) -> List[Dict[str, Union[int, List[str]]]]: + """ + 批量查询集群的数据库列表 + @param cluster_ids: 集群ID列表 + @param cluster_id__role_map: (可选)集群ID和对应查询库表角色的映射表 + """ # 如果集群列表为空,则提前返回 if not cluster_ids: @@ -37,10 +43,13 @@ def show_databases(self, cluster_ids: List[int]) -> List[Dict[str, Union[int, Li # 查询各个集群可执行的实例地址 for cluster_id in cluster_ids: cluster_handler = ClusterHandler.get_exact_handler(bk_biz_id=self.bk_biz_id, cluster_id=cluster_id) - inst = cluster_handler.get_exec_inst() + if cluster_id__role_map.get(cluster_id): + address = cluster_handler.get_remote_address(cluster_id__role_map[cluster_id]) + else: + address = cluster_handler.get_remote_address() + bk_cloud_id = cluster_handler.cluster.bk_cloud_id - address = f"{inst.machine.ip}{IP_PORT_DIVIDER}{inst.port}" - cloud_addresses[bk_cloud_id].append(f"{inst.machine.ip}{IP_PORT_DIVIDER}{inst.port}") + cloud_addresses[bk_cloud_id].append(address) address_cluster_id_map[bk_cloud_id][address] = cluster_id # 批量查询实例地址对应的数据库列表 @@ -86,7 +95,7 @@ def check_cluster_database(self, cluster_ids: List[int], db_names: List[str]) -> master_inst__cluster_map: Dict[str, int] = {} for cluster_id in cluster_ids: cluster_handler = ClusterHandler.get_exact_handler(bk_biz_id=self.bk_biz_id, cluster_id=cluster_id) - master_inst__cluster_map[cluster_handler.get_exec_inst().ip_port] = cluster_id + master_inst__cluster_map[cluster_handler.get_remote_address()] = cluster_id raw_db_names = [f"'{db_name}'" for db_name in db_names] rpc_results = DRSApi.rpc( diff --git a/dbm-ui/backend/db_services/mysql/resources/spider/query.py b/dbm-ui/backend/db_services/mysql/resources/spider/query.py index 5fcd43123c..23e74cf00b 100644 --- a/dbm-ui/backend/db_services/mysql/resources/spider/query.py +++ b/dbm-ui/backend/db_services/mysql/resources/spider/query.py @@ -104,10 +104,12 @@ def _to_cluster_representation( "spider_slave": spider[TenDBClusterSpiderRole.SPIDER_SLAVE], "spider_mnt": spider[TenDBClusterSpiderRole.SPIDER_MNT], # TODO: 待补充当前集群使用容量,需要监控采集的支持 - "cluster_shard_num": len(spider[TenDBClusterSpiderRole.SPIDER_MASTER]), - "remote_shard_num": len(spider[TenDBClusterSpiderRole.SPIDER_MASTER]) / machine_pair_cnt, + "cluster_shard_num": len(remote_db), + "remote_shard_num": len(remote_db) / machine_pair_cnt, "machine_pair_cnt": machine_pair_cnt, + "remote_db": remote_db, "remote_dr": remote_dr, + "db_module_id": cluster.db_module_id, "db_module_name": db_module_names.get(cluster.db_module_id, ""), "creator": cluster.creator, "create_at": datetime2str(cluster.create_at), diff --git a/dbm-ui/backend/db_services/mysql/sql_import/constants.py b/dbm-ui/backend/db_services/mysql/sql_import/constants.py index 06f32768d6..6286f27faa 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/constants.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/constants.py @@ -13,7 +13,7 @@ BKREPO_SQLFILE_PATH = "mysql/sqlfile" -CACHE_SEMANTIC_TASK_FIELD = "{user}_semantic_check_task" +CACHE_SEMANTIC_TASK_FIELD = "{user}_{cluster_type}_semantic_check_task" CACHE_SEMANTIC_AUTO_COMMIT_FIELD = "{bk_biz_id}_{root_id}_semantic_check_auto_commit" CACHE_SEMANTIC_SKIP_PAUSE_FILED = "{bk_biz_id}_{root_id}_semantic_check_skip_pause" SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME = 7 * 24 * 60 * 60 diff --git a/dbm-ui/backend/db_services/mysql/sql_import/dataclass.py b/dbm-ui/backend/db_services/mysql/sql_import/dataclass.py index 4b08d030ee..0b2c332cb1 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/dataclass.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/dataclass.py @@ -23,6 +23,7 @@ class SQLMeta: sql_content: str = None sql_files: List[InMemoryUploadedFile] = None + cluster_type: str = None def to_dict(self): return asdict(self) diff --git a/dbm-ui/backend/db_services/mysql/sql_import/handlers.py b/dbm-ui/backend/db_services/mysql/sql_import/handlers.py index 8b59543bf0..99887ff435 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/handlers.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/handlers.py @@ -13,13 +13,13 @@ import tempfile import time import uuid -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Union from django.core.cache import cache from django.core.files.uploadedfile import InMemoryUploadedFile from backend.components.sql_import.client import SQLImportApi -from backend.configuration.constants import PLAT_BIZ_ID +from backend.configuration.constants import PLAT_BIZ_ID, DBType from backend.core.storages.storage import get_storage from backend.db_services.mysql.sql_import.constants import ( BKREPO_SQLFILE_PATH, @@ -27,13 +27,15 @@ CACHE_SEMANTIC_SKIP_PAUSE_FILED, CACHE_SEMANTIC_TASK_FIELD, SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME, + SQLImportMode, ) -from backend.db_services.mysql.sql_import.dataclass import SemanticOperateMeta, SQLExecuteMeta, SQLMeta from backend.db_services.taskflow.handlers import TaskFlowHandler from backend.flow.consts import StateType from backend.flow.engine.bamboo.engine import BambooEngine from backend.flow.engine.controller.mysql import MySQLController +from backend.flow.engine.controller.spider import SpiderController from backend.flow.models import FlowNode, FlowTree +from backend.flow.plugins.components.collections.mysql.exec_actuator_script import ExecuteDBActuatorScriptComponent from backend.flow.plugins.components.collections.mysql.semantic_check import SemanticCheckComponent from backend.utils.redis import RedisConn @@ -43,14 +45,16 @@ class SQLHandler(object): 封装sql导入相关处理操作 """ - def __init__(self, bk_biz_id: int, context: Dict = None): + def __init__(self, bk_biz_id: int, context: Dict = None, cluster_type: str = ""): """ - :param bk_biz_id: 业务ID - :param context: 上下文数据 + @param bk_biz_id: 业务ID + @param context: 上下文数据 + @param cluster_type: 集群类型 """ self.bk_biz_id = bk_biz_id self.context = context + self.cluster_type = cluster_type def _upload_sql_file( self, sql_content: str = None, sql_file_list: List[InMemoryUploadedFile] = None @@ -87,18 +91,21 @@ def _upload_sql_file( return sql_file_info_list - def grammar_check(self, sql: SQLMeta) -> Optional[Dict]: + def grammar_check(self, sql_content: str = None, sql_files: List[InMemoryUploadedFile] = None) -> Optional[Dict]: """ sql 语法检查 - :param sql: sql元数据 + @param sql_content: sql内容 + @param sql_files: sql文件 """ - sql_file_info_list = self._upload_sql_file(sql.sql_content, sql.sql_files) + sql_file_info_list = self._upload_sql_file(sql_content, sql_files) file_name_list = [os.path.split(sql_file_info["sql_path"])[1] for sql_file_info in sql_file_info_list] dir_name = os.path.split(sql_file_info_list[0]["sql_path"])[0] # 获取检查信息 - check_info = SQLImportApi.grammar_check(params={"path": dir_name, "files": file_name_list}) + check_info = SQLImportApi.grammar_check( + params={"path": dir_name, "files": file_name_list, "cluster_type": self.cluster_type} + ) # 填充sql内容。TODO:如果sql内容过大需要进行压缩吗? for sql_file_info in sql_file_info_list: @@ -110,67 +117,102 @@ def grammar_check(self, sql: SQLMeta) -> Optional[Dict]: return check_info - def semantic_check(self, sql_execute: SQLExecuteMeta) -> Dict: + def semantic_check( + self, + charset: str, + path: str, + cluster_ids: List[int], + execute_sql_files: List[str], + execute_db_infos: List[Dict[str, List]], + highrisk_warnings: Dict, + ticket_type: str, + ticket_mode: Dict, + import_mode: SQLImportMode, + backup: List[Dict], + ) -> Dict: """ sql 模拟执行(sql 语义检查) - :param sql_execute: sql执行元数据 + @param charset: 字符集 + @param path: sql文件路径 + @param cluster_ids: 集群列表 + @param execute_sql_files: 待执行的sql文件名 + @param execute_db_infos: 待执行的db匹配模式 + @param highrisk_warnings: 高危信息 + @param ticket_type: 单据类型 + @param ticket_mode: sql导入单据的触发类型 + @param import_mode: sql文件导入类型 + @param backup: 备份信息(和备份单据一样) """ # 语义检查参数准备 - root_id = f"{datetime.date.today()}{uuid.uuid1().hex[:6]}".replace("-", "") - sql_execute.created_by = self.context["user"] - sql_execute.bk_biz_id = self.bk_biz_id - sql_execute.execute_objects = [] - for sql_file in sql_execute.execute_sql_files: - sql_execute.execute_objects.extend( - [{"sql_file": sql_file, **db_info} for db_info in sql_execute.execute_db_infos] - ) + execute_objects: List[Dict[str, Union[str, List]]] = [] + for sql_file in execute_sql_files: + execute_objects.extend([{"sql_file": sql_file, **db_info} for db_info in execute_db_infos]) # 异步执行语义检查 - MySQLController(root_id=root_id, ticket_data=sql_execute.to_dict()).mysql_sql_semantic_check_scene() + root_id = f"{datetime.date.today()}{uuid.uuid1().hex[:6]}".replace("-", "") + ticket_data = { + "created_by": self.context["user"], + "bk_biz_id": self.bk_biz_id, + "ticket_type": ticket_type, + "charset": charset, + "path": path, + "cluster_ids": cluster_ids, + "execute_objects": execute_objects, + "highrisk_warnings": highrisk_warnings, + "ticket_mode": ticket_mode, + "import_mode": import_mode, + "backup": backup, + } + if self.cluster_type == DBType.MySQL: + MySQLController(root_id=root_id, ticket_data=ticket_data).mysql_sql_semantic_check_scene() + elif self.cluster_type == DBType.Tendb: + SpiderController(root_id=root_id, ticket_data=ticket_data).spider_sql_import_scene() # 获取语义执行的node id tree = FlowTree.objects.get(root_id=root_id) - node_id = self._get_node_id_by_component(tree, SemanticCheckComponent.code) + code = ( + SemanticCheckComponent.code if self.cluster_type == DBType.MySQL else ExecuteDBActuatorScriptComponent.code + ) + node_id = self.get_node_id_by_component(tree.tree, code) - # 缓存用户的语义检查,并删除过期的数据, django的cache不支持redis命令,这里只能使用原生redis客户端进行操作 + # 缓存用户的语义检查,并删除过期的数据。注:django的cache不支持redis命令,这里只能使用原生redis客户端进行操作 now = int(time.time()) - key = CACHE_SEMANTIC_TASK_FIELD.format(user=sql_execute.created_by) - expired_task_ids = RedisConn.zrangebyscore(key, "-inf", now - SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) - self.delete_user_semantic_tasks(semantic=SemanticOperateMeta(task_ids=expired_task_ids)) + key = CACHE_SEMANTIC_TASK_FIELD.format(user=self.context["user"], cluster_type=self.cluster_type) RedisConn.zadd(key, {root_id: now}) RedisConn.set(root_id, StateType.CREATED) + expired_task_ids = RedisConn.zrangebyscore(key, "-inf", now - SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) + self.delete_user_semantic_tasks(task_ids=expired_task_ids) + return {"root_id": root_id, "node_id": node_id} - def delete_user_semantic_tasks(self, semantic: SemanticOperateMeta) -> None: + def delete_user_semantic_tasks(self, task_ids: List[int]) -> None: """ 删除用户的语义执行任务 - :param semantic: 语义检查相关操作的元数据 + @param task_ids: 待删除的语义任务ID """ - key = CACHE_SEMANTIC_TASK_FIELD.format(user=self.context["user"]) - if semantic.task_ids: - RedisConn.zrem(key, *semantic.task_ids) - RedisConn.delete(*semantic.task_ids) + key = CACHE_SEMANTIC_TASK_FIELD.format(user=self.context["user"], cluster_type=self.cluster_type) + if task_ids: + RedisConn.zrem(key, *task_ids) + RedisConn.delete(*task_ids) - def revoke_semantic_check(self, semantic: SemanticOperateMeta) -> Dict: + def revoke_semantic_check(self, root_id: str) -> Dict: """ 撤销语义检查流程 - :param semantic: 语义检查相关操作的元数据 + @param root_id: 语义检查的任务ID """ - root_id = semantic.root_id revoke_info = TaskFlowHandler(root_id=root_id).revoke_pipeline() return {"result": revoke_info.result, "message": revoke_info.message, "data": revoke_info.data} - def query_semantic_data(self, semantic: SemanticOperateMeta) -> Dict: + def query_semantic_data(self, root_id: str) -> Dict: """ 根据语义执行id查询语义执行的数据 - :param semantic: 语义检查相关操作的元数据 + @param root_id: 语义任务执行ID """ - root_id = semantic.root_id first_act_node_id = FlowNode.objects.filter(root_id=root_id).first().node_id try: @@ -181,40 +223,37 @@ def query_semantic_data(self, semantic: SemanticOperateMeta) -> Dict: import_mode = details["import_mode"] return {"semantic_data": details, "import_mode": import_mode, "sql_data_ready": True} - def deploy_user_config(self, semantic: SemanticOperateMeta) -> None: + def deploy_user_config(self, root_id: str, is_auto_commit: bool, is_skip_pause: bool) -> None: """ 更改用户配置(是否自动提交,是否跳过确认) - :param semantic: 语义检查相关操作的元数据 + @param root_id: 语义任务执行ID + @param is_auto_commit: 是否自动提交 + @param is_skip_pause: 是否跳过暂停 """ # auto_commit的配置 - auto_commit_key = CACHE_SEMANTIC_AUTO_COMMIT_FIELD.format(bk_biz_id=self.bk_biz_id, root_id=semantic.root_id) - cache.set(auto_commit_key, semantic.is_auto_commit, SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) + auto_commit_key = CACHE_SEMANTIC_AUTO_COMMIT_FIELD.format(bk_biz_id=self.bk_biz_id, root_id=root_id) + cache.set(auto_commit_key, is_auto_commit, SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) # skip_pause的配置 - skip_pause_key = CACHE_SEMANTIC_SKIP_PAUSE_FILED.format(bk_biz_id=self.bk_biz_id, root_id=semantic.root_id) - cache.set(skip_pause_key, semantic.is_skip_pause, SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) + skip_pause_key = CACHE_SEMANTIC_SKIP_PAUSE_FILED.format(bk_biz_id=self.bk_biz_id, root_id=root_id) + cache.set(skip_pause_key, is_skip_pause, SQL_SEMANTIC_CHECK_DATA_EXPIRE_TIME) - def query_user_config(self, semantic: SemanticOperateMeta) -> Dict: + def query_user_config(self, root_id: str) -> Dict: """ 查询用户配置 - :param semantic: 语义检查相关操作的元数据 + @param root_id: 语义任务执行ID """ - auto_commit_key = CACHE_SEMANTIC_AUTO_COMMIT_FIELD.format(bk_biz_id=self.bk_biz_id, root_id=semantic.root_id) - skip_pause_key = CACHE_SEMANTIC_SKIP_PAUSE_FILED.format(bk_biz_id=self.bk_biz_id, root_id=semantic.root_id) - + auto_commit_key = CACHE_SEMANTIC_AUTO_COMMIT_FIELD.format(bk_biz_id=self.bk_biz_id, root_id=root_id) + skip_pause_key = CACHE_SEMANTIC_SKIP_PAUSE_FILED.format(bk_biz_id=self.bk_biz_id, root_id=root_id) is_auto_commit = cache.get(auto_commit_key) is_skip_pause = cache.get(skip_pause_key) return {"is_auto_commit": is_auto_commit, "is_skip_pause": is_skip_pause} - def get_user_semantic_tasks(self, semantic: SemanticOperateMeta) -> List[Dict]: - """ - 获取用户的语义检查执行信息列表 - :param semantic: 语义检查相关操作的元数据 - """ - - key = CACHE_SEMANTIC_TASK_FIELD.format(user=self.context["user"]) + def _get_user_semantic_tasks(self, cluster_type, code) -> List[Dict]: + # 获取缓存的任务ID + key = CACHE_SEMANTIC_TASK_FIELD.format(user=self.context["user"], cluster_type=cluster_type) task_ids = RedisConn.zrange(key, 0, -1) task_ids__status_map = dict(zip(task_ids, RedisConn.mget(task_ids))) @@ -224,7 +263,7 @@ def get_user_semantic_tasks(self, semantic: SemanticOperateMeta) -> List[Dict]: { "bk_biz_id": tree.bk_biz_id, "root_id": tree.root_id, - "node_id": self._get_node_id_by_component(tree, SemanticCheckComponent.code), + "node_id": self.get_node_id_by_component(tree.tree, code), "created_at": tree.created_at, "status": tree.status, "is_alter": task_ids__status_map[tree.root_id] != tree.status, @@ -240,14 +279,36 @@ def get_user_semantic_tasks(self, semantic: SemanticOperateMeta) -> List[Dict]: return semantic_info_list - def _get_node_id_by_component(self, tree: FlowTree, component_code: str) -> str: + def get_user_semantic_tasks(self) -> List[Dict]: + """ + 获取用户的语义检查执行信息列表 + """ + semantic_info_list: List[Dict] = [] + if not self.cluster_type or self.cluster_type == DBType.MySQL: + semantic_info_list.extend(self._get_user_semantic_tasks(DBType.MySQL, SemanticCheckComponent.code)) + + if not self.cluster_type or self.cluster_type == DBType.Tendb: + semantic_info_list.extend( + self._get_user_semantic_tasks(DBType.Tendb, ExecuteDBActuatorScriptComponent.code) + ) + + return semantic_info_list + + def get_node_id_by_component(self, tree: Dict, component_code: str) -> str: """ 根据component获取node id :param tree: 流程树对象 :param component_code: 组件code名称 """ - activities: Dict = tree.tree["activities"] + activities: Dict = tree["activities"] for node_id, activity in activities.items(): - if activity["component"]["code"] == component_code: + if activity.get("component") and activity["component"]["code"] == component_code: return node_id + + if activity.get("pipeline"): + node_id = self.get_node_id_by_component(activity["pipeline"], component_code) + if node_id: + return node_id + + return "" diff --git a/dbm-ui/backend/db_services/mysql/sql_import/mock_data.py b/dbm-ui/backend/db_services/mysql/sql_import/mock_data.py index 9955cfb838..cdedf2298a 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/mock_data.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/mock_data.py @@ -47,7 +47,7 @@ SQL_TICKET_AUTO_COMMIT_REQUEST_DATA = {"root_id": 12232133211, "is_auto_commit": True} -USER_SEMANTIC_LIST_REQUEST_DATA = {"user": "admin"} +USER_SEMANTIC_LIST_REQUEST_DATA = {"user": "admin", "cluster_type": "mysql"} USER_SEMANTIC_LIST_RESPONSE_DATA = { "semantic_list": [ {"root_id": 1231613324894, "created_at": "2011/11/11", "status": "RUNNING"}, diff --git a/dbm-ui/backend/db_services/mysql/sql_import/serializers.py b/dbm-ui/backend/db_services/mysql/sql_import/serializers.py index 200b18d2ec..c839537787 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/serializers.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/serializers.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from backend.configuration.constants import DBType from backend.constants import DATETIME_PATTERN from backend.db_meta.enums import InstanceInnerRole from backend.db_services.mysql.sql_import import mock_data @@ -43,13 +44,12 @@ def validate(self, attrs): return attrs -class SQLGrammarCheckResultSerializer(serializers.Serializer): - syntax_fails = serializers.ListField(help_text=_("语法错误"), allow_empty=True, allow_null=True) - highrisk_warnings = serializers.ListField(help_text=_("高危警告"), allow_empty=True, allow_null=True) - bancommand_warnings = serializers.ListField(help_text=_("禁止命令"), allow_empty=True, allow_null=True) - - class SQLGrammarCheckResponseSerializer(serializers.Serializer): + class SQLGrammarCheckResultSerializer(serializers.Serializer): + syntax_fails = serializers.ListField(help_text=_("语法错误"), allow_empty=True, allow_null=True) + highrisk_warnings = serializers.ListField(help_text=_("高危警告"), allow_empty=True, allow_null=True) + bancommand_warnings = serializers.ListField(help_text=_("禁止命令"), allow_empty=True, allow_null=True) + sql_file_name = serializers.DictField(help_text=_("语法检查结果"), child=SQLGrammarCheckResultSerializer()) class Meta: @@ -88,6 +88,9 @@ class SQLImportBackUpSerializer(serializers.Serializer): ticket_mode = SQLImportModeSerializer() import_mode = serializers.ChoiceField(help_text=_("sql导入模式"), choices=SQLImportMode.get_choices()) backup = serializers.ListSerializer(help_text=_("备份信息"), child=SQLImportBackUpSerializer(), required=False) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型,默认为mysql"), choices=DBType.get_choices(), required=False, default=DBType.MySQL + ) class Meta: swagger_schema_fields = {"example": mock_data.SQL_SEMANTIC_CHECK_REQUEST_DATA} @@ -99,7 +102,9 @@ def validate(self, attrs): try: datetime.strptime(trigger_time, DATETIME_PATTERN) except Exception as e: # pylint: disable=broad-except - raise serializers.Serializer(_("时间{}格式解析失败: {},请按照{}格式输入时间").format(trigger_time, e, DATETIME_PATTERN)) + raise serializers.ValidationError( + _("时间{}格式解析失败: {},请按照{}格式输入时间").format(trigger_time, e, DATETIME_PATTERN) + ) return attrs @@ -130,8 +135,9 @@ class Meta: class GetUserSemanticListSerializer(serializers.Serializer): - # TODO 暂时不需要用户参数,后面可能会扩展 - # user = serializers.CharField(help_text=_("用户名")) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型,不传则查询所有集群的任务"), choices=DBType.get_choices(), required=False, default="" + ) class Meta: swagger_schema_fields = {"example": mock_data.USER_SEMANTIC_LIST_REQUEST_DATA} diff --git a/dbm-ui/backend/db_services/mysql/sql_import/views.py b/dbm-ui/backend/db_services/mysql/sql_import/views.py index 129e3a49b4..7c1234776d 100644 --- a/dbm-ui/backend/db_services/mysql/sql_import/views.py +++ b/dbm-ui/backend/db_services/mysql/sql_import/views.py @@ -17,6 +17,7 @@ from backend.bk_web import viewsets from backend.bk_web.swagger import common_swagger_auto_schema +from backend.configuration.constants import DBType from backend.db_services.mysql.sql_import.dataclass import SemanticOperateMeta, SQLExecuteMeta, SQLMeta from backend.db_services.mysql.sql_import.handlers import SQLHandler from backend.db_services.mysql.sql_import.serializers import ( @@ -58,10 +59,10 @@ def _view_common_handler( :param func: handler的回调函数名称 """ - base_info = {"bk_biz_id": bk_biz_id, "context": {"user": request.user.username}} validated_data = self.params_validate(self.get_serializer_class()) - meta_init_data = meta.from_dict(validated_data) - return Response(getattr(SQLHandler(**base_info), func)(meta_init_data)) + cluster_type = validated_data.pop("cluster_type", None) + base_info = {"bk_biz_id": bk_biz_id, "context": {"user": request.user.username}, "cluster_type": cluster_type} + return Response(getattr(SQLHandler(**base_info), func)(**validated_data)) @common_swagger_auto_schema( operation_summary=_("sql语法检查"), diff --git a/dbm-ui/backend/env/apigw_domains.py b/dbm-ui/backend/env/apigw_domains.py index b5470c375f..95f19ef43a 100644 --- a/dbm-ui/backend/env/apigw_domains.py +++ b/dbm-ui/backend/env/apigw_domains.py @@ -28,7 +28,7 @@ DRS_APIGW_DOMAIN = get_type_env(key="DRS_APIGW_DOMAIN", _type=str) SQL_IMPORT_APIGW_DOMAIN = get_type_env(key="SQL_IMPORT_APIGW_DOMAIN", _type=str) BKMONITORV3_APIGW_DOMAIN = get_type_env(key="BKMONITORV3_APIGW_DOMAIN", _type=str) -MYSQL_SIMULATION_DONAIN = get_type_env(key="MYSQL_SIMULATION_DONAIN", _type=str) +MYSQL_SIMULATION_DONAIN = get_type_env(key="MYSQL_SIMULATION_DOMAIN", _type=str) NAMESERVICE_APIGW_DOMAIN = get_type_env(key="NAMESERVICE_APIGW_DOMAIN", _type=str) HADB_APIGW_DOMAIN = get_type_env(key="HADB_APIGW_DOMAIN", _type=str) DBRESOURCE_APIGW_DOMAIN = get_type_env(key="DBRESOURCE_APIGW_DOMAIN", _type=str) diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index 927ac3f50f..4fc837b68a 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -789,3 +789,12 @@ class PrivRole(str, StructuredEnum): class MysqlChangeMasterType(str, StructuredEnum): MASTERSTATUS = EnumField("MasterStatus", _("from show master status")) BACKUPFILE = EnumField("BackFile", _("from backup file")) + + +class TenDBBackUpLocation(str, StructuredEnum): + """ + TendbCluster的库表备份位置 + """ + + REMOTE = EnumField("remote", _("REMOTE")) + SPIDER_MNT = EnumField("spider_mnt", _("SPIDER_MNT")) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mysql/mysql_clone_rules.py b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/mysql_clone_rules.py index c9aca45642..a364ab6364 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mysql/mysql_clone_rules.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mysql/mysql_clone_rules.py @@ -22,7 +22,6 @@ class MySQLCloneRules(object): """ mysql权限克隆的流程抽象类 - todo 后续需要兼容跨云管理 """ def __init__(self, root_id: str, data: Optional[Dict]): diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py index 51a2f72cb7..32e66a06fc 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/import_sqlfile_flow.py @@ -184,7 +184,7 @@ def sql_semantic_check_flow(self): semantic_check_pipeline.run_pipeline() - def __get_master_ctl_info(self, cluster_id: int) -> object: + def __get_master_ctl_info(self, cluster_id: int) -> dict: cluster = Cluster.objects.get(id=cluster_id) logger.info("get ") master_ctl_addr = cluster.tendbcluster_ctl_primary_address() diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py index 386daae9b6..2d39347def 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_checksum.py @@ -50,7 +50,7 @@ class SpiderChecksumFlow(object): "root_id": 123, "created_by": "admin", "bk_biz_id": 9991001, - "ticket_type": "SPIDER_CHECKSUM", + "ticket_type": "TENDBCLUSTER_CHECKSUM", "timing": "2022-11-21 12:04:10", "is_sync_non_innodb": true, "runtime_hour": 48, diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py index a058216e89..703e2938eb 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_db_table_backup.py @@ -57,7 +57,7 @@ def backup_flow(self): "uid": "2022051612120001", "created_by": "xxx", "bk_biz_id": "152", - "ticket_type": "SPIDER_DB_TABLE_BACKUP", + "ticket_type": "TENDBCLUSTER_DB_TABLE_BACKUP", "infos": [ { "cluster_id": int, diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py index 634b65ae0c..52cf51576a 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_full_backup.py @@ -50,7 +50,7 @@ def full_backup_flow(self): "uid": "398346234", "created_type": "xxx", "bk_biz_id": "152", - "ticket_type": "SPIDER_FULL_BACKUP", + "ticket_type": "TENDBCLUSTER_FULL_BACKUP", "infos": { "backup_type": enum of backend.flow.consts.MySQLBackupTypeEnum "file_tag": enum of backend.flow.consts.MySQLBackupFileTagEnum diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py index 15688d040c..8d57beb3a8 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_cluster_truncate_database.py @@ -87,7 +87,7 @@ def truncate_database(self): "uid": "2022051612120001", "created_by": "xxx", "bk_biz_id": "152", - "ticket_type": "SPIDER_TRUNCATE_DATABASE", + "ticket_type": "TENDBCLUSTER_TRUNCATE_DATABASE", "truncate_data_infos": [ { "cluster_id": int, diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_partition.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_partition.py index 178c69596a..5f148dff54 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_partition.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_partition.py @@ -35,7 +35,7 @@ class SpiderPartitionFlow(object): "root_id": 123, "created_by": "xxx", "bk_biz_id": "xxx", - "ticket_type": "SPIDER_PARTITION", + "ticket_type": "TENDBCLUSTER_PARTITION", "infos": [ { "config_id": 1, diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py index 7b45685046..d764005a2a 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/spider/spider_rename_database_flow.py @@ -83,7 +83,7 @@ def rename_database(self): "uid": "2022051612120001", "created_by": "xxx", "bk_biz_id": "152", - "ticket_type": "SPIDER_RENAME_DATABASE", + "ticket_type": "TENDBCLUSTER_RENAME_DATABASE", "infos": [ { "cluster_id": int, diff --git a/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_rules.py b/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_rules.py index a97c53875b..c37b8eaf14 100644 --- a/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_rules.py +++ b/dbm-ui/backend/flow/plugins/components/collections/mysql/clone_rules.py @@ -35,14 +35,15 @@ def _execute(self, data, parent_data, callback=None) -> bool: bk_biz_id = kwargs["bk_biz_id"] operator = kwargs["created_by"] clone_type = kwargs["clone_type"] + cluster_type = kwargs["cluster_type"] clone_data_list = kwargs["clone_data"] clone_success_count = 0 # 如果是实例克隆,则提前获得ip:port与机器信息的字典 if clone_type == CloneType.INSTANCE: - address_machine_map = CloneHandler(bk_biz_id, operator, clone_type).get_address__machine_map( - clone_data_list - ) + address_machine_map = CloneHandler( + bk_biz_id=bk_biz_id, operator=operator, clone_type=clone_type, cluster_type=cluster_type + ).get_address__machine_map(clone_data_list) for clone_data in clone_data_list: # 实例化权限克隆记录,后续存到数据库中 @@ -56,13 +57,15 @@ def _execute(self, data, parent_data, callback=None) -> bool: if clone_type == CloneType.CLIENT.value: record.target = "\n".join(record.target) - # 权限克隆 + # 权限克隆全局参数准备 params = { "bk_biz_id": bk_biz_id, "operator": operator, "bk_cloud_id": clone_data["bk_cloud_id"], + "cluster_type": cluster_type, } try: + # 调用客户端克隆/实例克隆 if clone_type == CloneType.CLIENT.value: params.update({"source_ip": clone_data["source"], "target_ip": clone_data["target"]}) resp = MySQLPrivManagerApi.clone_client(params=params, raw=True) @@ -81,11 +84,11 @@ def _execute(self, data, parent_data, callback=None) -> bool: ) resp = MySQLPrivManagerApi.clone_instance(params=params, raw=True) + # 填充克隆的结果和信息 record.status = int(resp["code"]) == 0 clone_success_count += record.status - - self.log_info(f"{resp['message']}\n") record.error = resp["message"] + self.log_info(f"{resp['message']}\n") except Exception as e: # pylint: disable=broad-except if isinstance(e, ApiResultError): diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index 47b0363d35..2f1f7fac5b 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -278,7 +278,7 @@ # tendbcluster db重命名 url(r"^scene/tendbcluster_rename_database$", TenDBClusterRenameDatabaseView.as_view()), # tendbcluster 清档 - url(r"^scene/tendbcluster_truncate_database$", TenDBClusterTruncateDatabaseView.as_view()), + url(r"^scene/tendbcluster_truncate_data$", TenDBClusterTruncateDatabaseView.as_view()), # tendbcluster 库表备份 url(r"^scene/tendbcluster_database_table_backup$", TenDBClusterDatabaseTableBackupView.as_view()), # spider 添加 diff --git a/dbm-ui/backend/flow/views/spider_cluster_truncate_database.py b/dbm-ui/backend/flow/views/spider_cluster_truncate_database.py index bbf447efa6..9e1c172a35 100644 --- a/dbm-ui/backend/flow/views/spider_cluster_truncate_database.py +++ b/dbm-ui/backend/flow/views/spider_cluster_truncate_database.py @@ -22,7 +22,7 @@ class TenDBClusterTruncateDatabaseView(FlowTestView): """ - api: api: /apis/v1/flow/scene/tendbcluster_truncate_database + api: api: /apis/v1/flow/scene/tendbcluster_truncate_data """ @staticmethod diff --git a/dbm-ui/backend/tests/db_services/mysql/permission/test_account_handler.py b/dbm-ui/backend/tests/db_services/mysql/permission/test_account_handler.py index 82da235ee5..59b603c996 100644 --- a/dbm-ui/backend/tests/db_services/mysql/permission/test_account_handler.py +++ b/dbm-ui/backend/tests/db_services/mysql/permission/test_account_handler.py @@ -49,7 +49,7 @@ class TestAccountHandler: @pytest.mark.parametrize("password", VALID_PASSWORD_LIST + INVALID_PASSWORD_LIST) def test_check_password_strength__valid(self, password): - is_pwd_valid, _ = AccountHandler._check_pwd_strength(password, rule_data=copy.deepcopy(POLICY_DATA)) + is_pwd_valid, _ = AccountHandler._check_password_strength(password, rule_data=copy.deepcopy(POLICY_DATA)) assert is_pwd_valid == (password in VALID_PASSWORD_LIST) @patch("backend.db_services.mysql.permission.db_account.handlers.MySQLPrivManagerApi", MySQLPrivManagerApiMock) diff --git a/dbm-ui/backend/ticket/builders/common/base.py b/dbm-ui/backend/ticket/builders/common/base.py index 0f4b2a1a9e..cf8b56c09b 100644 --- a/dbm-ui/backend/ticket/builders/common/base.py +++ b/dbm-ui/backend/ticket/builders/common/base.py @@ -237,12 +237,17 @@ def _validate_single_database_table_selector( @classmethod def validate_database_table_selector( - cls, bk_biz_id: int, infos: Dict, is_only_db_operate_list: List[bool] = None + cls, bk_biz_id: int, infos: Dict, role_key: None, is_only_db_operate_list: List[bool] = None ) -> Tuple[bool, str]: """校验库表选择器的数据是否合法""" cluster_ids = [info["cluster_id"] for info in infos] - dbs_in_cluster = RemoteServiceHandler(bk_biz_id).show_databases(cluster_ids) + # 如果想验证特定角色的库表,则传入集群ID与角色映射表 + cluster_id__role_map = {} + if role_key: + cluster_id__role_map = {info["cluster_id"]: info[role_key] for info in infos} + + dbs_in_cluster = RemoteServiceHandler(bk_biz_id).show_databases(cluster_ids, cluster_id__role_map) dbs_in_cluster_map = {db["cluster_id"]: db["databases"] for db in dbs_in_cluster} if not is_only_db_operate_list: is_only_db_operate_list = [False] * len(infos) diff --git a/dbm-ui/backend/ticket/builders/common/constants.py b/dbm-ui/backend/ticket/builders/common/constants.py index 40570f5622..2cd925f247 100644 --- a/dbm-ui/backend/ticket/builders/common/constants.py +++ b/dbm-ui/backend/ticket/builders/common/constants.py @@ -80,6 +80,15 @@ class MySQLChecksumTicketMode(str, StructuredEnum): MANUAL = EnumField("manual", _("人工确认")) +class TendbChecksumScope(str, StructuredEnum): + """ + tendbcluster集群校验的范围 + """ + + ALL = EnumField("all", _("整个集群")) + PARTIAL = EnumField("partial", _("部分实例")) + + class MySQLDataRepairTriggerMode(str, StructuredEnum): """ 数据修复触发类型 diff --git a/dbm-ui/backend/ticket/builders/mysql/base.py b/dbm-ui/backend/ticket/builders/mysql/base.py index 3279a7bd5d..f67b94d482 100644 --- a/dbm-ui/backend/ticket/builders/mysql/base.py +++ b/dbm-ui/backend/ticket/builders/mysql/base.py @@ -130,10 +130,13 @@ def validate_instance_related_clusters( if not CommonValidate.validate_instance_related_clusters(inst, cluster_ids, role): raise serializers.ValidationError(_("请保证所选实例{}的关联集群为{}").format(inst, cluster_ids)) - def validate_database_table_selector(self, attrs, is_only_db_operate_list: List[bool] = None): + def validate_database_table_selector(self, attrs, role_key=None, is_only_db_operate_list: List[bool] = None): """校验库表选择器的数据是否合法""" is_valid, message = CommonValidate.validate_database_table_selector( - bk_biz_id=self.context["bk_biz_id"], infos=attrs["infos"], is_only_db_operate_list=is_only_db_operate_list + bk_biz_id=self.context["bk_biz_id"], + infos=attrs["infos"], + role_key=role_key, + is_only_db_operate_list=is_only_db_operate_list, ) if not is_valid: raise serializers.ValidationError(message) @@ -161,3 +164,17 @@ def clusters_status_transfer_valid(cls, cluster_ids: List[int], ticket_type: str def validate_cluster_ids(self, value): self.clusters_status_transfer_valid(cluster_ids=value, ticket_type=self.context["ticket_type"]) return value + + +class MySQLBaseOperateResourceParamBuilder(builders.ResourceApplyParamBuilder): + def format(self): + cluster_ids = fetch_cluster_ids(self.ticket_data) + clusters = Cluster.objects.filter(id__in=cluster_ids) + # 对每个info补充bk_cloud_id和bk_biz_id + for info in self.ticket_data["infos"]: + cluster_id = info.get("cluster_id") or info.get("cluster_ids")[0] + bk_cloud_id = clusters.get(id=cluster_id).bk_cloud_id + info.update(bk_cloud_id=bk_cloud_id, bk_biz_id=self.ticket.bk_biz_id) + + def post_callback(self): + pass diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_clone_rules.py b/dbm-ui/backend/ticket/builders/mysql/mysql_clone_rules.py index 16d9b7c8a7..af27ce4e7b 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_clone_rules.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_clone_rules.py @@ -14,6 +14,7 @@ from rest_framework import serializers from backend import env +from backend.db_meta.enums import ClusterType from backend.db_services.mysql.permission.constants import CloneType from backend.db_services.mysql.permission.exceptions import CloneDataHasExpiredException from backend.flow.engine.controller.mysql import MySQLController @@ -27,6 +28,9 @@ class MySQLCloneRulesSerializer(SkipToRepresentationMixin, serializers.Serializer): clone_uid = serializers.CharField(help_text=_("权限克隆数据缓存uid")) clone_type = serializers.ChoiceField(help_text=_("权限克隆类型"), choices=CloneType.get_choices()) + cluster_type = serializers.ChoiceField( + help_text=_("集群类型"), choices=ClusterType.get_choices(), required=False, default=ClusterType.TenDBHA + ) class MySQLCloneRulesFlowParamBuilder(builders.FlowParamBuilder): diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_flashback.py b/dbm-ui/backend/ticket/builders/mysql/mysql_flashback.py index 650bc3cea5..34316c9dc9 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_flashback.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_flashback.py @@ -51,6 +51,8 @@ def validate(self, attrs): _("flash的起止时间{}--{}不合法,请保证开始时间小于结束时间,并且二者不大于当前时间").format(start_time, end_time) ) + # TODO: flash库表的校验选择 + return attrs diff --git a/dbm-ui/backend/ticket/builders/mysql/mysql_import_sqlfile.py b/dbm-ui/backend/ticket/builders/mysql/mysql_import_sqlfile.py index d26a6461f0..8615e35aae 100644 --- a/dbm-ui/backend/ticket/builders/mysql/mysql_import_sqlfile.py +++ b/dbm-ui/backend/ticket/builders/mysql/mysql_import_sqlfile.py @@ -16,9 +16,9 @@ from rest_framework import serializers from backend import env +from backend.configuration.constants import DBType from backend.db_meta.models import Cluster from backend.db_services.mysql.sql_import.constants import SQLExecuteTicketMode -from backend.db_services.mysql.sql_import.dataclass import SemanticOperateMeta from backend.db_services.mysql.sql_import.handlers import SQLHandler from backend.flow.engine.bamboo.engine import BambooEngine from backend.flow.engine.controller.mysql import MySQLController @@ -51,46 +51,11 @@ def validate(self, attrs): class MysqlSqlImportItsmParamBuilder(builders.ItsmParamBuilder): """SQL导入审批单据参数""" - def format(self): - self.details.pop("execute_sql_files") - self.details.pop("execute_db_infos") - - self.details[_("字符集")] = self.details.pop("charset") - self.details[_("sql文件路径")] = self.details.pop("path") - self.details[_("集群ID")] = self.details.pop("cluster_ids") - self.details[_("执行模式")] = self.details.pop("ticket_mode") - self.details[_("sql导入模式")] = self.details.pop("import_mode") - self.details[_("模拟执行node_id")] = self.details.pop("semantic_node_id") - self.details[_("模拟执行root_id")] = self.details.pop("root_id") - self.details[_("业务ID")] = self.details.pop("bk_biz_id") - self.details[_("创建人")] = self.details.pop("created_by") - self.details[_("高危信息提示")] = self.details.pop("highrisk_warnings") - - execute_objects = self.details.pop("execute_objects") - for index, sql_obj in enumerate(execute_objects): - sql_obj[_("sql文件名")] = sql_obj.pop("sql_file") - sql_obj[_("目标变更db")] = sql_obj.pop("dbnames") - sql_obj[_("忽略db")] = sql_obj.pop("ignore_dbnames") - execute_objects[index] = json.dumps(sql_obj, ensure_ascii=False) - - sql_execute_info = "\n".join(execute_objects) - self.details[_("sql执行体信息")] = f"[\n{sql_execute_info}\n]" - - backup_objects = self.details.pop("backup", []) - for index, backup_obj in enumerate(backup_objects): - backup_obj[_("备份源")] = backup_obj.pop("backup_on") - backup_obj[_("备份匹配DB列表")] = backup_obj.pop("db_patterns") - backup_obj[_("备份匹配Table列表")] = backup_obj.pop("table_patterns") - backup_objects[index] = json.dumps(backup_obj, ensure_ascii=False) - - backup_info = "\n".join(backup_objects) - self.details[_("sql备份信息")] = f"[\n{backup_info}\n]" - def get_params(self): params = super().get_params() # 添加语义执行结果的链接 - root_id = self.details[_("模拟执行root_id")] + root_id = self.ticket.details["root_id"] semantic_url = f"{env.BK_SAAS_HOST}/database/{self.ticket.bk_biz_id}/mission-details/{root_id}/" params["dynamic_fields"].append({"name": _("模拟执行链接"), "type": "LINK", "value": semantic_url}) @@ -121,15 +86,16 @@ def format_ticket_data(self): class MysqlSqlImportFlowBuilder(BaseMySQLTicketFlowBuilder): serializer = MysqlSqlImportDetailSerializer - def patch_ticket_detail(self): + @classmethod + def patch_sqlimport_ticket_detail(cls, ticket, cluster_type): # 移除语义执行缓存 - root_id = self.ticket.details["root_id"] - handler = SQLHandler(bk_biz_id=self.ticket.bk_biz_id, context={"user": self.ticket.creator}) - handler.delete_user_semantic_tasks(semantic=SemanticOperateMeta(task_ids=[root_id])) + root_id = ticket.details["root_id"] + handler = SQLHandler(bk_biz_id=ticket.bk_biz_id, context={"user": ticket.creator}, cluster_type=cluster_type) + handler.delete_user_semantic_tasks(task_ids=[root_id]) # 为语义执行的FlowTree关联单据 flow_tree = FlowTree.objects.get(root_id=root_id) - flow_tree.uid = self.ticket.id + flow_tree.uid = ticket.id flow_tree.save() # 获取语义执行的details的输入数据 @@ -145,14 +111,17 @@ def patch_ticket_detail(self): # 补充集群信息和node_id cluster_ids = details["cluster_ids"] - semantic_node_id = handler._get_node_id_by_component(flow_tree, SemanticCheckComponent.code) + semantic_node_id = handler.get_node_id_by_component(flow_tree.tree, SemanticCheckComponent.code) details.update( semantic_node_id=semantic_node_id, clusters={cluster.id: cluster.to_dict() for cluster in Cluster.objects.filter(id__in=cluster_ids)}, ) - self.ticket.details.update(details) - self.ticket.save(update_fields=["details"]) + ticket.details.update(details) + ticket.save(update_fields=["details"]) + + def patch_ticket_detail(self): + self.patch_sqlimport_ticket_detail(ticket=self.ticket, cluster_type=DBType.MySQL) def init_ticket_flows(self): """ diff --git a/dbm-ui/backend/ticket/builders/spider/base.py b/dbm-ui/backend/ticket/builders/spider/base.py index 9798582819..5f8fe0316e 100644 --- a/dbm-ui/backend/ticket/builders/spider/base.py +++ b/dbm-ui/backend/ticket/builders/spider/base.py @@ -9,10 +9,17 @@ specific language governing permissions and limitations under the License. """ +from django.utils.translation import ugettext as _ +from rest_framework import serializers + from backend.configuration.constants import DBType from backend.ticket.builders import TicketFlowBuilder from backend.ticket.builders.common.base import MySQLTicketFlowBuilderPatchMixin -from backend.ticket.builders.mysql.base import MySQLBaseOperateDetailSerializer, MySQLClustersTakeDownDetailsSerializer +from backend.ticket.builders.mysql.base import ( + MySQLBaseOperateDetailSerializer, + MySQLBaseOperateResourceParamBuilder, + MySQLClustersTakeDownDetailsSerializer, +) class BaseTendbTicketFlowBuilder(MySQLTicketFlowBuilderPatchMixin, TicketFlowBuilder): @@ -24,4 +31,9 @@ class TendbBaseOperateDetailSerializer(MySQLBaseOperateDetailSerializer): class TendbClustersTakeDownDetailsSerializer(MySQLClustersTakeDownDetailsSerializer): + is_only_delete_slave_domain = serializers.BooleanField(help_text=_("是否只禁用只读集群"), required=False) + is_only_add_slave_domain = serializers.BooleanField(help_text=_("是否只启用只读集群"), required=False) + + +class TendbBaseOperateResourceParamBuilder(MySQLBaseOperateResourceParamBuilder): pass diff --git a/dbm-ui/backend/ticket/builders/spider/spider_add_nodes.py b/dbm-ui/backend/ticket/builders/spider/spider_add_nodes.py new file mode 100644 index 0000000000..d492671cb8 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/spider_add_nodes.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.db_meta.enums import TenDBClusterSpiderRole +from backend.db_services.dbbase.constants import IpSource +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import ( + BaseTendbTicketFlowBuilder, + TendbBaseOperateDetailSerializer, + TendbBaseOperateResourceParamBuilder, +) +from backend.ticket.constants import TicketType + + +class SpiderAddNodesDetailSerializer(TendbBaseOperateDetailSerializer): + class SpiderNodesItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + add_spider_role = serializers.ChoiceField(help_text=_("接入层类型"), choices=TenDBClusterSpiderRole.get_choices()) + resource_spec = serializers.DictField(help_text=_("规格参数")) + + ip_source = serializers.ChoiceField( + help_text=_("机器导入类型"), choices=IpSource.get_choices(), required=False, default=IpSource.RESOURCE_POOL + ) + infos = serializers.ListSerializer(help_text=_("扩容信息"), child=SpiderNodesItemSerializer()) + + +class SpiderAddNodesFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.add_spider_nodes_scene + + def format_ticket_data(self): + pass + + +class SpiderAddNodesResourceParamBuilder(TendbBaseOperateResourceParamBuilder): + def post_callback(self): + next_flow = self.ticket.next_flow() + for info in next_flow.details["ticket_data"]["infos"]: + # 格式化规格信息 + info["resource_spec"]["spider"] = info["resource_spec"].pop("spider_slave_ip_list") + + next_flow.save(update_fields=["details"]) + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_SPIDER_ADD_NODES, is_apply=True) +class SpiderPartitionFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = SpiderAddNodesDetailSerializer + inner_flow_builder = SpiderAddNodesFlowParamBuilder + inner_flow_name = _("接入层扩容") + resource_batch_apply_builder = SpiderAddNodesResourceParamBuilder + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/spider_partition.py b/dbm-ui/backend/ticket/builders/spider/spider_partition.py index 6a8dd3c4f6..17c46bdc2b 100644 --- a/dbm-ui/backend/ticket/builders/spider/spider_partition.py +++ b/dbm-ui/backend/ticket/builders/spider/spider_partition.py @@ -13,11 +13,9 @@ from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders -from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder -from backend.ticket.builders.mysql.mysql_partition import MySQLPartitionDetailSerializer, MySQLPartitionParamBuilder +from backend.ticket.builders.mysql.mysql_partition import MySQLPartitionDetailSerializer from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder -from backend.ticket.constants import FlowRetryType, FlowType, TicketType -from backend.ticket.models import Flow +from backend.ticket.constants import TicketType class SpiderPartitionDetailSerializer(MySQLPartitionDetailSerializer): @@ -31,7 +29,7 @@ def format_ticket_data(self): pass -@builders.BuilderFactory.register(TicketType.SPIDER_PARTITION) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_PARTITION) class SpiderPartitionFlowBuilder(BaseTendbTicketFlowBuilder): serializer = SpiderPartitionDetailSerializer inner_flow_builder = SpiderPartitionParamBuilder diff --git a/dbm-ui/backend/ticket/builders/spider/spider_slave_apply.py b/dbm-ui/backend/ticket/builders/spider/spider_slave_apply.py new file mode 100644 index 0000000000..f91a938bac --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/spider_slave_apply.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.db_meta.models import AppCache, Cluster +from backend.db_services.dbbase.constants import IpSource +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import ( + BaseTendbTicketFlowBuilder, + TendbBaseOperateDetailSerializer, + TendbBaseOperateResourceParamBuilder, +) +from backend.ticket.constants import TicketType + + +class SpiderSlaveApplyDetailSerializer(TendbBaseOperateDetailSerializer): + class SpiderNodesItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) + spider_slave_ip_list = serializers.ListField( + help_text=_("slave信息"), child=serializers.DictField(), required=False + ) + resource_spec = serializers.JSONField(help_text=_("资源规格参数"), required=False) + + infos = serializers.ListSerializer(help_text=_("扩容信息"), child=SpiderNodesItemSerializer()) + # 暂时不清楚该单据是否支持资源池,所以默认手动输入 + ip_source = serializers.ChoiceField( + help_text=_("机器导入类型"), choices=IpSource.get_choices(), required=False, default=IpSource.MANUAL_INPUT + ) + + +class SpiderSlaveApplyFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.spider_slave_cluster_apply_scene + + def format_ticket_data(self): + # 补充从域名 + cluster_ids = [info["cluster_id"] for info in self.ticket_data["infos"]] + cluster_id__name = {cluster.id: cluster.name for cluster in Cluster.objects.filter(id__in=cluster_ids)} + db_app_abbr = AppCache.objects.get(bk_biz_id=self.ticket.bk_biz_id).db_app_abbr + for info in self.ticket_data["infos"]: + info.update(slave_domain=f"spider.slave-{cluster_id__name[info['cluster_id']]}.{db_app_abbr}.db") + + +class SpiderSlaveApplyResourceParamBuilder(TendbBaseOperateResourceParamBuilder): + def post_callback(self): + next_flow = self.ticket.next_flow() + for info in next_flow.details["ticket_data"]["infos"]: + # 格式化规格信息 + info["resource_spec"]["spider"] = info["resource_spec"].pop("spider_ip_list") + + next_flow.save(update_fields=["details"]) + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_SPIDER_SLAVE_APPLY, is_apply=True) +class SpiderSlaveApplyFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = SpiderSlaveApplyDetailSerializer + inner_flow_builder = SpiderSlaveApplyFlowParamBuilder + inner_flow_name = _("spider-slave 集群添加") + resource_batch_apply_builder = SpiderSlaveApplyResourceParamBuilder diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_apply.py b/dbm-ui/backend/ticket/builders/spider/tendb_apply.py index 31fa688bf4..1c5b5a2d51 100644 --- a/dbm-ui/backend/ticket/builders/spider/tendb_apply.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_apply.py @@ -26,6 +26,7 @@ class TenDBClusterApplyDetailSerializer(serializers.Serializer): bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) + db_app_abbr = serializers.CharField(help_text=_("业务英文缩写")) cluster_name = serializers.CharField(help_text=_("集群名")) city_code = serializers.CharField( help_text=_("城市代码"), required=False, allow_blank=True, allow_null=True, default="" @@ -37,9 +38,7 @@ class TenDBClusterApplyDetailSerializer(serializers.Serializer): resource_spec = serializers.JSONField(help_text=_("部署规格")) spider_port = serializers.IntegerField(help_text=_("集群访问端口")) cluster_shard_num = serializers.IntegerField(help_text=_("集群分片数")) - cluster_capacity = serializers.IntegerField(help_text=_("集群容量")) - cluster_qps = serializers.CharField(help_text=_("集群QPS")) - immutable_domain = serializers.CharField(help_text=_("集群访问域名")) + remote_shard_num = serializers.IntegerField(help_text=_("单机分片数")) # display fields bk_cloud_name = serializers.SerializerMethodField(help_text=_("云区域")) @@ -47,7 +46,7 @@ class TenDBClusterApplyDetailSerializer(serializers.Serializer): version = serializers.SerializerMethodField(help_text=_("数据库版本")) db_module_name = serializers.SerializerMethodField(help_text=_("DB模块名")) city_name = serializers.SerializerMethodField(help_text=_("城市名")) - machine_pair_cnt = serializers.SerializerMethodField(help_text=_("机器数")) + machine_pair_cnt = serializers.SerializerMethodField(help_text=_("机器组数")) def get_bk_cloud_name(self, obj): clouds = ResourceQueryHelper.search_cc_cloud(get_cache=True) @@ -68,7 +67,7 @@ def get_city_name(self, obj): return self.context["ticket_ctx"].city_map.get(city_code, city_code) def get_machine_pair_cnt(self, obj): - return obj["machine_pair_cnt"] + return obj["cluster_shard_num"] / obj["remote_shard_num"] def validate(self, attrs): # TODO: spider集群部署校验 @@ -83,6 +82,7 @@ def format_ticket_data(self): self.ticket_data.update( module=str(self.ticket.details["db_module_id"]), city=self.ticket.details["city_code"], + immutable_domain=f"spider.{self.ticket_data['cluster_name']}.{self.ticket_data['db_app_abbr']}.db", ) @@ -90,14 +90,17 @@ class TenDBClusterApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): def post_callback(self): next_flow = self.ticket.next_flow() nodes = next_flow.details["ticket_data"].pop("nodes") + resource_spec = next_flow.details["ticket_data"]["resource_spec"] # 格式化后台角色信息 - spider_ip_list, mysql_ip_list = nodes["spider"], nodes["remote"] - next_flow.details["ticket_data"].update(spider_ip_list=spider_ip_list, mysql_ip_list=mysql_ip_list) + resource_spec["remote"] = resource_spec.pop("backend_group") + next_flow.details["ticket_data"].update( + spider_ip_list=nodes["spider"], remote_group=nodes["backend_group"], resource_spec=resource_spec + ) next_flow.save(update_fields=["details"]) -@builders.BuilderFactory.register(TicketType.TENDB_CLUSTER_APPLY) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_APPLY, is_apply=True, cluster_type=ClusterType.TenDBCluster) class TenDBClusterApplyFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TenDBClusterApplyDetailSerializer inner_flow_builder = TenDBClusterApplyFlowParamBuilder @@ -129,4 +132,4 @@ def patch_ticket_detail(self): @property def need_itsm(self): - return False + return True diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_backup.py b/dbm-ui/backend/ticket/builders/spider/tendb_backup.py new file mode 100644 index 0000000000..728511edb6 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_backup.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.flow.consts import TenDBBackUpLocation +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer +from backend.ticket.constants import TicketType + + +class TendbBackUpDetailSerializer(TendbBaseOperateDetailSerializer): + class TendbBackUpItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + backup_local = serializers.ChoiceField(help_text=_("备份位置"), choices=TenDBBackUpLocation.get_choices()) + spider_mnt_address = serializers.CharField(help_text=_("运维节点ip:port"), required=False) + db_patterns = serializers.ListField(help_text=_("匹配DB列表"), child=serializers.CharField()) + ignore_dbs = serializers.ListField(help_text=_("忽略DB列表"), child=serializers.CharField()) + table_patterns = serializers.ListField(help_text=_("匹配Table列表"), child=serializers.CharField()) + ignore_tables = serializers.ListField(help_text=_("忽略Table列表"), child=serializers.CharField()) + + infos = serializers.ListSerializer(help_text=_("库表备份信息"), child=TendbBackUpItemSerializer()) + + def validate(self, attrs): + # 库表选择器校验 + super().validate_database_table_selector(attrs, role_key="backup_local") + return attrs + + +class TendbBackUpFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.database_table_backup + + def format_ticket_data(self): + pass + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_DB_TABLE_BACKUP) +class TendbBackUpFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbBackUpDetailSerializer + inner_flow_builder = TendbBackUpFlowParamBuilder + inner_flow_name = _("TenDB Cluster 库表备份") + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_checksum.py b/dbm-ui/backend/ticket/builders/spider/tendb_checksum.py new file mode 100644 index 0000000000..1ce67bbea0 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_checksum.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +import copy +from typing import Any, Dict, List + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.db_meta.models import Cluster, StorageInstance, TenDBClusterStorageSet +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.common.base import HostInfoSerializer +from backend.ticket.builders.common.constants import MySQLChecksumTicketMode, TendbChecksumScope +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer +from backend.ticket.constants import TicketType + + +class TendbChecksumDetailSerializer(TendbBaseOperateDetailSerializer): + class DataRepairSerializer(serializers.Serializer): + is_repair = serializers.BooleanField(help_text=_("是否修复")) + mode = serializers.ChoiceField(help_text=_("数据校验后修复执行类型"), choices=MySQLChecksumTicketMode.get_choices()) + + class ChecksumDataInfoSerializer(serializers.Serializer): + class BackupInfoSerializer(serializers.Serializer): + master = serializers.CharField(help_text=_("主库IP")) + slave = serializers.CharField(help_text=_("从库IP")) + db_patterns = serializers.ListField(help_text=_("匹配DB列表"), child=serializers.CharField()) + ignore_dbs = serializers.ListField(help_text=_("忽略DB列表"), child=serializers.CharField()) + table_patterns = serializers.ListField(help_text=_("匹配Table列表"), child=serializers.CharField()) + ignore_tables = serializers.ListField(help_text=_("忽略Table列表"), child=serializers.CharField()) + + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + checksum_scope = serializers.ChoiceField(help_text=_("校验范围"), choices=TendbChecksumScope.get_choices()) + backup_infos = serializers.ListSerializer(help_text=_("备份信息"), child=BackupInfoSerializer()) + + data_repair = DataRepairSerializer(help_text=_("数据修复信息")) + runtime_hour = serializers.IntegerField(help_text=_("超时时间")) + timing = serializers.CharField(help_text=_("定时触发时间")) + infos = serializers.ListField(help_text=_("全备信息列表"), child=ChecksumDataInfoSerializer()) + is_sync_non_innodb = serializers.BooleanField(help_text=_("非innodb表是否修复"), required=False, default=False) + + def validate(self, attrs): + # super().validate(attrs) + return attrs + + +class TendbChecksumParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.spider_checksum + + def _get_backup_table_info(self, backup_info): + return { + "db_patterns": backup_info["db_patterns"], + "ignore_dbs": backup_info["ignore_dbs"], + "table_patterns": backup_info["table_patterns"], + "ignore_tables": backup_info["ignore_tables"], + } + + def _get_instance_related_info(self, inst): + return { + "id": inst.id, + "ip": inst.machine.ip, + "port": inst.port, + "instance_inner_role": inst.instance_inner_role, + } + + def fetch_cluster_shard_infos(self, cluster, backup_table_info): + storage_set = TenDBClusterStorageSet.objects.select_related("storage_instance_tuple").filter(cluster=cluster) + shard_infos: List[Dict[str, Any]] = [] + for shard in storage_set: + # 排除spider集群迁移的情况(这个放到具体场景下做)。正常checksum提单,一个分片只有一主一从 + master = self._get_instance_related_info(shard.storage_instance_tuple.ejector) + slave = self._get_instance_related_info(shard.storage_instance_tuple.receiver) + shard_infos.append({"shard_id": shard.shard_id, "master": master, "slaves": [slave], **backup_table_info}) + + return shard_infos + + def fetch_machine_shard_infos(self, cluster, master_machine, backup_table_info): + masters = StorageInstance.objects.prefetch_related("as_ejector").filter( + cluster=cluster, machine__ip=master_machine + ) + shard_infos: List[Dict[str, Any]] = [] + for master in masters: + # 获取master关联的storage_tuple,并查询对应的slave和shard_id + inst_tuple = master.as_ejector.first() + master_info = self._get_instance_related_info(master) + slave_info = self._get_instance_related_info(inst_tuple.receiver) + shard_infos.append( + { + "shard_id": inst_tuple.tendbclusterstorageset.shard_id, + "master": master_info, + "slaves": [slave_info], + **backup_table_info, + } + ) + + return shard_infos + + def format_ticket_data(self): + cluster_ids = [info["cluster_id"] for info in self.ticket_data["infos"]] + cluster_id__cluster_map = {cluster.id: cluster for cluster in Cluster.objects.filter(id__in=cluster_ids)} + for info in self.ticket_data["infos"]: + cluster = cluster_id__cluster_map[info["cluster_id"]] + + # 如果校验范围为全库,则查询所有的分片信息。 否则根据machine查询对应分片信息 + if info["checksum_scope"] == TendbChecksumScope.ALL: + backup_table_info = self._get_backup_table_info(info["backup_infos"][0]) + shard_infos = self.fetch_cluster_shard_infos(cluster, backup_table_info) + else: + shard_infos: List[Dict[str, Any]] = [] + for backup_info in info["backup_infos"]: + backup_table_info = self._get_backup_table_info(backup_info) + sub_shard_infos = self.fetch_machine_shard_infos(cluster, backup_info["master"], backup_table_info) + shard_infos.extend(sub_shard_infos) + + # 填充校验的分片信息,填充时区,域名和云区域 + info["shards"] = shard_infos + info["time_zone"] = cluster.time_zone + info["immute_domain"] = cluster.immute_domain + info["bk_cloud_id"] = cluster.bk_cloud_id + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_CHECKSUM) +class TendbChecksumFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbChecksumDetailSerializer + inner_flow_builder = TendbChecksumParamBuilder + inner_flow_name = _("TendbCluster 数据校验修复") + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/spider_destory.py b/dbm-ui/backend/ticket/builders/spider/tendb_destroy.py similarity index 87% rename from dbm-ui/backend/ticket/builders/spider/spider_destory.py rename to dbm-ui/backend/ticket/builders/spider/tendb_destroy.py index 4ce3c2ec5e..dbc5723c6b 100644 --- a/dbm-ui/backend/ticket/builders/spider/spider_destory.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_destroy.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbClustersTakeDownDetailsSerializer @@ -22,10 +23,10 @@ class TendbDestroyDetailSerializer(TendbClustersTakeDownDetailsSerializer): class TendbDestroyFlowParamBuilder(builders.FlowParamBuilder): - controller = SpiderController.spider_cluster_disable_scene + controller = SpiderController.spider_cluster_destroy_scene -@builders.BuilderFactory.register(TicketType.TENDB_CLUSTER_DESTROY) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_DESTROY, phase=ClusterPhase.DESTROY) class TendbDestroyFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TendbDestroyDetailSerializer diff --git a/dbm-ui/backend/ticket/builders/spider/spider_disable.py b/dbm-ui/backend/ticket/builders/spider/tendb_disable.py similarity index 91% rename from dbm-ui/backend/ticket/builders/spider/spider_disable.py rename to dbm-ui/backend/ticket/builders/spider/tendb_disable.py index 37bcb7dc02..e8a905fc97 100644 --- a/dbm-ui/backend/ticket/builders/spider/spider_disable.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_disable.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder @@ -26,7 +27,7 @@ class TendbDisableFlowParamBuilder(builders.FlowParamBuilder): controller = SpiderController.spider_cluster_disable_scene -@builders.BuilderFactory.register(TicketType.TENDB_CLUSTER_DISABLE) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_DISABLE, phase=ClusterPhase.OFFLINE) class TendbEnableFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TendbDisableDetailSerializer diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_enable.py b/dbm-ui/backend/ticket/builders/spider/tendb_enable.py index 4fbe86a118..00e1c98c41 100644 --- a/dbm-ui/backend/ticket/builders/spider/tendb_enable.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_enable.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ +from backend.db_meta.enums import ClusterPhase from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder @@ -26,7 +27,7 @@ class TendbEnableFlowParamBuilder(builders.FlowParamBuilder): controller = SpiderController.spider_cluster_enable_scene -@builders.BuilderFactory.register(TicketType.TENDB_CLUSTER_ENABLE) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_ENABLE, phase=ClusterPhase.ONLINE) class TendbEnableFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TendbEnableDetailSerializer diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_flashback.py b/dbm-ui/backend/ticket/builders/spider/tendb_flashback.py new file mode 100644 index 0000000000..de9d82393b --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_flashback.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ + +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.mysql.mysql_flashback import MySQLFlashbackDetailSerializer +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder +from backend.ticket.constants import FlowRetryType, TicketType + + +class TendbFlashbackDetailSerializer(MySQLFlashbackDetailSerializer): + def validate(self, attrs): + super().validate(attrs) + return attrs + + +class TendbFlashbackFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.flashback + + def format_ticket_data(self): + pass + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_FLASHBACK) +class TendbFlashbackFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbFlashbackDetailSerializer + inner_flow_builder = TendbFlashbackFlowParamBuilder + inner_flow_name = _("TenDB Cluster 闪回执行") + retry_type = FlowRetryType.MANUAL_RETRY diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_full_backup.py b/dbm-ui/backend/ticket/builders/spider/tendb_full_backup.py new file mode 100644 index 0000000000..97f3b0e9b9 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_full_backup.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.flow.consts import MySQLBackupFileTagEnum, MySQLBackupTypeEnum, TenDBBackUpLocation +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer +from backend.ticket.constants import TicketType + + +class TendbFullBackUpDetailSerializer(TendbBaseOperateDetailSerializer): + class FullBackUpItemSerializer(serializers.Serializer): + class FullBackUpClusterItemSerializer(serializers.Serializer): + id = serializers.IntegerField(help_text=_("集群ID")) + backup_local = serializers.ChoiceField(help_text=_("备份位置"), choices=TenDBBackUpLocation.get_choices()) + spider_mnt_address = serializers.CharField(help_text=_("spider临时节点地址(备份位置是spider_mnt才需要)"), required=False) + + backup_type = serializers.ChoiceField(help_text=_("备份选项"), choices=MySQLBackupTypeEnum.get_choices()) + file_tag = serializers.ChoiceField(help_text=_("备份保存时间"), choices=MySQLBackupFileTagEnum.get_choices()) + clusters = serializers.ListSerializer(help_text=_("集群备份信息"), child=FullBackUpClusterItemSerializer()) + + infos = FullBackUpItemSerializer() + + def validate(self, attrs): + for cluster in attrs["infos"]["clusters"]: + if cluster["backup_local"] == TenDBBackUpLocation.SPIDER_MNT and "spider_mnt_address" not in cluster: + raise serializers.ValidationError(_("备份位置选择spider_mnt时,请提供临时节点的地址")) + + return attrs + + +class TendbFullBackUpFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.full_backup + + def format_ticket_data(self): + pass + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_FULL_BACKUP) +class TendbFullBackUpFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbFullBackUpDetailSerializer + inner_flow_builder = TendbFullBackUpFlowParamBuilder + inner_flow_name = _("TenDB Cluster 全库备份") + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_import_sqlfile.py b/dbm-ui/backend/ticket/builders/spider/tendb_import_sqlfile.py new file mode 100644 index 0000000000..6c187fcaa1 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_import_sqlfile.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +import json +import logging + +from django.utils.translation import ugettext as _ +from rest_framework import serializers + +from backend import env +from backend.configuration.constants import DBType +from backend.db_meta.models import Cluster +from backend.db_services.mysql.sql_import.constants import SQLExecuteTicketMode +from backend.db_services.mysql.sql_import.dataclass import SemanticOperateMeta +from backend.db_services.mysql.sql_import.handlers import SQLHandler +from backend.flow.engine.bamboo.engine import BambooEngine +from backend.flow.engine.controller.mysql import MySQLController +from backend.flow.engine.controller.spider import SpiderController +from backend.flow.models import FlowNode, FlowTree +from backend.flow.plugins.components.collections.mysql.semantic_check import SemanticCheckComponent +from backend.ticket import builders +from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder, MySQLBaseOperateDetailSerializer +from backend.ticket.builders.mysql.mysql_import_sqlfile import ( + MysqlSqlImportBackUpFlowParamBuilder, + MysqlSqlImportDetailSerializer, + MysqlSqlImportFlowBuilder, + MysqlSqlImportFlowParamBuilder, + MysqlSqlImportItsmParamBuilder, +) +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder +from backend.ticket.constants import FlowRetryType, FlowType, TicketType +from backend.ticket.exceptions import TicketBaseException +from backend.ticket.models import Flow + +logger = logging.getLogger("root") + + +class TenDBClusterSqlImportDetailSerializer(MysqlSqlImportDetailSerializer): + pass + + +class TenDBClusterSqlImportItsmParamBuilder(MysqlSqlImportItsmParamBuilder): + pass + + +class TenDBClusterSqlImportBackUpFlowParamBuilder(MysqlSqlImportBackUpFlowParamBuilder): + controller = SpiderController.database_table_backup + + def format_ticket_data(self): + super().format_ticket_data() + + +class TenDBClusterSqlImportFlowParamBuilder(MysqlSqlImportFlowParamBuilder): + controller = SpiderController.spider_sql_import_scene + + def format_ticket_data(self): + super().format_ticket_data() + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_IMPORT_SQLFILE) +class TenDBClusterSqlImportFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TenDBClusterSqlImportDetailSerializer + + def patch_ticket_detail(self): + MysqlSqlImportFlowBuilder.patch_sqlimport_ticket_detail(ticket=self.ticket, cluster_type=DBType.MySQL) + + def init_ticket_flows(self): + """ + sql导入根据执行模式可分为三种执行流程: + 手动:语义检查-->单据审批-->手动确认-->(备份)--->sql导入 + 自动:语义检查-->单据审批-->(备份)--->sql导入 + 定时:语义检查-->单据审批-->定时触发-->(备份)--->sql导入 + """ + + flows = [ + Flow( + ticket=self.ticket, + flow_type=FlowType.DESCRIBE_TASK.value, + details=TenDBClusterSqlImportFlowParamBuilder(self.ticket).get_params(), + flow_alias=_("SQL模拟执行状态查询"), + ), + Flow( + ticket=self.ticket, + flow_type=FlowType.BK_ITSM.value, + details=TenDBClusterSqlImportItsmParamBuilder(self.ticket).get_params(), + flow_alias=_("单据审批"), + ), + ] + + mode = self.ticket.details["ticket_mode"]["mode"] + if mode == SQLExecuteTicketMode.MANUAL.value: + flows.append(Flow(ticket=self.ticket, flow_type=FlowType.PAUSE.value, flow_alias=_("人工确认执行"))) + elif mode == SQLExecuteTicketMode.TIMER.value: + flows.append(Flow(ticket=self.ticket, flow_type=FlowType.TIMER.value, flow_alias=_("定时执行"))) + + if self.ticket.details.get("backup"): + flows.append( + Flow( + ticket=self.ticket, + flow_type=FlowType.INNER_FLOW.value, + details=TenDBClusterSqlImportBackUpFlowParamBuilder(self.ticket).get_params(), + retry_type=FlowRetryType.MANUAL_RETRY.value, + flow_alias=_("库表备份"), + ) + ) + + flows.append( + Flow( + ticket=self.ticket, + flow_type=FlowType.INNER_FLOW.value, + details=TenDBClusterSqlImportFlowParamBuilder(self.ticket).get_params(), + retry_type=FlowRetryType.MANUAL_RETRY.value, + flow_alias=_("变更SQL执行"), + ) + ) + + Flow.objects.bulk_create(flows) + return list(Flow.objects.filter(ticket=self.ticket)) diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_master_fail_over.py b/dbm-ui/backend/ticket/builders/spider/tendb_master_fail_over.py index 2d9d0ad7a6..b2f0e0ec74 100644 --- a/dbm-ui/backend/ticket/builders/spider/tendb_master_fail_over.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_master_fail_over.py @@ -10,7 +10,9 @@ """ from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers +from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder from backend.ticket.builders.spider.tendb_master_slave_switch import TendbMasterSlaveSwitchDetailSerializer @@ -18,15 +20,21 @@ class TendbMasterFailOverDetailSerializer(TendbMasterSlaveSwitchDetailSerializer): - pass + force = serializers.BooleanField(help_text=_("是否强制执行(互切不强制,故障切强制)"), required=False, default=True) + serializers.BooleanField(help_text=_("是否检测数据同步延时情况")) + + def validate(self, attrs): + if not attrs["force"]: + raise serializers.ValidationError(_("主故障切换场景需要强制执行")) + + return attrs class TendbMasterFailOverParamBuilder(builders.FlowParamBuilder): - # controller = SpiderController.mysql_ha_master_fail_over_scene - controller = None + controller = SpiderController.tendbcluster_remote_fail_over_scene -@builders.BuilderFactory.register(TicketType.SPIDER_MASTER_FAIL_OVER) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_MASTER_FAIL_OVER) class TendbMasterFailOverFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TendbMasterFailOverDetailSerializer inner_flow_builder = TendbMasterFailOverParamBuilder @@ -34,4 +42,8 @@ class TendbMasterFailOverFlowBuilder(BaseTendbTicketFlowBuilder): @property def need_manual_confirm(self): - return True + return False + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_master_slave_switch.py b/dbm-ui/backend/ticket/builders/spider/tendb_master_slave_switch.py index b00cf1468d..a0fe7ef8a5 100644 --- a/dbm-ui/backend/ticket/builders/spider/tendb_master_slave_switch.py +++ b/dbm-ui/backend/ticket/builders/spider/tendb_master_slave_switch.py @@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from backend.flow.engine.controller.spider import SpiderController from backend.ticket import builders from backend.ticket.builders.common.base import HostInfoSerializer from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer @@ -20,26 +21,33 @@ class TendbMasterSlaveSwitchDetailSerializer(TendbBaseOperateDetailSerializer): class InfoSerializer(serializers.Serializer): - master_ip = HostInfoSerializer(help_text=_("主库 IP")) - slave_ip = HostInfoSerializer(help_text=_("从库 IP")) - cluster_ids = serializers.ListField(help_text=_("集群ID列表"), child=serializers.IntegerField()) + class SwitchItemSerializer(serializers.Serializer): + master = HostInfoSerializer(help_text=_("主库信息")) + slave = HostInfoSerializer(help_text=_("从库信息")) + + switch_tuples = serializers.ListSerializer(help_text=_("切换的主从组"), child=SwitchItemSerializer()) + cluster_id = serializers.IntegerField(help_text=_("集群ID")) infos = serializers.ListField(help_text=_("单据信息"), child=InfoSerializer()) - is_check_proc = serializers.BooleanField(help_text=_("是否检测连接")) - is_check_delay = serializers.BooleanField(help_text=_("是否检测数据同步延时情况")) - is_check_checksum = serializers.BooleanField(help_text=_("是否检测历史数据检验结果")) + force = serializers.BooleanField(help_text=_("是否强制执行(互切不强制,故障切强制)"), default=False, required=False) + is_check_process = serializers.BooleanField(help_text=_("是否检测连接")) + is_check_delay = serializers.BooleanField( + help_text=_("是否检测数据同步延时情况(互切单据延时属于强制检测,故必须传True)"), default=True, required=False + ) + is_verify_checksum = serializers.BooleanField(help_text=_("是否检测历史数据检验结果")) def validate(self, attrs): - # super().validate(attrs) + if attrs["force"] or not attrs["is_check_delay"]: + raise serializers.ValidationError(_("主从互切场景:非强制执行,强制检查延时")) + return attrs class TendbMasterSlaveSwitchParamBuilder(builders.FlowParamBuilder): - # controller = SpiderController.mysql_ha_switch_scene - controller = None + controller = SpiderController.tendb_cluster_remote_switch_scene -@builders.BuilderFactory.register(TicketType.SPIDER_MASTER_SLAVE_SWITCH) +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_MASTER_SLAVE_SWITCH) class TendbMasterSlaveSwitchFlowBuilder(BaseTendbTicketFlowBuilder): serializer = TendbMasterSlaveSwitchDetailSerializer inner_flow_builder = TendbMasterSlaveSwitchParamBuilder @@ -47,4 +55,8 @@ class TendbMasterSlaveSwitchFlowBuilder(BaseTendbTicketFlowBuilder): @property def need_manual_confirm(self): - return True + return False + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_mnt_apply.py b/dbm-ui/backend/ticket/builders/spider/tendb_mnt_apply.py new file mode 100644 index 0000000000..c3c636c783 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_mnt_apply.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.db_meta.models import Cluster +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer +from backend.ticket.constants import TicketType + + +class TendbMNTApplyDetailSerializer(TendbBaseOperateDetailSerializer): + class MNTApplySerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) + spider_ip_list = serializers.ListField(help_text=_("临时节点信息"), child=serializers.DictField()) + + infos = serializers.ListField(help_text=_("添加spider临时节点信息"), child=MNTApplySerializer()) + + def validate(self, attrs): + # super().validate(attrs) + return attrs + + +class TendbMNTApplyParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.add_spider_mnt_scene + + def format_ticket_data(self): + cluster_ids = [info["cluster_id"] for info in self.ticket_data["infos"]] + cluster_id__domain = { + cluster.id: cluster.immute_domain for cluster in Cluster.objects.filter(id__in=cluster_ids) + } + for info in self.ticket_data["infos"]: + info.update(immutable_domain=cluster_id__domain[info["cluster_id"]]) + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_SPIDER_MNT_APPLY, is_apply=True) +class TendbMNTApplyFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbMNTApplyDetailSerializer + inner_flow_builder = TendbMNTApplyParamBuilder + inner_flow_name = _("TendbCluster 添加临时节点") + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_node_reblance.py b/dbm-ui/backend/ticket/builders/spider/tendb_node_reblance.py new file mode 100644 index 0000000000..97b0032b8e --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_node_reblance.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.spider.base import BaseTendbTicketFlowBuilder, TendbBaseOperateDetailSerializer +from backend.ticket.constants import TicketType, TriggerChecksumType + + +class TendbNodeRebalanceDetailSerializer(TendbBaseOperateDetailSerializer): + class NodeRebalanceItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + bk_cloud_id = serializers.IntegerField(help_text=_("云区域ID")) + db_module_id = serializers.IntegerField(help_text=_("模块ID")) + cluster_shard_num = serializers.IntegerField(help_text=_("集群分片数")) + remote_shard_num = serializers.IntegerField(help_text=_("单机分片数")) + resource_spec = serializers.JSONField(help_text=_("规格要求")) + + infos = serializers.ListSerializer(help_text=_("集群扩缩容信息"), child=NodeRebalanceItemSerializer()) + need_checksum = serializers.BooleanField(help_text=_("执行前是否需要数据校验")) + trigger_checksum_type = serializers.ChoiceField(help_text=_("数据校验触发类型"), choices=TriggerChecksumType.get_choices()) + trigger_checksum_time = serializers.DateTimeField(help_text=_("数据校验 触发时间")) + + def validate(self, attrs): + # super().validate(attrs) + return attrs + + +class TendbNodeRebalanceFlowParamBuilderBuilder(builders.FlowParamBuilder): + controller = None + + +class TendbNodeRebalanceResourceParamBuilder(builders.ResourceApplyParamBuilder): + def post_callback(self): + next_flow = self.ticket.next_flow() + infos = next_flow.details["ticket_data"]["infos"] + for info in infos: + info["resource_spec"]["remote"] = info["resource_spec"].pop("backend_group") + info["remote_group"] = info.pop("backend_group") + + next_flow.save(update_fields=["details"]) + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_NODE_REBALANCE, is_apply=True) +class TendbMNTApplyFlowBuilder(BaseTendbTicketFlowBuilder): + serializer = TendbNodeRebalanceDetailSerializer + inner_flow_builder = TendbNodeRebalanceFlowParamBuilderBuilder + resource_batch_apply_builder = TendbNodeRebalanceResourceParamBuilder + inner_flow_name = _("TendbCluster 集群容量变更") diff --git a/dbm-ui/backend/ticket/builders/spider/tendb_rename.py b/dbm-ui/backend/ticket/builders/spider/tendb_rename.py new file mode 100644 index 0000000000..0cc40a9536 --- /dev/null +++ b/dbm-ui/backend/ticket/builders/spider/tendb_rename.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +from django.utils.translation import ugettext as _ + +from backend.flow.engine.controller.spider import SpiderController +from backend.ticket import builders +from backend.ticket.builders.mysql.base import BaseMySQLTicketFlowBuilder +from backend.ticket.builders.mysql.mysql_ha_rename import MySQLHaRenameSerializer +from backend.ticket.constants import FlowRetryType, TicketType + + +class TendbRenameSerializer(MySQLHaRenameSerializer): + pass + + +class TendbRenameFlowParamBuilder(builders.FlowParamBuilder): + controller = SpiderController.rename_database + + def format_ticket_data(self): + pass + + +@builders.BuilderFactory.register(TicketType.TENDBCLUSTER_RENAME_DATABASE) +class MySQLHaRenameFlowBuilder(BaseMySQLTicketFlowBuilder): + serializer = TendbRenameSerializer + inner_flow_builder = TendbRenameFlowParamBuilder + inner_flow_name = _("Tendb Cluster 重命名执行") + retry_type = FlowRetryType.MANUAL_RETRY + + @property + def need_itsm(self): + return False diff --git a/dbm-ui/backend/ticket/constants.py b/dbm-ui/backend/ticket/constants.py index dc4af839b3..0cda6ca710 100644 --- a/dbm-ui/backend/ticket/constants.py +++ b/dbm-ui/backend/ticket/constants.py @@ -161,21 +161,27 @@ def get_choice_value(cls, label: str) -> str: MYSQL_SINGLE_TRUNCATE_DATA = EnumField("MYSQL_SINGLE_TRUNCATE_DATA", _("MySQL 单节点清档")) MYSQL_SINGLE_RENAME_DATABASE = EnumField("MYSQL_SINGLE_RENAME_DATABASE", _("MySQL 单节点DB重命名")) - # SPIDER - SPIDER_CHECKSUM = EnumField("SPIDER_CHECKSUM", _("Spider 数据校验修复")) - SPIDER_PARTITION = EnumField("SPIDER_PARTITION", _("Spider 分区管理")) - SPIDER_DB_TABLE_BACKUP = EnumField("SPIDER_DB_TABLE_BACKUP", _("Spider 库表备份")) - SPIDER_RENAME_DATABASE = EnumField("SPIDER_RENAME_DATABASE", _("Spider 数据库重命名")) - SPIDER_TRUNCATE_DATABASE = EnumField("SPIDER_TRUNCATE_DATABASE", _("Spider 清档")) # SPIDER(TenDB Cluster) - SPIDER_MASTER_FAIL_OVER = EnumField("SPIDER_MASTER_FAIL_OVER", _("TenDB Cluster 主故障切换")) - SPIDER_MASTER_SLAVE_SWITCH = EnumField("SPIDER_MASTER_SLAVE_SWITCH", _("TenDB Cluster 主从互切")) - TENDB_CLUSTER_APPLY = EnumField("TENDB_CLUSTER_APPLY", _("TenDB Cluster 集群部署")) - TENDB_CLUSTER_ENABLE = EnumField("TENDB_CLUSTER_ENABLE", _("TenDB Cluster 集群启用")) - TENDB_CLUSTER_DISABLE = EnumField("TENDB_CLUSTER_DISABLE", _("TenDB Cluster 集群禁用")) - TENDB_CLUSTER_DESTROY = EnumField("TENDB_CLUSTER_DESTROY", _("TenDB Cluster 集群销毁")) - SPIDER_FULL_BACKUP = EnumField("SPIDER_FULL_BACKUP", _("Spider 全备")) - TENDB_CLUSTER_FLASHBACK = EnumField("TENDBCLUSTER_FLASHBACK", _("TenDB Cluster Flashback")) + TENDBCLUSTER_CHECKSUM = EnumField("TENDBCLUSTER_CHECKSUM", _("TenDB Cluster 数据校验修复")) + TENDBCLUSTER_PARTITION = EnumField("TENDBCLUSTER_PARTITION", _("TenDB Cluster 分区管理")) + TENDBCLUSTER_DB_TABLE_BACKUP = EnumField("TENDBCLUSTER_DB_TABLE_BACKUP", _("TenDB Cluster 库表备份")) + TENDBCLUSTER_RENAME_DATABASE = EnumField("TENDBCLUSTER_RENAME_DATABASE", _("TenDB Cluster 数据库重命名")) + TENDBCLUSTER_TRUNCATE_DATABASE = EnumField("TENDBCLUSTER_TRUNCATE_DATABASE", _("TenDB Cluster 清档")) + TENDBCLUSTER_MASTER_FAIL_OVER = EnumField("TENDBCLUSTER_MASTER_FAIL_OVER", _("TenDB Cluster 主故障切换")) + TENDBCLUSTER_MASTER_SLAVE_SWITCH = EnumField("TENDBCLUSTER_MASTER_SLAVE_SWITCH", _("TenDB Cluster 主从互切")) + TENDBCLUSTER_IMPORT_SQLFILE = EnumField("TENDBCLUSTER_IMPORT_SQLFILE", _("TenDB Cluster 变更SQL执行")) + TENDBCLUSTER_SEMANTIC_CHECK = EnumField("TENDBCLUSTER_SEMANTIC_CHECK", _("TenDB Cluster 模拟执行")) + TENDBCLUSTER_SPIDER_ADD_NODES = EnumField("TENDBCLUSTER_SPIDER_ADD_NODES", _("TenDB Cluster 扩容接入层")) + TENDBCLUSTER_SPIDER_REDUCE_NODES = EnumField("TENDBCLUSTER_SPIDER_REDUCE_NODES", _("TenDB Cluster 缩容接入层")) + TENDBCLUSTER_SPIDER_MNT_APPLY = EnumField("TENDBCLUSTER_SPIDER_MNT_APPLY", _("TenDB Cluster 添加临时节点")) + TENDBCLUSTER_SPIDER_SLAVE_APPLY = EnumField("TENDBCLUSTER_SPIDER_SLAVE_APPLY", _("TenDB Cluster 部署只读集群")) + TENDBCLUSTER_APPLY = EnumField("TENDBCLUSTER_APPLY", _("TenDB Cluster 集群部署")) + TENDBCLUSTER_ENABLE = EnumField("TENDBCLUSTER_ENABLE", _("TenDB Cluster 集群启用")) + TENDBCLUSTER_DISABLE = EnumField("TENDBCLUSTER_DISABLE", _("TenDB Cluster 集群禁用")) + TENDBCLUSTER_DESTROY = EnumField("TENDBCLUSTER_DESTROY", _("TenDB Cluster 集群销毁")) + TENDBCLUSTER_NODE_REBALANCE = EnumField("TENDBCLUSTER_NODE_REBALANCE", _("TenDB Cluster 集群容量变更")) + TENDBCLUSTER_FULL_BACKUP = EnumField("TENDBCLUSTER_FULL_BACKUP", _("TenDB Cluster 全库备份")) + TENDBCLUSTER_FLASHBACK = EnumField("TENDBCLUSTER_FLASHBACK", _("TenDB Cluster Flashback")) # REDIS REDIS_PLUGIN_CREATE_CLB = EnumField("REDIS_PLUGIN_CREATE_CLB", _("Redis 创建CLB")) @@ -398,3 +404,12 @@ class WriteModeType(str, StructuredEnum): DELETE_WRITE = EnumField("delete_and_write_to_redis", _("删除同名key再写入")) APPEND_WRITE = EnumField("keep_and_append_to_redis", _("保留同名key追加写入")) FLUSH_WRITE = EnumField("flushall_and_write_to_redis", _("清空集群后写入")) + + +class TriggerChecksumType(str, StructuredEnum): + """ + 触发数据校验的类型 + """ + + NOW = EnumField("now", _("立刻触发")) + TIMER = EnumField("timer", _("定时触发")) From a58da53a59c7ee21d9832be09e5fd11f12718619 Mon Sep 17 00:00:00 2001 From: gaohongsong Date: Mon, 17 Jul 2023 16:29:50 +0800 Subject: [PATCH 156/476] =?UTF-8?q?feat:=20=E6=95=B4=E6=9C=BA=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E5=92=8C=E6=95=85=E9=9A=9C=E5=88=87=E6=8D=A2=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E8=B0=83=E6=95=B4=20#507?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db_services/redis/toolbox/handlers.py | 2 +- .../scene/redis/redis_cluster_scene_cmr.py | 19 +++++++++++-------- .../scene/redis/redis_cluster_scene_mss.py | 13 +++++++------ .../redis_toolbox_master_slave_switch.py | 1 + 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/dbm-ui/backend/db_services/redis/toolbox/handlers.py b/dbm-ui/backend/db_services/redis/toolbox/handlers.py index f130c14281..8ae74dcb1e 100644 --- a/dbm-ui/backend/db_services/redis/toolbox/handlers.py +++ b/dbm-ui/backend/db_services/redis/toolbox/handlers.py @@ -54,7 +54,7 @@ def query_master_slave_by_ip(self, master_ips) -> list: ms_pairs = StorageInstanceTuple.objects.filter(ejector__machine__ip=master_ip) results.append( { - "cluster": masters.first().cluster.first().simple_desc, + "cluster": masters.last().cluster.first().simple_desc, "master_ip": master_ip, "slave_ip": ms_pairs.last().receiver.machine.ip, "instances": map(lambda x: x.simple_desc, masters), diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py index 673830b835..3384e619b3 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_cmr.py @@ -8,6 +8,7 @@ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ +import copy import logging.config from collections import defaultdict from copy import deepcopy @@ -56,7 +57,7 @@ class RedisClusterCMRSceneFlow(object): "infos": [ { "cluster_id": 1, - "redis_proxy": [ + "proxy": [ {"ip": "1.1.1.a","spec_id": 17, "target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"} }], @@ -233,13 +234,13 @@ def generate_cluster_replacement(self, flow_data, act_kwargs, replacement_param) sub_pipeline.add_sub_pipeline(slave_replace_pipe) # 再添加Proxy替换流程 - if replacement_param.get("redis_proxy"): + if replacement_param.get("proxy"): proxy_kwargs = deepcopy(act_kwargs) self.proxy_replacement( sub_pipeline, proxy_kwargs, { - "redis_proxy": replacement_param.get("redis_proxy"), + "proxy": replacement_param.get("proxy"), "proxy_spec": replacement_param.get("resource_spec", {}).get("proxy", {}), }, ) @@ -270,7 +271,7 @@ def generate_cluster_replacement(self, flow_data, act_kwargs, replacement_param) def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_info): old_proxies, new_proxies = [], [] - proxy_replace_details = proxy_replace_info["redis_proxy"] + proxy_replace_details = proxy_replace_info["proxy"] for replace_link in proxy_replace_details: # {"ip": "1.1.1.a","spec_id": 17,"target": {"bk_cloud_id": 0,"bk_host_id": 216,"status": 1,"ip": "2.2.2.b"}} old_proxies.append(replace_link["ip"]) @@ -294,16 +295,17 @@ def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_info): ) for proxy_ip in new_proxies: + replace_kwargs = copy.deepcopy(act_kwargs) params = { "ip": proxy_ip, "redis_pwd": config_info["redis_password"], "proxy_pwd": config_info["password"], "proxy_port": int(config_info["port"]), - "servers": act_kwargs.cluster["backend_servers"], + "servers": replace_kwargs.cluster["backend_servers"], "spec_id": proxy_replace_info["proxy_spec"].get("id", 0), "spec_config": proxy_replace_info["proxy_spec"], } - sub_builder = ProxyBatchInstallAtomJob(self.root_id, self.data, act_kwargs, params) + sub_builder = ProxyBatchInstallAtomJob(self.root_id, self.data, replace_kwargs, params) sub_pipelines.append(sub_builder) sub_pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) @@ -345,7 +347,8 @@ def proxy_replacement(self, sub_pipeline, act_kwargs, proxy_replace_info): proxy_down_pipelines = [] for proxy_ip in old_proxies: params = {"ip": proxy_ip, "proxy_port": act_kwargs.cluster["proxy_port"]} - sub_builder = ProxyUnInstallAtomJob(self.root_id, self.data, act_kwargs, params) + uninstall_kwargs = copy.deepcopy(act_kwargs) + sub_builder = ProxyUnInstallAtomJob(self.root_id, self.data, uninstall_kwargs, params) proxy_down_pipelines.append(sub_builder) sub_pipeline.add_parallel_sub_pipeline(sub_flow_list=proxy_down_pipelines) @@ -357,7 +360,7 @@ def precheck_for_compelete_replace(self): except Cluster.DoesNotExist as e: raise Exception("redis cluster does not exist,{}", e) # check proxy - for proxy in cluster_replacement.get("redis_proxy", []): + for proxy in cluster_replacement.get("proxy", []): if not cluster.proxyinstance_set.filter(machine__ip=proxy["ip"]): raise Exception("proxy {} does not exist in cluster {}", proxy["ip"], cluster.immute_domain) # check slave diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py index de7d4fc7e0..8f765b7a8c 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py @@ -50,6 +50,7 @@ class RedisClusterMSSSceneFlow(object): "uid": "2023051612120001", "created_by":"vitox", "ticket_type":"REDIS_CLUSTER_MASTER_FAILOVER", + "force":false, # 是否需要强制切换 "infos": [ { "cluster_id": 1, @@ -57,7 +58,6 @@ class RedisClusterMSSSceneFlow(object): "pairs": [ {"redis_master": "1.1.a.3", "redis_slave": "1.1.2.b"} ] - "force_switch":false, # 是否需要强制切换 } ] } @@ -93,8 +93,8 @@ def __get_cluster_info(bk_biz_id: int, cluster_id: int) -> dict: raise Exception( "unsupport mutil slave with cluster {} 4:{}".format(cluster.immute_domain, master_obj.machine.ip) ) - else: - master_slave_map[master_obj.machine.ip] = slave_obj.machine.ip + + master_slave_map[master_obj.machine.ip] = slave_obj.machine.ip return { "immute_domain": cluster.immute_domain, @@ -127,6 +127,7 @@ def __init_builder(self, operate_name: str): def redis_ms_switch(self): redis_pipeline, act_kwargs = self.__init_builder(_("REDIS-主从切换")) sub_pipelines = [] + force_switch = self.data.get("force", False) for ms_switch in self.data["infos"]: cluster_kwargs = deepcopy(act_kwargs) cluster_info = self.__get_cluster_info(self.data["bk_biz_id"], ms_switch["cluster_id"]) @@ -142,14 +143,14 @@ def redis_ms_switch(self): act_component_code=GetRedisActPayloadComponent.code, kwargs=asdict(cluster_kwargs), ) - sub_pipeline = self.generate_ms_switch_flow(flow_data, cluster_kwargs, ms_switch) + sub_pipeline = self.generate_ms_switch_flow(flow_data, cluster_kwargs, ms_switch, force_switch) sub_pipelines.append(sub_pipeline) redis_pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) return redis_pipeline.run_pipeline() # 组装&控制 集群切换流程 - def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch): + def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch, force=False): """ 1. 切换前同步检查 2. 执行切换 3. 切换backends校验 @@ -189,7 +190,7 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch): sync_relations.append(sync_params) act_kwargs.cluster["switch_condition"] = { "sync_type": SyncType.SYNC_MS.value, - "is_check_sync": ms_switch.get("force_switch", True), # 强制切换 + "is_check_sync": force, # 强制切换 "slave_master_diff_time": DEFAULT_MASTER_DIFF_TIME, "last_io_second_ago": DEFAULT_LAST_IO_SECOND_AGO, "can_write_before_switch": True, diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_master_slave_switch.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_master_slave_switch.py index 3ecd2b6b8c..6a4d88accb 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_master_slave_switch.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_master_slave_switch.py @@ -32,6 +32,7 @@ class PairSerializer(serializers.Serializer): help_text=_("切换类型"), choices=SwitchConfirmType.get_choices(), default=SwitchConfirmType.NO_CONFIRM ) + force = serializers.BooleanField(help_text=_("是否强制执行"), required=False, default=False) infos = serializers.ListField(help_text=_("批量操作参数列表"), child=InfoSerializer()) From c9205471cd78f4b7aacd5b9a31eed740288ddbb5 Mon Sep 17 00:00:00 2001 From: xiepaup Date: Mon, 17 Jul 2023 16:53:53 +0800 Subject: [PATCH 157/476] =?UTF-8?q?fix(redis):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BB=E4=BB=8E=E5=88=87=E6=8D=A2=E6=B5=81=E7=A8=8B=20(#516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scene/redis/redis_cluster_scene_mss.py | 28 ++++--------------- .../backend/flow/utils/redis/redis_db_meta.py | 13 ++++++++- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py index 8f765b7a8c..1c7bffa552 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_cluster_scene_mss.py @@ -45,6 +45,7 @@ class RedisClusterMSSSceneFlow(object): ### 把Slave提升为Master #### 1. 正常手动切换 #### 2. 异常情况,强制切换 (1. 整机切换;2.部分切换) + #### 3. 这里只做元数据层的 master/slave 对调,不对old master 下架 { "bk_biz_id": 3, "uid": "2023051612120001", @@ -181,10 +182,10 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch, force=False) slave_port = slave_addr.split(IP_PORT_DIVIDER)[1] sync_params["ins_link"].append( { - "origin_1": master_port, - "origin_2": slave_port, - "sync_dst1": slave_port, - "sync_dst2": slave_port, + "origin_1": int(master_port), + "origin_2": int(slave_port), + "sync_dst1": int(slave_port), + "sync_dst2": int(slave_port), } ) sync_relations.append(sync_params) @@ -206,7 +207,7 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch, force=False) sub_kwargs.cluster["meta_update_ip"] = master_ip sub_kwargs.cluster["meta_udpate_ports"] = act_kwargs.cluster["master_ports"][master_ip] sub_kwargs.cluster["meta_update_status"] = InstanceStatus.UNAVAILABLE.value - sub_kwargs.cluster["meta_func_name"] = RedisDBMeta.instances_status_update.__name__ + sub_kwargs.cluster["meta_func_name"] = RedisDBMeta.instances_failover_4_scene.__name__ sub_acts.append( { "act_name": _("Redis-{}-元数据修改".format(master_ip)), @@ -249,23 +250,6 @@ def generate_ms_switch_flow(self, flow_data, act_kwargs, ms_switch, force=False) redis_pipeline.add_parallel_acts(acts_list=sub_acts) # 刷新监控 ###########################################################################完成###### - # #### 下架旧实例 ############################################################################# - sub_pipelines = [] - for master_ip in master_ips: - sub_pipelines.append( - RedisBatchShutdownAtomJob( - self.root_id, - flow_data, - act_kwargs, - { - "ip": master_ip, - "ports": act_kwargs.cluster["master_ports"][master_ip], - }, - ) - ) - redis_pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) - # #### 下架旧实例 ###################################################################### 完毕 ### - return redis_pipeline.build_sub_process( sub_name=_("Redis-{}-主从切换").format(act_kwargs.cluster["immute_domain"]) ) diff --git a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py index d12794d35b..e4b2d1615e 100644 --- a/dbm-ui/backend/flow/utils/redis/redis_db_meta.py +++ b/dbm-ui/backend/flow/utils/redis/redis_db_meta.py @@ -23,7 +23,7 @@ from backend.db_meta.api.cluster.tendispluscluster.handler import TendisPlusClusterHandler from backend.db_meta.api.cluster.tendisssd.handler import TendisSSDClusterHandler from backend.db_meta.enums import AccessLayer, ClusterPhase, ClusterType, InstanceInnerRole, InstanceRole, MachineType -from backend.db_meta.models import Cluster, Machine, ProxyInstance, StorageInstance +from backend.db_meta.models import Cluster, Machine, ProxyInstance, StorageInstance, StorageInstanceTuple from backend.db_services.dbbase.constants import IP_PORT_DIVIDER, SPACE_DIVIDER from backend.db_services.redis.rollback.models import TbTendisRollbackTasks from backend.flow.consts import DEFAULT_DB_MODULE_ID, ConfigFileEnum, ConfigTypeEnum, InstanceStatus @@ -417,6 +417,17 @@ def instances_status_update(self) -> bool: ).update(status=self.cluster["meta_update_status"]) return True + def instances_failover_4_scene(self) -> bool: + """1.修改状态、2.切换角色""" + self.instances_status_update() + with atomic(): + for port in self.cluster["meta_udpate_ports"]: + old_master = StorageInstance.objects.get(machine__ip=self.cluster["meta_update_ip"], port=port) + old_slave = old_master.as_ejector.get().receiver + StorageInstanceTuple.objects.get(ejector=old_master, receiver=old_slave).delete(keep_parents=True) + StorageInstanceTuple.objects.create(ejector=old_slave, receiver=old_master) + return True + def tendis_switch_4_scene(self): """切换 nosql_set_dtl, 挪动CC 模块""" cluster = Cluster.objects.get( From da0539b4b632e12457af5215eb5ee0ff1626714d Mon Sep 17 00:00:00 2001 From: iSecloud <869820505@qq.com> Date: Mon, 17 Jul 2023 17:05:56 +0800 Subject: [PATCH 158/476] =?UTF-8?q?fix(backend):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=A7=84=E6=A0=BC=E9=80=9A=E8=BF=87=E5=88=86=E7=89=87=E6=95=B0?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=20#519?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/db_services/dbresource/handlers.py | 18 +++++++++++------- .../db_services/dbresource/serializers.py | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/dbm-ui/backend/db_services/dbresource/handlers.py b/dbm-ui/backend/db_services/dbresource/handlers.py index 0616a4100f..a6fb3cf6a5 100644 --- a/dbm-ui/backend/db_services/dbresource/handlers.py +++ b/dbm-ui/backend/db_services/dbresource/handlers.py @@ -19,11 +19,12 @@ class ClusterSpecFilter(object): """集群规格的过滤器""" - def __init__(self, capacity, future_capacity, qps, spec_cluster_type, spec_machine_type): - # 用户的当前容量,期望容量以及期望qps范围 + def __init__(self, capacity, future_capacity, qps, spec_cluster_type, spec_machine_type, shard_num=0): + # 用户的当前容量,期望容量,期望qps范围和分片数(可选) self.capacity: int = capacity self.future_capacity: int = future_capacity self.qps: Dict = qps + self.filter_shard_num = shard_num # 当前集群的筛选规格 self.specs: List[Dict[str, Any]] = [ {**model_to_dict(spec), "capacity": spec.capacity} @@ -49,8 +50,8 @@ def _qps_check(self, user_qps_range, spec_qps_range): return True - def qps_filter(self): - """根据qps进行筛选""" + def system_filter(self): + """系统自带的过滤:qps和分片数""" valid_specs: List[Dict[str, Any]] = [] for spec in self.specs: qps_range = { @@ -60,6 +61,9 @@ def qps_filter(self): if not self._qps_check(self.qps, qps_range): continue + if self.filter_shard_num and spec["cluster_shard_num"] != self.filter_shard_num: + continue + valid_specs.append(spec) self.specs = valid_specs @@ -71,7 +75,7 @@ def custom_filter(self): def get_target_specs(self): self.calc_machine_pair() self.calc_cluster_shard_num() - self.qps_filter() + self.system_filter() self.custom_filter() return self.specs @@ -133,9 +137,9 @@ class TendisPlusSpecFilter(RedisSpecFilter): # 最佳容量管理大小 300G OPTIMAL_MANAGE_CAPACITY = 300 - def qps_filter(self): + def _qps_check(self, user_qps_range, spec_qps_range): # TendisPlus集群不需要qps过滤 - pass + return True def calc_machine_pair(self): """计算每种规格所需的机器组数,TendisPlus至少需要三组""" diff --git a/dbm-ui/backend/db_services/dbresource/serializers.py b/dbm-ui/backend/db_services/dbresource/serializers.py index 2a4b652a98..7b5b402d3b 100644 --- a/dbm-ui/backend/db_services/dbresource/serializers.py +++ b/dbm-ui/backend/db_services/dbresource/serializers.py @@ -165,7 +165,7 @@ class QueryOperationListSerializer(serializers.Serializer): ticket_types = serializers.CharField(help_text=_("过滤的单据类型列表"), required=False) task_ids = serializers.CharField(help_text=_("过滤的任务ID列表"), required=False) ip_list = serializers.CharField(help_text=_("过滤IP列表"), required=False) - orderby = serializers.CharField(help_text=_("排序模式"), required=False) + update_time = serializers.BooleanField(help_text=_("时间排序模式"), required=False, default=True) operator = serializers.CharField(help_text=_("操作者"), required=False) begin_time = serializers.CharField(help_text=_("操作开始时间"), required=False) @@ -188,6 +188,8 @@ def validate(self, attrs): if attrs.get("ip_list"): attrs["ip_list"] = attrs["ip_list"].split(",") + attrs["orderby"] = "asc" if attrs["update_time"] else "desc" + return attrs @@ -253,6 +255,7 @@ class QueryQPSRangeSerializer(serializers.Serializer): spec_machine_type = serializers.ChoiceField(help_text=_("角色类型"), choices=MachineType.get_choices()) capacity = serializers.IntegerField(help_text=_("当前容量需求")) future_capacity = serializers.IntegerField(help_text=_("未来容量需求")) + shard_num = serializers.IntegerField(help_text=_("所需分片数"), required=False, default=0) class QueryQPSRangeResponseSerializer(serializers.Serializer): From 843166d4e8590b825d34d02410ee28fdbe63fa2e Mon Sep 17 00:00:00 2001 From: ymakedaq <996156275@qq.com> Date: Mon, 17 Jul 2023 17:57:11 +0800 Subject: [PATCH 159/476] =?UTF-8?q?fix(dbm-services):=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?tdbctl=E8=A1=A8=E7=BB=93=E6=9E=84bug=20close=20#521?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subcmd/mysqlcmd/semantic_dump_schema.go | 17 ++++++++++++++--- .../components/mysql/semantic_dump_schema.go | 10 ++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_dump_schema.go b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_dump_schema.go index 4229fd1e74..cc7e6d8143 100644 --- a/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_dump_schema.go +++ b/dbm-services/mysql/db-tools/dbactuator/internal/subcmd/mysqlcmd/semantic_dump_schema.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysqlcmd import ( @@ -65,12 +75,13 @@ func (d *SenmanticDumpSchemaAct) Init() (err error) { func (d *SenmanticDumpSchemaAct) Run() (err error) { steps := subcmd.Steps{ { - FunName: "precheck", - Func: d.Service.Precheck, - }, { FunName: "init", Func: d.Service.Init, }, + { + FunName: "precheck", + Func: d.Service.Precheck, + }, { FunName: "运行导出表结构", Func: d.Service.DumpSchema, diff --git a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go index 41cfc19e75..ef5c900bb3 100644 --- a/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go +++ b/dbm-services/mysql/db-tools/dbactuator/pkg/components/mysql/semantic_dump_schema.go @@ -1,3 +1,13 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + package mysql import ( From 4887e41219b74f2b7e8e82d4fca49c36f9edf103 Mon Sep 17 00:00:00 2001 From: daryl Date: Fri, 14 Jul 2023 17:03:24 +0800 Subject: [PATCH 160/476] =?UTF-8?q?feat(frontend):=20=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=94=AF=E6=8C=81=E5=A4=9A=20ID=20=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=20#503?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/db-search-select/index.vue | 92 ++++------------ .../src/views/mission/common/types.ts | 5 - .../src/views/mission/hooks/useFetchData.ts | 101 ------------------ .../src/views/mission/pages/index.vue | 82 +++++++------- 4 files changed, 58 insertions(+), 222 deletions(-) delete mode 100644 dbm-ui/frontend/src/views/mission/hooks/useFetchData.ts diff --git a/dbm-ui/frontend/src/components/db-search-select/index.vue b/dbm-ui/frontend/src/components/db-search-select/index.vue index 5d39582f67..623d789627 100644 --- a/dbm-ui/frontend/src/components/db-search-select/index.vue +++ b/dbm-ui/frontend/src/components/db-search-select/index.vue @@ -13,10 +13,12 @@ diff --git a/dbm-ui/frontend/src/views/mission/pages/Details.vue b/dbm-ui/frontend/src/views/mission/pages/Details.vue index 40495c98b8..4ad745334e 100644 --- a/dbm-ui/frontend/src/views/mission/pages/Details.vue +++ b/dbm-ui/frontend/src/views/mission/pages/Details.vue @@ -226,6 +226,11 @@ + + diff --git a/dbm-ui/frontend/src/views/resource-pool/list/components/ImportHostBtn.vue b/dbm-ui/frontend/src/views/resource-pool/list/components/ImportHostBtn.vue index b4fa89c153..20287222f7 100644 --- a/dbm-ui/frontend/src/views/resource-pool/list/components/ImportHostBtn.vue +++ b/dbm-ui/frontend/src/views/resource-pool/list/components/ImportHostBtn.vue @@ -66,7 +66,9 @@ name: 'DatabaseMission', params: { bizId: taskInfo.value?.bk_biz_id, - id: taskInfo.value?.task_ids.join(','), + }, + query: { + root_ids: taskInfo.value?.task_ids.join(','), }, }); }; diff --git a/dbm-ui/frontend/src/views/resource-pool/record/Index.vue b/dbm-ui/frontend/src/views/resource-pool/record/Index.vue index 1c8f93983a..909fccee59 100644 --- a/dbm-ui/frontend/src/views/resource-pool/record/Index.vue +++ b/dbm-ui/frontend/src/views/resource-pool/record/Index.vue @@ -21,7 +21,8 @@ + :data-source="dataSource" + @clear-search="handleClearSearch" />
+ diff --git a/dbm-ui/frontend/src/components/smart-action/index.vue b/dbm-ui/frontend/src/components/smart-action/index.vue index 6916bcbcce..21fed80a62 100644 --- a/dbm-ui/frontend/src/components/smart-action/index.vue +++ b/dbm-ui/frontend/src/components/smart-action/index.vue @@ -19,6 +19,7 @@ role="placeholder" :style="placeholderStyles">
Element | null; fill?: number; + showActionArea?: boolean; } const props = withDefaults(defineProps(), { fill: 0, offsetTarget: () => null, + showActionArea: true, }); const placeholderRef = ref(); diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 115dd0e134..24509571c9 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -1480,7 +1480,7 @@ "无需确认": "无需确认", "请输入或选择集群": "请输入或选择集群", "台数只能为正整数": "台数只能为正整数", - "不能大于最大台数": "不能大于最大台数", + "必须小于当前台数": "必须小于当前台数", "缩容接入层提交成功": "缩容接入层提交成功", "请先输入集群": "请先输入集群", "请输入字段名搜索": "请输入字段名搜索", @@ -1623,5 +1623,60 @@ "移入待回收": "移入待回收", "确认将以下主机转移至待回收模块": "确认将以下主机转移至待回收模块?", "转移成功": "转移成功", + "确认复制n个集群数据?": "确认从n个集群进行数据复制?", + "将会把源集群的数据复制到对应的新集群": "将会把源集群的数据复制到对应的新集群", + "数据复制任务提交成功": "数据复制任务提交成功", + "数据传输记录": "数据传输记录", + "成功后,数据同步关系会一直保持,如需断开,请跳转至xx 断开同步": "成功后,数据同步关系会一直保持,如需断开,请跳转至“{0}” 断开同步", + "数据复制记录": "数据复制记录", + "源集群": "源集群", + "复制类型": "复制类型", + "包含 key": "包含 key", + "排除 key": "排除 key", + "最近一次修复单": "最近一次修复单", + "断开同步": "断开同步", + "数据校验与修复": "数据校验与修复", + "全量传输中": "全量传输中", + "增量传输中": "增量传输中", + "全量传输失败": "全量传输失败", + "增量传输失败": "增量传输失败", + "传输结束": "传输结束", + "传输终止": "传输终止", + "【数据复制】传输详情": "【数据复制】传输详情", + "请选择目标业务": "请选择目标业务", + "Task 类型": "Task 类型", + "执行状态": "执行状态", + "请选择条件进行搜索": "请选择条件进行搜索", + "确认断开同步?": "确认断开同步?", + "断开后,数据将不会再再自动同步,请谨慎操作!": "断开后,数据将不会再再自动同步,请谨慎操作!", + "重新复制": "重新复制", + "确认重新复制数据?": "确认重新复制数据?", + "全量覆盖同名 Key(如:del $key+ hset $key)": "全量覆盖同名 Key(如:del $key+ hset $key)", + "增量覆盖同名 Key(如:hset $key)": "增量覆盖同名 Key(如:hset $key)", + "清空目标集群所有数据": "清空目标集群所有数据", + "请输入集群名称": "请输入集群名称", + "回写数据:xxx": "回写数据:xxx", + "以构造实例恢复": "以构造实例恢复", + "输入访问入口后自动生成": "输入访问入口后自动生成", + "请输入或选择构造实例": "请输入或选择构造实例", + "构造实例不能为空": "构造实例不能为空", + "确认对n个构造实例进行恢复?": "确认对 {n} 个构造实例进行恢复?", + "以构造实例恢复任务提交成功": "以构造实例恢复任务提交成功", + "目标集群输入格式有误": "目标集群输入格式有误", + "必须大于当前台数": "必须大于当前台数", + "格式有误,请输入数字": "格式有误,请输入数字", + "IP不能为空": "IP不能为空", + "磁盘类别": "磁盘类别", + "最小容量(G)": "最小容量(G)", + "数据回写任务提交成功": "数据回写任务提交成功", + "集群分片变更:xxx": "集群分片变更:xxx", + "集群分片变更": "集群分片变更", + "请选择部署方案": "请选择部署方案", + "请先选择部署方案": "请先选择部署方案", + "写入类型": "写入类型", + "断开设置": "断开设置", + "提醒频率": "提醒频率", + "校验与修复类型": "校验与修复类型", + "校验与修复频率设置": "校验与修复频率设置", "这行勿动!新增翻译请在上一行添加!": "" -} +} \ No newline at end of file diff --git a/dbm-ui/frontend/src/services/clusters.ts b/dbm-ui/frontend/src/services/clusters.ts index 19dbfe6b46..06e24b8d41 100644 --- a/dbm-ui/frontend/src/services/clusters.ts +++ b/dbm-ui/frontend/src/services/clusters.ts @@ -22,12 +22,13 @@ import type { InstanceInfos, MySQLClusterInfos, ResourceInstance, - ResourceItem, ResourceParams, + ResourceItem, ResourceParams, ResourcesResult, ResourceTopo, ResourceTopoParams, TableFieldsItem, - TableFieldsParams } from './types/clusters'; + TableFieldsParams, +} from './types/clusters'; import type { HostNode, ListBase } from './types/common'; /** @@ -48,7 +49,7 @@ export const getResourceDetails = (dbType: string, params: ResourceParams): P /** * 获取集群实例列表 */ -export const getResourceInstances = (params: {db_type: string, type?: string, bk_biz_id: number} & Record): Promise> => http.get(`/apis/${params.db_type}/bizs/${params.bk_biz_id}/${params.type}_resources/list_instances/`, params); +export const getResourceInstances = (params: { db_type: string, type?: string, bk_biz_id: number } & Record): Promise> => http.get(`/apis/${params.db_type}/bizs/${params.bk_biz_id}/${params.type}_resources/list_instances/`, params); /** * 获取集群实例详情 @@ -89,7 +90,7 @@ export const checkInstances = ( export const getClusterDBNames = ( bizId: number, params: Record<'cluster_ids', Array>, -): Promise, system_databases: Array}>> => http.post(`/apis/mysql/bizs/${bizId}/remote_service/show_cluster_databases/`, params); +): Promise, system_databases: Array }>> => http.post(`/apis/mysql/bizs/${bizId}/remote_service/show_cluster_databases/`, params); /** * 通过集群域名获取集群详情 @@ -109,15 +110,21 @@ export const findRelatedClustersByClusterIds = ( cluster_id: number, cluster_info: MySQLClusterInfos, related_clusters: Array - }>> => http.post(`/apis/mysql/bizs/${bizId}/cluster/find_related_clusters_by_cluster_ids/`, params); +}>> => http.post(`/apis/mysql/bizs/${bizId}/cluster/find_related_clusters_by_cluster_ids/`, params); /** * 校验DB是否在集群内 */ export const checkClusterDatabase = function (params: { - bk_biz_id: number, - cluster_id: number, - db_name: string - }): Promise { + bk_biz_id: number, + cluster_id: number, + db_name: string +}): Promise { return http.post(`/apis/mysql/bizs/${params.bk_biz_id}/remote_service/check_cluster_database/`, params); }; + + +/** + * 查询所有数据库的版本列表 + */ +export const getClusterTypeToVersions = (): Promise> => http.get('/apis/version/cluster_type_to_versions/'); diff --git a/dbm-ui/frontend/src/services/model/redis/redis-cluster-node-by-ip.ts b/dbm-ui/frontend/src/services/model/redis/redis-cluster-node-by-ip.ts index 0284b10650..dd27224f0c 100644 --- a/dbm-ui/frontend/src/services/model/redis/redis-cluster-node-by-ip.ts +++ b/dbm-ui/frontend/src/services/model/redis/redis-cluster-node-by-ip.ts @@ -12,6 +12,8 @@ */ export default class RedisClusterNodeByIp { + bk_host_id: number; + bk_cloud_id: number; cluster: { bk_cloud_id: number; cluster_type: string; @@ -34,6 +36,7 @@ export default class RedisClusterNodeByIp { }; ip: string; role: string; + spec_id: number; spec_config: { count: number; cpu: { @@ -58,9 +61,12 @@ export default class RedisClusterNodeByIp { }; constructor(payload = {} as RedisClusterNodeByIp) { + this.bk_host_id = payload.bk_host_id; + this.bk_cloud_id = payload.bk_cloud_id; this.cluster = payload.cluster; this.ip = payload.ip; this.role = payload.role; + this.spec_id = payload.spec_id; this.spec_config = payload.spec_config; } } diff --git a/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts b/dbm-ui/frontend/src/services/model/resource-spec/redis-cluster-sepc.ts similarity index 96% rename from dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts rename to dbm-ui/frontend/src/services/model/resource-spec/redis-cluster-sepc.ts index 13c4e2ec69..cefc266515 100644 --- a/dbm-ui/frontend/src/services/model/resource-spec/cluster-sepc.ts +++ b/dbm-ui/frontend/src/services/model/resource-spec/redis-cluster-sepc.ts @@ -23,6 +23,7 @@ export default class RedisClusterSpec { max: number; }; creator: string; + cluster_qps: number; desc: string; instance_num: number; machine_pair: number; @@ -50,6 +51,7 @@ export default class RedisClusterSpec { this.cluster_shard_num = payload.cluster_shard_num; this.cpu = payload.cpu; this.creator = payload.creator; + this.cluster_qps = payload.cluster_qps; this.desc = payload.desc; this.instance_num = payload.instance_num; this.machine_pair = payload.machine_pair; diff --git a/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts b/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts index d3737ca5a7..7c7e7380f2 100644 --- a/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts +++ b/dbm-ui/frontend/src/services/model/resource-spec/resourceSpec.ts @@ -63,4 +63,8 @@ export default class ResourceSpec { this.qps = payload.qps; } } + + get name() { + return this.spec_name; + } } diff --git a/dbm-ui/frontend/src/services/resourceSpec.ts b/dbm-ui/frontend/src/services/resourceSpec.ts index 803603b9c9..1e3bd677d1 100644 --- a/dbm-ui/frontend/src/services/resourceSpec.ts +++ b/dbm-ui/frontend/src/services/resourceSpec.ts @@ -12,47 +12,14 @@ */ import http from './http'; +import RedisClusterSpecModel from './model/resource-spec/redis-cluster-sepc'; import ResourceSpecModel from './model/resource-spec/resourceSpec'; import type { ListBase } from './types/common'; -export interface FilterClusterSpecItem { - creator: string, - updater: string, - spec_id: number, - spec_name: string, - spec_cluster_type: string, - spec_machine_type: string, - cpu: { - max: number, - min: number - }, - mem: { - max: number, - min: number - }, - device_class: string[], - storage_spec: { - size: number, - type: string, - mount_point: string - }[], - desc: string, - instance_num: number, - qps: { - max: number, - min: number - }, - cluster_qps: string, - capacity: number, - machine_pair: number, - cluster_capacity: number, - cluster_shard_num: number -} - // 获取资源规格列表 -export const getResourceSpecList = function (params: Record & { +export const getResourceSpecList = function (params: Record & { spec_cluster_type: string, - spec_machine_type: string, + spec_machine_type?: string, }) { return http.get>('/apis/dbresource/spec/', params) .then(res => ({ @@ -72,7 +39,7 @@ export const updateResourceSpec = function (specId: number, params: Record & {spec_ids: number[]}) { +export const batchDeleteResourceSpec = function (params: Record & { spec_ids: number[] }) { return http.delete('/apis/dbresource/spec/batch_delete/', params, {}); }; @@ -87,16 +54,17 @@ export const queryQPSRange = (params: { spec_machine_type: string, capacity: number, future_capacity: number, -}) => http.get<{max: number, min: number}>('/apis/dbresource/spec/query_qps_range/', params); +}) => http.get<{ max: number, min: number }>('/apis/dbresource/spec/query_qps_range/', params); // 筛选集群部署规格方案 export const getFilterClusterSpec = (params: { spec_cluster_type: string, spec_machine_type: string, + shard_num: number, capacity: number, future_capacity: number, qps: { min: number, max: number } -}) => http.post('/apis/dbresource/spec/filter_cluster_spec/', params); +}) => http.post('/apis/dbresource/spec/filter_cluster_spec/', params); diff --git a/dbm-ui/frontend/src/styles/common.less b/dbm-ui/frontend/src/styles/common.less index ae878de071..b65271f5c7 100644 --- a/dbm-ui/frontend/src/styles/common.less +++ b/dbm-ui/frontend/src/styles/common.less @@ -636,3 +636,39 @@ .dbm-fade-leave-to { opacity: 0%; } + +.title-spot { + position: relative; + width: 100%; + height: 20px; + font-size: 12px; + font-weight: 700; + color: @default-color; + + .required { + position: relative; + + &::after { + position: absolute; + top: -10px; + margin-left: 4px; + font-size: 12px; + line-height: 40px; + color: @danger-color; + content: "*"; + } + } +} + +.shadow-left { + &::before { + position: absolute; + top: 0; + left: -10px; + width: 10px; + height: 100%; + background: linear-gradient(to left, rgb(0 0 0 / 12%), transparent); + content: ''; + } + +} \ No newline at end of file diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue index 0776bf2ce4..be863370c2 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/Index.vue @@ -20,14 +20,16 @@ :title="$t('集群容量变更:XXX')" /> + @click-cancel="() => showChooseClusterTargetPlan = false" + @click-confirm="handleChoosedTargetCapacity" /> @@ -69,7 +72,9 @@ import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; - import RedisClusterSpecModel from '@services/model/resource-spec/cluster-sepc'; + import { getClusterTypeToVersions } from '@services/clusters'; + import { RedisClusterTypes } from '@services/model/redis/redis'; + import RedisClusterSpecModel from '@services/model/resource-spec/redis-cluster-sepc'; import { createTicket } from '@services/ticket'; import type { SubmitTicket } from '@services/types/ticket'; @@ -77,10 +82,10 @@ import { ClusterTypes, TicketTypes } from '@common/const'; + import ChooseClusterTargetPlan, { type Props as TargetPlanProps } from '@views/redis/common/cluster-deploy-plan/Index.vue'; import ClusterSelector from '@views/redis/common/cluster-selector/ClusterSelector.vue'; - import { getClusterInfo, getRedisVersions } from '@views/redis/common/utils'; + import { getClusterInfo } from '@views/redis/common/utils'; - import ChooseClusterTargetPlan from './components/ChooseClusterTargetPlan.vue'; import RenderData from './components/Index.vue'; import { OnlineSwitchType } from './components/RenderSwitchMode.vue'; import RenderDataRow, { @@ -126,26 +131,33 @@ const rowRefs = ref(); const isShowMasterInstanceSelector = ref(false); const isSubmitting = ref(false); - const tableData = ref([createRowData()]); - const versionList = ref<{ - id: string; - name: string - }[]>([]); const showChooseClusterTargetPlan = ref(false); - const activeRowData = ref(); + const activeRowData = ref(); const activeRowIndex = ref(0); + const isFixed = ref(false); + const versionsMap = ref>({}); + const totalNum = computed(() => tableData.value.filter(item => Boolean(item.targetCluster)).length); const clusterSelectorTabList = [ClusterTypes.REDIS]; // 集群域名是否已存在表格的映射表 - let domainMemo = {} as Record; + let domainMemo: Record = {}; onMounted(() => { - fetchVersions(); + queryDBVersions(); }); + const queryDBVersions = async () => { + const ret = await getClusterTypeToVersions(); + versionsMap.value = ret; + }; + + const handleScrollDisplay = (status: boolean) => { + isFixed.value = status; + }; + // 从侧边窗点击确认后触发 const handleChoosedTargetCapacity = (obj: RedisClusterSpecModel) => { const currentRow = tableData.value[activeRowIndex.value]; @@ -174,7 +186,14 @@ activeRowIndex.value = index; const rowData = tableData.value[index]; if (rowData.targetCluster) { - activeRowData.value = rowData; + const obj = { + targetCluster: rowData.targetCluster, + currentSepc: rowData.currentSepc ?? '', + capacity: rowData.currentCapacity ?? { total: 1, used: 0 }, + clusterType: rowData.clusterType ?? RedisClusterTypes.TwemproxyRedisInstance, + shardNum: rowData.shardNum ?? 0, + }; + activeRowData.value = obj; showChooseClusterTargetPlan.value = true; } }; @@ -252,24 +271,26 @@ // 根据表格数据生成提交单据请求参数 const generateRequestParam = (moreList: GetRowMoreInfo[]) => { - const dataArr = tableData.value.filter(item => item.targetCluster !== ''); - const infos = dataArr.map((item, index) => { - const obj: InfoItem = { - cluster_id: item.clusterId, - db_version: moreList[index].version, - bk_cloud_id: item.bkCloudId, - shard_num: item.targetShardNum ?? 0, - group_num: item.targetGroupNum ?? 0, - online_switch_type: moreList[index].switchMode, - resource_spec: { - backend_group: { - spec_id: item.sepcId ?? 0, - count: item.targetGroupNum ?? 0, // 机器组数 - affinity: AffinityType.CROS_SUBZONE, // 暂时固定 'CROS_SUBZONE', + const infos: InfoItem[] = []; + tableData.value.forEach((item, index) => { + if (item.targetCluster) { + const obj: InfoItem = { + cluster_id: item.clusterId, + db_version: moreList[index].version, + bk_cloud_id: item.bkCloudId, + shard_num: item.targetShardNum ?? 0, + group_num: item.targetGroupNum ?? 0, + online_switch_type: moreList[index].switchMode, + resource_spec: { + backend_group: { + spec_id: item.sepcId ?? 0, + count: item.targetGroupNum ?? 0, // 机器组数 + affinity: AffinityType.CROS_SUBZONE, // 暂时固定 'CROS_SUBZONE', + }, }, - }, - }; - return obj; + }; + infos.push(obj); + } }); return infos; }; @@ -322,12 +343,6 @@ domainMemo = {}; window.changeConfirm = false; }; - - // 获取 redis 版本信息 - const fetchVersions = async () => { - const list = await getRedisVersions(); - if (list) versionList.value = list; - }; diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/Index.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/Index.vue new file mode 100644 index 0000000000..268f018590 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/Index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/Index.vue new file mode 100644 index 0000000000..f587d210fd --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/Index.vue @@ -0,0 +1,361 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Index.vue new file mode 100644 index 0000000000..79b510f50b --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Index.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderDeployPlan.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderDeployPlan.vue new file mode 100644 index 0000000000..4463598f2c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderDeployPlan.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderNodeType.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderNodeType.vue new file mode 100644 index 0000000000..040ca89f2c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderNodeType.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderSwitchMode.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderSwitchMode.vue new file mode 100644 index 0000000000..3b34b3590f --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderSwitchMode.vue @@ -0,0 +1,93 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderTargetCluster.vue new file mode 100644 index 0000000000..c7403ad820 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/RenderTargetCluster.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Row.vue new file mode 100644 index 0000000000..b3a616a319 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page1/components/Row.vue @@ -0,0 +1,170 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page2/Index.vue new file mode 100644 index 0000000000..b01ccc3d5c --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/cluster-shard-update/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue b/dbm-ui/frontend/src/views/redis/common/cluster-deploy-plan/Index.vue similarity index 81% rename from dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue rename to dbm-ui/frontend/src/views/redis/common/cluster-deploy-plan/Index.vue index b885bf0121..31a4536fbe 100644 --- a/dbm-ui/frontend/src/views/redis/capacity-change/pages/page1/components/ChooseClusterTargetPlan.vue +++ b/dbm-ui/frontend/src/views/redis/common/cluster-deploy-plan/Index.vue @@ -42,7 +42,10 @@ 变更后的规格:
- {{ targetSepc }} + {{ targetSepc }} + {{ t('请先选择部署方案') }}
@@ -71,20 +74,23 @@ 变更后容量:
- - {{ targetPercent }}% - {{ `(${targetCapacity.used}G/${targetCapacity.total}G)` }} - {{ `(${changeObj.rate}%, ${changeObj.num}G)` }} + + {{ t('请先选择部署方案') }}
@@ -92,17 +98,16 @@
- 目标集群容量需求 + 目标集群容量需求
+ type="number" + @change="(value) => capacityNeed = Number(value)" />
G
@@ -110,17 +115,16 @@
- 未来集群容量需求 + 未来集群容量需求
+ type="number" + @change="(value) => capacityFutureNeed = Number(value)" />
G
@@ -129,7 +133,7 @@
- QPS 预估范围 + QPS 预估范围
- 集群部署方案 + 集群部署方案
- + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/ExecuteStatus.vue b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/ExecuteStatus.vue new file mode 100644 index 0000000000..9256ffa14a --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/ExecuteStatus.vue @@ -0,0 +1,95 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/Index.vue new file mode 100644 index 0000000000..bd104adbe9 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page1/Index.vue @@ -0,0 +1,453 @@ + + + + + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page2/Index.vue new file mode 100644 index 0000000000..b17747ed45 --- /dev/null +++ b/dbm-ui/frontend/src/views/redis/db-data-copy-record/pages/page2/Index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue index 4ba483449b..20e086d3bb 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/Index.vue @@ -21,15 +21,17 @@
- 复制类型 + {{ t('复制类型') }}
+ :key="item.value" + :label="item.value"> + {{ item.label }} +
+ :cluster-list="clusterList" + @on-change-table-available="handleTableDataAvailableChange" /> + :cluster-list="clusterList" + @on-change-table-available="handleTableDataAvailableChange" /> + :cluster-list="clusterList" + @on-change-table-available="handleTableDataAvailableChange" />
- 写入类型 + style="margin: 25px 0 12px;"> + {{ t('写入类型') }}
@@ -63,8 +68,10 @@ {{ item.label }} -
- 断开设置 +
+ {{ t('断开设置') }}
@@ -76,8 +83,10 @@ diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue index cbf695d407..ac1509c407 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/Index.vue @@ -13,8 +13,14 @@ - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue deleted file mode 100644 index 534d5fa6ef..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/cross-business/RenderTargetCluster.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderKeyRelated.vue deleted file mode 100644 index 8940273c1a..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderKeyRelated.vue +++ /dev/null @@ -1,140 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderTargetCluster.vue deleted file mode 100644 index e65d506c98..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/intra-business-third/RenderTargetCluster.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue deleted file mode 100644 index 8940273c1a..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/selfbuilt-clusters-intra-business/RenderKeyRelated.vue +++ /dev/null @@ -1,140 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue deleted file mode 100644 index a46333bf7f..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderKeyRelated.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue deleted file mode 100644 index e65d506c98..0000000000 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/within-business/RenderTargetCluster.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue index 5cbd182346..acd07640a1 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page2/Index.vue @@ -23,21 +23,22 @@ {{ $t('我的服务单') }} - + ; +
handleChangeHostIp(index, ip)" @remove="handleRemove(index)" /> -
+ diff --git a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue index 9e98728f7d..18deb99adf 100644 --- a/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue +++ b/dbm-ui/frontend/src/views/redis/db-replace/pages/page1/components/RenderSpec.vue @@ -21,7 +21,8 @@ + :data="data" + :hide-qps="hideQps"> diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderTargetHostNumber.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderTargetHostNumber.vue index 8b1d091d65..c8ee914f94 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderTargetHostNumber.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/RenderTargetHostNumber.vue @@ -29,7 +29,8 @@ import type { IDataRow } from './Row.vue'; interface Props { - modelValue?: IDataRow['hostNum']; + data?: IDataRow['hostNum']; + max?: number; isLoading?: boolean; } @@ -38,11 +39,12 @@ } const props = withDefaults(defineProps(), { - modelValue: '', + data: '', + max: 0, }); const { t } = useI18n(); - const localValue = ref(props.modelValue); + const localValue = ref(props.data); const editRef = ref(); const nonInterger = /\D/g; @@ -56,6 +58,10 @@ validator: (value: string) => !nonInterger.test(_.trim(value)), message: t('格式有误,请输入数字'), }, + { + validator: (value: string) => Number(_.trim(value)) <= props.max, + message: t('不能超过实例数'), + }, ]; defineExpose({ diff --git a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue index 67a52b680f..202a33d57e 100644 --- a/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/db-structure/pages/page1/components/Row.vue @@ -22,7 +22,8 @@ + :is-loading="data.isLoading" + @change="handleChoosedListChange" /> + :is-loading="data.isLoading" + :max="targetMax" /> @@ -85,10 +87,17 @@ targetDateTime?: string; } - export interface MoreInfoItem { - instances: string[]; - hostNum: string; - targetDateTime: string; + export interface InfoItem { + cluster_id: number, + bk_cloud_id: number; + master_instances:string[], + recovery_time_point: string, + resource_spec: { + redis: { + spec_id: number, + count: number, + } + } } // 创建表格数据 @@ -110,11 +119,11 @@ interface Emits { (e: 'add', params: Array): void, (e: 'remove'): void, - (e: 'onClusterInputFinish', value: string): void + (e: 'clusterInputFinish', value: string): void } interface Exposes { - getValue: () => Promise + getValue: () => Promise } const props = defineProps(); @@ -124,10 +133,14 @@ const instanceRef = ref(); const hostNumRef = ref(); const timeRef = ref(); + const targetMax = ref(0); + const handleChoosedListChange = (arr: string[]) => { + targetMax.value = arr.length; + }; const handleInputFinish = (value: string) => { - emits('onClusterInputFinish', value); + emits('clusterInputFinish', value); }; const handleAppend = () => { @@ -148,9 +161,16 @@ ]).then((data) => { const [instances, hostNum, targetDateTime] = data; return { - instances, - hostNum, - targetDateTime, + cluster_id: props.data.clusterId, + bk_cloud_id: props.data.bkCloudId, + master_instances: instances, + recovery_time_point: targetDateTime, + resource_spec: { + redis: { + spec_id: props.data.spec?.id ?? 0, + count: Number(hostNum), + }, + }, }; }); }, diff --git a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue index 1b1c8b38e5..96e86fc912 100644 --- a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/Index.vue @@ -19,13 +19,18 @@ theme="info" :title="$t('主库故障切换:主机级别操作,即同机所有集群的从库均会升级成主库')" />
- - - 强制切换 - - + + + + + {{ $t('强制切换') }}
{ - const moreDataList = await Promise.all(rowRefs.value.map((item: { - getValue: () => Promise - }) => item.getValue())); - const infos = tableData.value.reduce((result: InfoItem[], item, index) => { - if (item.ip) { - const infoItem: InfoItem = { - cluster_id: item.clusterId, - online_switch_type: moreDataList[index], - pairs: [ - { - redis_master: item.ip, - redis_slave: item.slave, - }, - ], - }; - result.push(infoItem); - } - return result; - }, []); - return infos; - }; - // 提交 const handleSubmit = async () => { - const infos = await generateRequestParam(); + const infos = await Promise.all(rowRefs.value.map((item: { + getValue: () => Promise + }) => item.getValue())); + const params: SubmitTicket & { details: { force: boolean }} = { bk_biz_id: currentBizId, ticket_type: TicketTypes.REDIS_MASTER_SLAVE_SWITCH, diff --git a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/components/Row.vue index fb55ca2d0b..b3062f643d 100644 --- a/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/master-failover/pages/page1/components/Row.vue @@ -67,7 +67,7 @@ import RenderHost from './RenderHost.vue'; import RenderMasterInstance from './RenderMasterInstance.vue'; import RenderSlaveHost from './RenderSlaveHost.vue'; - import RenderSwitchMode from './RenderSwitchMode.vue'; + import RenderSwitchMode, { OnlineSwitchType } from './RenderSwitchMode.vue'; export interface IDataRow { rowKey: string; @@ -80,6 +80,14 @@ masters?:string[]; } + export interface InfoItem { + cluster_id: number, + online_switch_type: OnlineSwitchType, + pairs: { + redis_master: string, + redis_slave: string, + }[] + } // 创建表格数据 export const createRowData = (data?: IDataRow): IDataRow => ({ rowKey: random(), @@ -106,7 +114,7 @@ } interface Exposes { - getValue: () => Promise + getValue: () => Promise } const props = defineProps(); @@ -131,7 +139,19 @@ }; defineExpose({ - getValue: async () => await switchModeRef.value.getValue(), + getValue: async () => { + const switchType = await switchModeRef.value.getValue(); + return { + cluster_id: props.data.clusterId, + online_switch_type: switchType, + pairs: [ + { + redis_master: props.data.ip, + redis_slave: props.data.slave, + }, + ], + }; + }, }); diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue index c38ccd7e15..c43332f4df 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/Index.vue @@ -28,7 +28,7 @@ :data="item" :removeable="tableData.length < 2" @add="(payload: Array) => handleAppend(index, payload)" - @on-cluster-input-finish="(domain: string) => handleChangeCluster(index, domain)" + @cluster-input-finish="(domain: string) => handleChangeCluster(index, domain)" @remove="handleRemove(index)" /> ) => { if (list.length > 1) { @@ -135,7 +126,7 @@ id: item.cluster_spec.spec_id, count: item.proxy.length, }, - targetNum: '1', + targetNum: '2', }); // 批量选择 @@ -182,30 +173,11 @@ delete domainMemo[cluster]; }; - // 根据表格数据生成提交单据请求参数 - const generateRequestParam = (moreList: GetRowMoreInfo[]) => { - const infos = tableData.value.reduce((result: InfoItem[], item, index) => { - if (item.cluster) { - const obj: InfoItem = { - cluster_id: item.clusterId, - bk_cloud_id: item.bkCloudId, - target_proxy_count: moreList[index].targetNum, - online_switch_type: moreList[index].switchMode, - }; - result.push(obj); - } - return result; - }, []); - return infos; - }; - // 点击提交按钮 const handleSubmit = async () => { - const moreList = await Promise.all(rowRefs.value.map((item: { - getValue: () => Promise + const infos = await Promise.all(rowRefs.value.map((item: { + getValue: () => Promise }) => item.getValue())); - - const infos = generateRequestParam(moreList); const params: SubmitTicket = { bk_biz_id: currentBizId, ticket_type: TicketTypes.PROXY_SCALE_DOWN, diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue index c18b2320fd..051e2a436a 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-down/pages/page1/components/RenderSpec.vue @@ -20,7 +20,8 @@ {{ data?.name ? `${data.name} ${$t('((n))台', {n: data?.count})}` : '' }} + :data="data" + hide-qps> @@ -47,7 +47,7 @@ const props = defineProps(); const isShowEye = ref(true); const selectRef = ref(); - const localValue = ref(''); + const localValue = ref(0); const { t } = useI18n(); @@ -58,7 +58,15 @@ }, ]; - const handleChange = (value: string) => { + watch(() => props.data, (data) => { + if (data) { + localValue.value = data.id; + } + }, { + immediate: true, + }); + + const handleChange = (value: number) => { localValue.value = value; }; diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue index b26c263cf5..0c5581020a 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/RenderTargetNumber.vue @@ -29,7 +29,7 @@ import type { IDataRow } from './Row.vue'; interface Props { - modelValue?: IDataRow['targetNum']; + data?: IDataRow['targetNum']; min?: number; isLoading?: boolean; } @@ -39,12 +39,12 @@ } const props = withDefaults(defineProps(), { - modelValue: '', + data: '', min: 0, }); const { t } = useI18n(); - const localValue = ref(props.modelValue); + const localValue = ref(props.data); const editRef = ref(); const nonInterger = /\D/g; diff --git a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue index a0cf4ed21f..91781a107c 100644 --- a/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue +++ b/dbm-ui/frontend/src/views/redis/proxy-scale-up/pages/page1/components/Row.vue @@ -58,6 +58,8 @@ diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue deleted file mode 100644 index 9ea81c6eac..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Index.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue deleted file mode 100644 index 9084f51063..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderEntry.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue deleted file mode 100644 index 310f54fbb1..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderInstance.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue deleted file mode 100644 index 9e98728f7d..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderSpec.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue deleted file mode 100644 index 633f107a3d..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetCluster.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue deleted file mode 100644 index 36a43d1fce..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/RenderTargetDateTime.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue deleted file mode 100644 index 244df557f8..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/Row.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue deleted file mode 100644 index ee2db733c6..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecPanel.vue +++ /dev/null @@ -1,222 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue b/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue deleted file mode 100644 index bd47c670e6..0000000000 --- a/dbm-ui/frontend/src/views/redis/structure-instance/pages/page1/components/SpecSelect.vue +++ /dev/null @@ -1,425 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts index 5fa49aa596..69c775143f 100644 --- a/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts +++ b/dbm-ui/frontend/src/views/redis/toolbox/common/menus.ts @@ -21,87 +21,87 @@ export interface MenuChild { export default [ { name: t('集群维护'), - id: 'redis', + id: 'manage', icon: 'db-icon-cluster', children: [ { name: t('集群容量变更'), id: 'RedisCapacityChange', - parentId: 'redis', + parentId: 'manage', }, { name: t('扩容接入层'), id: 'RedisProxyScaleUp', - parentId: 'redis', + parentId: 'manage', }, { name: t('缩容接入层'), id: 'RedisProxyScaleDown', - parentId: 'redis', + parentId: 'manage', }, { name: t('集群分片变更'), id: 'RedisClusterShardUpdate', - parentId: 'redis', + parentId: 'manage', }, { name: t('集群类型变更'), id: 'RedisClusterTypeUpdate', - parentId: 'redis', + parentId: 'manage', }, { name: t('新建从库'), id: 'RedisDBCreateSlave', - parentId: 'redis', + parentId: 'manage', }, { name: t('主故障切换'), id: 'RedisMasterFailover', - parentId: 'redis', + parentId: 'manage', }, { name: t('整机替换'), id: 'RedisDBReplace', - parentId: 'redis', + parentId: 'manage', }, ], }, { name: t('数据构造'), - id: 'redis', + id: 'struct', icon: 'db-icon-copy', children: [ { name: t('定点构造'), id: 'RedisDBStructure', - parentId: 'redis', + parentId: 'struct', }, { name: t('构造实例'), id: 'RedisStructureInstance', - parentId: 'redis', + parentId: 'struct', }, { name: t('以构造实例恢复'), id: 'RedisRecoverFromInstance', - parentId: 'redis', + parentId: 'struct', }, ], }, { name: t('数据传输(DTS)'), - id: 'redis', + id: 'dts', icon: 'db-icon-data', children: [ { name: t('数据复制'), id: 'RedisDBDataCopy', - parentId: 'redis', + parentId: 'dts', }, { name: t('数据复制记录'), id: 'RedisDBDataCopyRecord', - parentId: 'redis', + parentId: 'dts', }, ], }, diff --git a/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue b/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue index 16a52e44d1..fd3ea03685 100644 --- a/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue +++ b/dbm-ui/frontend/src/views/redis/toolbox/components/TaskCount.vue @@ -54,7 +54,7 @@ diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/RenderTargetBusiness.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/RenderTargetBusiness.vue index 777924f64b..a59dad47d3 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/RenderTargetBusiness.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/RenderTargetBusiness.vue @@ -47,9 +47,7 @@ const emits = defineEmits<{ 'change': [value: number] }>(); - const globalBizsStore = useGlobalBizs(); - - const { bizs } = globalBizsStore; + const { bizs } = useGlobalBizs(); const { t } = useI18n(); diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/Row.vue index fd1b95eb4e..779c110714 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/Row.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/cross-business/Row.vue @@ -71,14 +71,14 @@ - diff --git a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/intra-business-third/Row.vue b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/intra-business-third/Row.vue index b6b41594ca..28699201ca 100644 --- a/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/intra-business-third/Row.vue +++ b/dbm-ui/frontend/src/views/redis/db-data-copy/pages/page1/components/intra-business-third/Row.vue @@ -67,13 +67,13 @@ diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/Index.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/Index.vue new file mode 100644 index 0000000000..f9b4aa6b87 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/Index.vue @@ -0,0 +1,312 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/DetailsClusterOperation.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsClusterOperation.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/DetailsClusterOperation.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsClusterOperation.vue index 221ab349e4..21913322d1 100644 --- a/dbm-ui/frontend/src/views/tickets/components/DetailsClusterOperation.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsClusterOperation.vue @@ -86,5 +86,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsES.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsES.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsES.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsES.vue index b771e99d79..24c67c02d5 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsES.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsES.vue @@ -190,7 +190,6 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsHDFS.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsHDFS.vue similarity index 95% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsHDFS.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsHDFS.vue index 249fd7424c..32364eebc0 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsHDFS.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsHDFS.vue @@ -100,7 +100,7 @@
- Zookeeper/JournalNode: + Zookeepers/JournalNodes:
- DataNode: + DataNodes: diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsInfluxDB.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsInfluxDB.vue index f1e0cd5852..201529d984 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsInfluxDB.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsInfluxDB.vue @@ -97,7 +97,7 @@ import { redisIpSources } from '@views/redis/apply/common/const'; - import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + import SpecInfos, { type SpecInfo } from '../../SpecInfos.vue'; interface TicketDetails { id: number, @@ -165,5 +165,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsKafka.vue similarity index 96% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsKafka.vue index 4c6b7d6c23..d1066411de 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsKafka.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsKafka.vue @@ -129,8 +129,9 @@ import { redisIpSources } from '@views/redis/apply/common/const'; - import { nodeTypeText } from '../../common/utils'; - import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + import { firstLetterToUpper } from '@utils'; + + import SpecInfos, { type SpecInfo } from '../../SpecInfos.vue'; interface Details extends TicketDetailsKafka { ip_source: string, @@ -176,10 +177,10 @@ function handleShowPreview(role: 'broker' | 'zookeeper') { previewState.isShow = true; previewState.role = role; - previewState.title = `【${nodeTypeText[role]}】${t('主机预览')}`; + previewState.title = `【${firstLetterToUpper(role)}】${t('主机预览')}`; } diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsPulsar.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsPulsar.vue index 2387fbce06..23cea42884 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/DetailsPulsar.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/DetailsPulsar.vue @@ -176,7 +176,7 @@ import { redisIpSources } from '@views/redis/apply/common/const'; - import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + import SpecInfos, { type SpecInfo } from '../../SpecInfos.vue'; type ServiceKeys = 'bookkeeper' | 'zookeeper' | 'broker'; @@ -258,5 +258,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataExpansionCapacity.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/ExpansionCapacity.vue similarity index 89% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataExpansionCapacity.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/ExpansionCapacity.vue index b572e7eb5c..e6180e3d03 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataExpansionCapacity.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/ExpansionCapacity.vue @@ -28,8 +28,6 @@ import type { IHostTableData } from '@components/cluster-common/big-data-host-table/HdfsHostTable.vue'; - import { nodeTypeText } from '../../common/utils'; - const props = defineProps({ ticketDetails: { required: true, @@ -48,6 +46,23 @@ cluster_type_name: string, } + /** + * 节点ip类型对应文案 + */ + const nodeTypeText: Record = { + hot: t('热节点'), + cold: t('冷节点'), + master: 'Master', + client: 'Client', + datanode: 'DataNode', + namenode: 'NameNode', + zookeeper: 'Zookeeper', + broker: 'Broker', + proxy: 'Proxy', + slave: 'Slave', + bookkeeper: 'Bookkeeper', + }; + /** * 大数据扩缩容单据 */ @@ -114,5 +129,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReboot.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Reboot.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReboot.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Reboot.vue index 4db5815b4f..7d0819e20c 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReboot.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Reboot.vue @@ -89,5 +89,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReplace.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Replace.vue similarity index 87% rename from dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReplace.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Replace.vue index b7e32bd2da..cf7a337a01 100644 --- a/dbm-ui/frontend/src/views/tickets/components/bigdata/BigDataReplace.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/bigdata/Replace.vue @@ -22,11 +22,11 @@ import { computed, type PropType } from 'vue'; import { useI18n } from 'vue-i18n'; - import type { BigDataReplaceDetails, TicketDetails } from '@services/types/ticket'; + import type { BigDataReplaceDetails, NodesType, TicketDetails } from '@services/types/ticket'; import { useCopy } from '@hooks'; - import { convertNodeFormat } from '../../common/utils'; + import type { IHostTableData } from '@components/cluster-common/big-data-host-table/HdfsHostTable.vue'; const props = defineProps({ ticketDetails: { @@ -122,10 +122,24 @@ }, clusters)); return list; }); + + // 获取节点IP列表 + function convertNodeFormat(obj: NodesType) { + const nodeList: any = []; + Object.entries(obj).forEach((item) => { + const key = item[0]; + const value = item[1]; + if (value.length) { + const data = value.map((key: IHostTableData) => key.ip); + nodeList.push({ key, value: data }); + } + }); + return nodeList; + } diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLClusterOperation.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ClusterOperation.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLClusterOperation.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ClusterOperation.vue index 1aa584e252..3ad078b042 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLClusterOperation.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ClusterOperation.vue @@ -89,5 +89,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/DetailsMySQL.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Details.vue similarity index 94% rename from dbm-ui/frontend/src/views/tickets/components/mysql/DetailsMySQL.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Details.vue index ae8048ea1e..2e73160740 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/DetailsMySQL.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Details.vue @@ -143,7 +143,7 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFlashback.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Flashback.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFlashback.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Flashback.vue index b8a346ac3e..e698950f6f 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFlashback.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Flashback.vue @@ -101,5 +101,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFullBackup.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/FullBackup.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFullBackup.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/FullBackup.vue index cd8cccb1d4..2df003077b 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLFullBackup.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/FullBackup.vue @@ -124,8 +124,8 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLImportSQLFile.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ImportSQLFile.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLImportSQLFile.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ImportSQLFile.vue index 20bc476ef7..a878403c91 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLImportSQLFile.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ImportSQLFile.vue @@ -121,6 +121,7 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMasterSlaveSwitch.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MasterSlaveSwitch.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMasterSlaveSwitch.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MasterSlaveSwitch.vue index 48a5c0c903..65e40b74e7 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMasterSlaveSwitch.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MasterSlaveSwitch.vue @@ -99,5 +99,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMigrateCluster.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MigrateCluster.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMigrateCluster.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MigrateCluster.vue index f68702972e..2d73a7072a 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLMigrateCluster.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/MigrateCluster.vue @@ -99,5 +99,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLOperation.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Operation.vue similarity index 99% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLOperation.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Operation.vue index a0c840168b..3b0f28c8b9 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLOperation.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Operation.vue @@ -207,7 +207,7 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLProxySwitch.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ProxySwitch.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLProxySwitch.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ProxySwitch.vue index ed4a873cca..5fe5cbf900 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLProxySwitch.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/ProxySwitch.vue @@ -99,5 +99,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRename.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Rename.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRename.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Rename.vue index 6e6be5fce4..8ad9cdb747 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRename.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Rename.vue @@ -82,5 +82,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRestoreSlave.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RestoreSlave.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRestoreSlave.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RestoreSlave.vue index 39d92d5be6..af6773b3df 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRestoreSlave.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RestoreSlave.vue @@ -102,5 +102,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRollbackCluster.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RollbackCluster.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRollbackCluster.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RollbackCluster.vue index 5b057a54ec..08a6082d3f 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLRollbackCluster.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/RollbackCluster.vue @@ -108,5 +108,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLSlave.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Slave.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLSlave.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Slave.vue index 5e84f03b5d..8a30e35b41 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLSlave.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/Slave.vue @@ -148,5 +148,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLTableBackup.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TableBackup.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/MySQLTableBackup.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TableBackup.vue index 05d7a3cc08..361c1c5e56 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/MySQLTableBackup.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TableBackup.vue @@ -142,5 +142,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/components/mysql/TargetClusterPreview.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TargetClusterPreview.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/mysql/TargetClusterPreview.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TargetClusterPreview.vue index 9c624f7a1b..cf8c875f6d 100644 --- a/dbm-ui/frontend/src/views/tickets/components/mysql/TargetClusterPreview.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/mysql/TargetClusterPreview.vue @@ -60,7 +60,7 @@ import DbStatus from '@components/db-status/index.vue'; - import { targetClusterData } from '../../hooks/targetClusterData'; + import { targetClusterData } from '@views/tickets/common/hooks/targetClusterData'; const props = defineProps({ isShow: { diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/AddSlave.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/AddSlave.vue new file mode 100644 index 0000000000..36c93774ac --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/AddSlave.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterCapacityUpdate.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterCapacityUpdate.vue new file mode 100644 index 0000000000..60ae80b40d --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterCapacityUpdate.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterShardUpdate.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterShardUpdate.vue new file mode 100644 index 0000000000..eb6e501217 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterShardUpdate.vue @@ -0,0 +1,38 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterTypeUpdate.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterTypeUpdate.vue new file mode 100644 index 0000000000..59fb393ade --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/ClusterTypeUpdate.vue @@ -0,0 +1,38 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DBReplace.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DBReplace.vue new file mode 100644 index 0000000000..6fd6e36f85 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DBReplace.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCheckAndRepair.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCheckAndRepair.vue new file mode 100644 index 0000000000..6cbb137974 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCheckAndRepair.vue @@ -0,0 +1,126 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCopy.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCopy.vue new file mode 100644 index 0000000000..ede9693059 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataCopy.vue @@ -0,0 +1,264 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataStructure.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataStructure.vue new file mode 100644 index 0000000000..3db66d02d3 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/DataStructure.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Details.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Details.vue index 586c78cc21..5f0c8bf0c1 100644 --- a/dbm-ui/frontend/src/views/tickets/components/redis/DetailsRedis.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Details.vue @@ -158,8 +158,9 @@ redisIpSources, } from '@views/redis/apply/common/const'; - import { nodeTypeText } from '../../common/utils'; - import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + import { firstLetterToUpper } from '@utils'; + + import SpecInfos, { type SpecInfo } from '../../SpecInfos.vue'; interface Details extends TicketDetailsRedis { ip_source: string, @@ -181,6 +182,17 @@ const { t } = useI18n(); + const previewState = reactive({ + isShow: false, + role: '', + title: t('主机预览'), + }); + const fetchNodesParams = computed(() => ({ + bk_biz_id: props.ticketDetails.bk_biz_id, + id: props.ticketDetails.id, + role: previewState.role, + })); + const proxySpec = computed(() => props.ticketDetails?.details?.resource_spec?.proxy || {}); const backendData = computed(() => { const data = props.ticketDetails?.details?.resource_spec?.backend_group?.spec_info; @@ -250,24 +262,13 @@ /** * 服务器详情预览功能 */ - const previewState = reactive({ - isShow: false, - role: '', - title: t('主机预览'), - }); - const fetchNodesParams = computed(() => ({ - bk_biz_id: props.ticketDetails.bk_biz_id, - id: props.ticketDetails.id, - role: previewState.role, - })); - function handleShowPreview(role: 'proxy' | 'master' | 'slave') { previewState.isShow = true; previewState.role = role; - previewState.title = `【${nodeTypeText[role]}】${t('主机预览')}`; + previewState.title = `【${firstLetterToUpper(role)}】${t('主机预览')}`; } diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/MasterFailover.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/MasterFailover.vue new file mode 100644 index 0000000000..2292efeafc --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/MasterFailover.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/redis/RedisOperation.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Operation.vue similarity index 62% rename from dbm-ui/frontend/src/views/tickets/components/redis/RedisOperation.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Operation.vue index 89b4b1d08b..5f06917e74 100644 --- a/dbm-ui/frontend/src/views/tickets/components/redis/RedisOperation.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/Operation.vue @@ -18,25 +18,25 @@ diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/StructureDelete.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/StructureDelete.vue new file mode 100644 index 0000000000..762e78513f --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/redis/StructureDelete.vue @@ -0,0 +1,45 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/AddNodes.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/AddNodes.vue new file mode 100644 index 0000000000..a927fccfcf --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/AddNodes.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/CheckSum.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/CheckSum.vue new file mode 100644 index 0000000000..0c205ff984 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/CheckSum.vue @@ -0,0 +1,152 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Destroy.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Destroy.vue new file mode 100644 index 0000000000..191b877cf6 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Destroy.vue @@ -0,0 +1,84 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/spider/DetailsSpider.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Details.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/spider/DetailsSpider.vue rename to dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Details.vue index 964bbd1010..638d140854 100644 --- a/dbm-ui/frontend/src/views/tickets/components/spider/DetailsSpider.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Details.vue @@ -96,7 +96,7 @@ } from '@services/resourceSpec'; import type { TicketDetails } from '@services/types/ticket'; - import SpecInfos, { type SpecInfo } from '../SpecInfos.vue'; + import SpecInfos, { type SpecInfo } from '../../SpecInfos.vue'; interface Details { bk_cloud_id: number, @@ -168,5 +168,5 @@ diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Disable.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Disable.vue new file mode 100644 index 0000000000..7fed792729 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Disable.vue @@ -0,0 +1,74 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Enable.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Enable.vue new file mode 100644 index 0000000000..b06da2b260 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Enable.vue @@ -0,0 +1,84 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Flashback.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Flashback.vue new file mode 100644 index 0000000000..287288a89a --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Flashback.vue @@ -0,0 +1,110 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/FullBackup.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/FullBackup.vue new file mode 100644 index 0000000000..c2200db6e9 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/FullBackup.vue @@ -0,0 +1,94 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTApply.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTApply.vue new file mode 100644 index 0000000000..532ae8f719 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTApply.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTDestroy.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTDestroy.vue new file mode 100644 index 0000000000..a01f157692 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MNTDestroy.vue @@ -0,0 +1,81 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MasterSlaveSwitch.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MasterSlaveSwitch.vue new file mode 100644 index 0000000000..6f28c97fcd --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/MasterSlaveSwitch.vue @@ -0,0 +1,82 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/NodeRebalance.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/NodeRebalance.vue new file mode 100644 index 0000000000..7efdf19f21 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/NodeRebalance.vue @@ -0,0 +1,137 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/ReduceNodes.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/ReduceNodes.vue new file mode 100644 index 0000000000..f244b76321 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/ReduceNodes.vue @@ -0,0 +1,117 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/RenameDatabase.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/RenameDatabase.vue new file mode 100644 index 0000000000..c1f3971144 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/RenameDatabase.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Rollback.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Rollback.vue new file mode 100644 index 0000000000..8ed769627d --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/Rollback.vue @@ -0,0 +1,110 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveApply.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveApply.vue new file mode 100644 index 0000000000..310dbadfd4 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveApply.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveDestroy.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveDestroy.vue new file mode 100644 index 0000000000..e212a02c7b --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/SlaveDestroy.vue @@ -0,0 +1,84 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TableBackup.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TableBackup.vue new file mode 100644 index 0000000000..5784a3249d --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TableBackup.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TruncateDatabase.vue b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TruncateDatabase.vue new file mode 100644 index 0000000000..89a4da9caa --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/common/components/demand-factory/spider/TruncateDatabase.vue @@ -0,0 +1,110 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/components/FlowContent.vue b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/Index.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/components/FlowContent.vue rename to dbm-ui/frontend/src/views/tickets/common/components/flow-content/Index.vue index 11641447c9..914adb876a 100644 --- a/dbm-ui/frontend/src/views/tickets/components/FlowContent.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/Index.vue @@ -119,8 +119,8 @@ import CostTimer from '@components/cost-timer/CostTimer.vue'; - import FlowContentInnerFlow from './FlowContentInnerFlow.vue'; - import FlowContentTodo from './FlowContentTodo.vue'; + import FlowContentInnerFlow from './components/ContentInnerFlow.vue'; + import FlowContentTodo from './components/ContentTodo.vue'; interface Emits { (e: 'fetch-data'): void diff --git a/dbm-ui/frontend/src/views/tickets/components/FlowContentInnerFlow.vue b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/ContentInnerFlow.vue similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/FlowContentInnerFlow.vue rename to dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/ContentInnerFlow.vue index 07833beb65..db726cd0a4 100644 --- a/dbm-ui/frontend/src/views/tickets/components/FlowContentInnerFlow.vue +++ b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/ContentInnerFlow.vue @@ -97,7 +97,7 @@ import CostTimer from '@components/cost-timer/CostTimer.vue'; - import FlowContentTodo from './FlowContentTodo.vue'; + import FlowContentTodo from './ContentTodo.vue'; interface Emits { (e: 'fetch-data'): void diff --git a/dbm-ui/frontend/src/views/tickets/components/FlowContentTodo.vue b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/ContentTodo.vue similarity index 100% rename from dbm-ui/frontend/src/views/tickets/components/FlowContentTodo.vue rename to dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/ContentTodo.vue diff --git a/dbm-ui/frontend/src/views/tickets/components/FlowIcon.vue b/dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/FlowIcon.vue similarity index 100% rename from dbm-ui/frontend/src/views/tickets/components/FlowIcon.vue rename to dbm-ui/frontend/src/views/tickets/common/components/flow-content/components/FlowIcon.vue diff --git a/dbm-ui/frontend/src/views/tickets/hooks/logCounts.ts b/dbm-ui/frontend/src/views/tickets/common/hooks/logCounts.ts similarity index 100% rename from dbm-ui/frontend/src/views/tickets/hooks/logCounts.ts rename to dbm-ui/frontend/src/views/tickets/common/hooks/logCounts.ts diff --git a/dbm-ui/frontend/src/views/tickets/hooks/targetClusterData.ts b/dbm-ui/frontend/src/views/tickets/common/hooks/targetClusterData.ts similarity index 100% rename from dbm-ui/frontend/src/views/tickets/hooks/targetClusterData.ts rename to dbm-ui/frontend/src/views/tickets/common/hooks/targetClusterData.ts diff --git a/dbm-ui/frontend/src/views/tickets/components/DetailsTable.less b/dbm-ui/frontend/src/views/tickets/common/styles/DetailsTable.less similarity index 100% rename from dbm-ui/frontend/src/views/tickets/components/DetailsTable.less rename to dbm-ui/frontend/src/views/tickets/common/styles/DetailsTable.less diff --git a/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less b/dbm-ui/frontend/src/views/tickets/common/styles/ticketDetails.less similarity index 98% rename from dbm-ui/frontend/src/views/tickets/components/ticketDetails.less rename to dbm-ui/frontend/src/views/tickets/common/styles/ticketDetails.less index 16698db100..a7ef467233 100644 --- a/dbm-ui/frontend/src/views/tickets/components/ticketDetails.less +++ b/dbm-ui/frontend/src/views/tickets/common/styles/ticketDetails.less @@ -11,7 +11,7 @@ * the specific language governing permissions and limitations under the License. */ -@import "@/styles/mixins.less"; +@import "@styles/mixins.less"; .ticket-details { &__info { diff --git a/dbm-ui/frontend/src/views/tickets/common/utils.ts b/dbm-ui/frontend/src/views/tickets/common/utils.ts deleted file mode 100644 index 131790d6ee..0000000000 --- a/dbm-ui/frontend/src/views/tickets/common/utils.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. - * - * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at https://opensource.org/licenses/MIT - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for - * the specific language governing permissions and limitations under the License. -*/ - -import { format } from 'date-fns'; - -import type { NodesType } from '@services/types/ticket'; - -import type { IHostTableData } from '@components/cluster-common/big-data-host-table/HdfsHostTable.vue'; - -import { t } from '@locales/index'; - -/** - * 单据状态类型 - */ -export enum StatusTypes { - ALL = '全部', - PENDING = '审批中', - RUNNING = '进行中', - SUCCEEDED = '已完成', - FAILED = '已终止', - REVOKED = '已撤销', -} -export type StatusTypesStrings = keyof typeof StatusTypes; - -/** - * 状态 theme 映射 - */ -export const tagTheme = { - PENDING: 'warning', - RUNNING: 'info', - SUCCEEDED: 'success', - FAILED: 'danger', - REVOKED: 'danger', - ALL: undefined, -}; - -/** - * 获取状态对应文案 - * @param key 状态 key - * @returns 状态文案 - */ -export const getTagTheme = (key: StatusTypesStrings) => tagTheme[key] as BKTagTheme; - -/** - * 节点ip类型对应文案 - */ -export const nodeTypeText: { - [key: string]: string -} = { - hot: t('热节点'), - cold: t('冷节点'), - master: 'Master', - client: 'Client', - datanode: 'DataNode', - namenode: 'NameNode', - zookeeper: 'Zookeeper', - broker: 'Broker', - proxy: 'Proxy', - slave: 'Slave', - bookkeeper: 'Bookkeeper', -}; - -/** - * 获取节点IP列表 - * @param obj 节点对象 - * @returns 节点数组 - */ -export function convertNodeFormat(obj: NodesType) { - const nodeList: any = []; - Object.entries(obj).forEach((item) => { - const key = item[0]; - const value = item[1]; - if (value.length) { - const data = value.map((key: IHostTableData) => key.ip); - nodeList.push({ key, value: data }); - } - }); - return nodeList; -} - -/** 需要轮训的单据类型 */ -export const needPollStatus = ['PENDING', 'RUNNING']; - -/** flows colors */ -export const flowsColors = { - PENDING: 'warning', - RUNNING: 'blue', - SUCCEEDED: 'green', - FAILED: 'red', -}; - -/** 格式化时间 */ -export const getDate = (value: string) => format(new Date(value), 'yyyy-MM-dd'); diff --git a/dbm-ui/frontend/src/views/tickets/components/TicketDetails.vue b/dbm-ui/frontend/src/views/tickets/components/TicketDetails.vue deleted file mode 100644 index 066d32d0b4..0000000000 --- a/dbm-ui/frontend/src/views/tickets/components/TicketDetails.vue +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/MyTickets.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/Index.vue similarity index 70% rename from dbm-ui/frontend/src/views/tickets/my-tickets/MyTickets.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/Index.vue index a1d86d4604..5baff0b809 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/MyTickets.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/Index.vue @@ -13,36 +13,31 @@ diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/Index.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/Index.vue new file mode 100644 index 0000000000..18e395c70b --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/Index.vue @@ -0,0 +1,246 @@ + + + + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/Demand.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/Demand.vue new file mode 100644 index 0000000000..6dff46e672 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/Demand.vue @@ -0,0 +1,33 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/TicketFlows.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/Index.vue similarity index 88% rename from dbm-ui/frontend/src/views/tickets/my-tickets/components/TicketFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/Index.vue index 0108846bcf..ba3d6242ab 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/components/TicketFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/Index.vue @@ -13,16 +13,11 @@ @@ -34,11 +29,9 @@ import { useTimeoutPoll } from '@vueuse/core'; - import { needPollStatus } from '../../common/utils'; - - import CommonFlows from './flows/Common.vue'; - import MySqlFlows from './flows/MySqlFlows.vue'; - import RedisFlows from './flows/RedisFlows.vue'; + import CommonFlows from './components/Common.vue'; + import MySqlFlows from './components/MySqlFlows.vue'; + import RedisFlows from './components/RedisFlows.vue'; const props = defineProps({ data: { @@ -64,6 +57,8 @@ return CommonFlows; }); + const needPollStatus = ['PENDING', 'RUNNING']; + // 轮询 const { isActive, resume, pause } = useTimeoutPoll(() => { fetchTicketFlows(props.data.id, true); diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/Common.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/Common.vue similarity index 89% rename from dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/Common.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/Common.vue index c9e4fe5f27..1fe75b0a99 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/Common.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/Common.vue @@ -26,8 +26,8 @@ import type { FlowItem } from '@services/types/ticket'; - import FlowContent from '../../../components/FlowContent.vue'; - import FlowIcon from '../../../components/FlowIcon.vue'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import FlowContent from '@views/tickets/common/components/flow-content/Index.vue'; interface Emits { (e: 'fetch-data'): void diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/MySqlFlows.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/MySqlFlows.vue similarity index 91% rename from dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/MySqlFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/MySqlFlows.vue index 90f4589977..5b2a4bd322 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/MySqlFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/MySqlFlows.vue @@ -57,12 +57,12 @@ import type { FlowItem } from '@services/types/ticket'; - import { getCostTimeDisplay } from '@utils'; + import SqlFileComponent from '@views/tickets/common/components/demand-factory/mysql/LogDetails.vue'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import FlowContent from '@views/tickets/common/components/flow-content/Index.vue'; + import useLogCounts from '@views/tickets/common/hooks/logCounts'; - import FlowContent from '../../../components/FlowContent.vue'; - import FlowIcon from '../../../components/FlowIcon.vue'; - import SqlFileComponent from '../../../components/mysql/SqlLogDetails.vue'; - import useLogCounts from '../../../hooks/logCounts'; + import { getCostTimeDisplay } from '@utils'; interface Emits { (e: 'fetch-data'): void diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/RedisFlows.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/RedisFlows.vue similarity index 93% rename from dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/RedisFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/RedisFlows.vue index fde8cd026d..fc55f1d2f4 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/components/flows/RedisFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/details/components/flow/components/RedisFlows.vue @@ -42,9 +42,8 @@ import type { FlowItem } from '@services/types/ticket'; import RedisResultFiles from '@views/mission/components/RedisResultFiles.vue'; - - import FlowContent from '../../../components/FlowContent.vue'; - import FlowIcon from '../../../components/FlowIcon.vue'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import FlowContent from '@views/tickets/common/components/flow-content/Index.vue'; interface Emits { (e: 'fetch-data'): void diff --git a/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue b/dbm-ui/frontend/src/views/tickets/my-tickets/components/list/Index.vue similarity index 91% rename from dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue rename to dbm-ui/frontend/src/views/tickets/my-tickets/components/list/Index.vue index fe18bc41df..3d7ed4a75b 100644 --- a/dbm-ui/frontend/src/views/tickets/my-tickets/TicketList.vue +++ b/dbm-ui/frontend/src/views/tickets/my-tickets/components/list/Index.vue @@ -74,8 +74,8 @@ - {{ $t(StatusTypes[item.status as StatusTypesStrings]) }} + :theme="item.getTagTheme()"> + {{ $t(item.getStatusText()) }}
{{ $t('申请人') }}: {{ item.creator }} - {{ getDate(item.create_at) }} + {{ item.getFormatCreateAt() }}
@@ -114,11 +114,39 @@
+ + diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/TicketList.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/List.vue similarity index 95% rename from dbm-ui/frontend/src/views/tickets/my-todos/TicketList.vue rename to dbm-ui/frontend/src/views/tickets/my-todos/components/List.vue index 0bcb1c37b9..9150fcc59f 100644 --- a/dbm-ui/frontend/src/views/tickets/my-todos/TicketList.vue +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/List.vue @@ -73,8 +73,8 @@ - {{ $t(StatusTypes[item.status as StatusTypesStrings]) }} + :theme="item.getTagTheme()"> + {{ $t(item.getStatusText()) }}
{{ $t('申请人') }}: {{ item.creator }} - {{ getDate(item.create_at) }} + {{ item.getFormatCreateAt() }}
@@ -120,8 +120,8 @@ + + + + diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/Demand.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/Demand.vue new file mode 100644 index 0000000000..6dff46e672 --- /dev/null +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/Demand.vue @@ -0,0 +1,33 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/components/TicketFlows.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/Index.vue similarity index 89% rename from dbm-ui/frontend/src/views/tickets/my-todos/components/TicketFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/Index.vue index 22b9ad7362..6b892a07a5 100644 --- a/dbm-ui/frontend/src/views/tickets/my-todos/components/TicketFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/Index.vue @@ -13,16 +13,11 @@ @@ -34,11 +29,9 @@ import { useTimeoutPoll } from '@vueuse/core'; - import { needPollStatus } from '../../common/utils'; - - import ApproveFlows from './flows/Approve.vue'; - import MySqlFlows from './flows/MySqlFlows.vue'; - import RedisFlows from './flows/RedisFlows.vue'; + import ApproveFlows from './components/Approve.vue'; + import MySqlFlows from './components/MySqlFlows.vue'; + import RedisFlows from './components/RedisFlows.vue'; const props = defineProps({ data: { @@ -64,6 +57,8 @@ return ApproveFlows; }); + const needPollStatus = ['PENDING', 'RUNNING']; + // 轮询 const { isActive, resume, pause } = useTimeoutPoll(() => { fetchTicketFlows(props.data.id, true); diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/Approve.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/Approve.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/my-todos/components/flows/Approve.vue rename to dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/Approve.vue index 92f35f832c..d03e0cad78 100644 --- a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/Approve.vue +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/Approve.vue @@ -136,10 +136,10 @@ import { useMenu, useUserProfile } from '@stores'; - import { getCostTimeDisplay } from '@utils'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import FlowContent from '@views/tickets/common/components/flow-content/Index.vue'; - import FlowContent from '../../../components/FlowContent.vue'; - import FlowIcon from '../../../components/FlowIcon.vue'; + import { getCostTimeDisplay } from '@utils'; interface Emits { (e: 'processed'): void diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/MySqlFlows.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/MySqlFlows.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/my-todos/components/flows/MySqlFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/MySqlFlows.vue index 0cad451f80..08df371c59 100644 --- a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/MySqlFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/MySqlFlows.vue @@ -181,11 +181,11 @@ import CostTimer from '@components/cost-timer/CostTimer.vue'; - import { getCostTimeDisplay } from '@utils'; + import SqlFileComponent from '@views/tickets/common/components/demand-factory/mysql/LogDetails.vue'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import useLogCounts from '@views/tickets/common/hooks/logCounts'; - import FlowIcon from '../../../components/FlowIcon.vue'; - import SqlFileComponent from '../../../components/mysql/SqlLogDetails.vue'; - import useLogCounts from '../../../hooks/logCounts'; + import { getCostTimeDisplay } from '@utils'; interface Emits { (e: 'processed'): void diff --git a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/RedisFlows.vue b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/RedisFlows.vue similarity index 97% rename from dbm-ui/frontend/src/views/tickets/my-todos/components/flows/RedisFlows.vue rename to dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/RedisFlows.vue index 213e01991a..6c5adb2780 100644 --- a/dbm-ui/frontend/src/views/tickets/my-todos/components/flows/RedisFlows.vue +++ b/dbm-ui/frontend/src/views/tickets/my-todos/components/details/components/flow/components/RedisFlows.vue @@ -152,12 +152,11 @@ import { useMenu, useUserProfile } from '@stores'; import RedisResultFiles from '@views/mission/components/RedisResultFiles.vue'; + import FlowIcon from '@views/tickets/common/components/flow-content/components/FlowIcon.vue'; + import FlowContent from '@views/tickets/common/components/flow-content/Index.vue'; import { getCostTimeDisplay } from '@utils'; - import FlowContent from '../../../components/FlowContent.vue'; - import FlowIcon from '../../../components/FlowIcon.vue'; - interface Emits { (e: 'processed'): void } diff --git a/dbm-ui/frontend/src/views/tickets/routes.ts b/dbm-ui/frontend/src/views/tickets/routes.ts index 3c13594c66..4c7d20f4e4 100644 --- a/dbm-ui/frontend/src/views/tickets/routes.ts +++ b/dbm-ui/frontend/src/views/tickets/routes.ts @@ -26,7 +26,7 @@ const routes: RouteRecordRaw[] = [ navName: t('我的服务单'), isMenu: true, }, - component: () => import('@views/tickets/my-tickets/MyTickets.vue'), + component: () => import('@views/tickets/my-tickets/Index.vue'), }, { name: 'MyTodos', @@ -36,7 +36,7 @@ const routes: RouteRecordRaw[] = [ navName: t('我的待办'), isMenu: true, }, - component: () => import('@views/tickets/my-todos/MyTodos.vue'), + component: () => import('@views/tickets/my-todos/Index.vue'), }, ]; From 43b0fcadbfd36e08d8d981b51d78b3772db295af Mon Sep 17 00:00:00 2001 From: hlinx <327159425@qq.com> Date: Mon, 14 Aug 2023 17:38:23 +0800 Subject: [PATCH 321/476] =?UTF-8?q?feat(frontend):=20spider=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=AE=B1=20#599?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 2 +- .../components/SelectOriginalHost.vue | 5 + dbm-ui/frontend/src/locales/zh-cn.json | 14 +- ...remote-pair.ts => remote-pair-instance.ts} | 4 +- dbm-ui/frontend/src/services/mysqlCluster.ts | 21 +- .../frontend/src/services/partitionManage.ts | 14 +- dbm-ui/frontend/src/services/sqlImport.ts | 81 +++++--- .../src/views/mission/pages/Details.vue | 7 +- .../views/mysql/common/edit-field/DbName.vue | 18 +- .../mysql/common/edit-field/TableName.vue | 18 +- .../src/views/mysql/common/edit/Input.vue | 2 + .../views/mysql/common/hooks/useTaskCount.ts | 3 +- .../views/mysql/common/render-table/Index.vue | 5 +- .../mysql/sql-execute/steps/step1/Index.vue | 2 +- .../steps/step1/components/TaskTips.vue | 2 +- .../mysql/toolbox/components/TaskCount.vue | 2 +- .../redis/toolbox/components/TaskCount.vue | 2 +- .../checksum/pages/page1/Index.vue | 7 +- .../components/RenderData/RenderMaster.vue | 61 ++++-- .../components/RenderData/RenderScope.vue | 27 ++- .../components/RenderData/RenderSlave.vue | 139 ++++++++----- .../components/RenderData/RenderTableName.vue | 140 ------------- .../pages/page1/components/RenderData/Row.vue | 186 +++++++++++------- .../common/spider-instance-selector/Index.vue | 6 +- .../components/RenderManualInput.vue | 11 +- .../components/RenderTopo.vue | 21 +- .../components/RenderTopoHost.vue | 25 ++- .../spider-manage/partition-manage/Index.vue | 34 ++-- .../partition-manage/components/DryRun.vue | 157 +++++++++++++++ .../components/ExecuteLog.vue | 82 ++++---- .../partition-manage/components/Operation.vue | 20 +- .../rollback/pages/page1/Index.vue | 29 +-- .../components/RenderData/RenderMode.vue | 91 ++------- .../pages/page1/components/RenderData/Row.vue | 30 +-- .../src/views/spider-manage/routes.ts | 20 +- .../sql-execute/steps/step1/Index.vue | 1 + .../steps/step1/components/TaskTips.vue | 2 +- .../toolbox/components/TaskCount.vue | 2 +- 38 files changed, 732 insertions(+), 561 deletions(-) rename dbm-ui/frontend/src/services/model/mysql-cluster/{remote-pair.ts => remote-pair-instance.ts} (87%) delete mode 100644 dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/RenderTableName.vue create mode 100644 dbm-ui/frontend/src/views/spider-manage/partition-manage/components/DryRun.vue diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index 97c5e0eeb5..a080b9d638 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -18,7 +18,7 @@ "@blueking/ip-selector": "0.0.1-beta.116", "@vueuse/core": "10.2.1", "axios": "1.2.1", - "bkui-vue": "0.0.1-beta.474", + "bkui-vue": "0.0.2-beta.6", "date-fns": "2.28.0", "dayjs": "1.11.9", "html-to-image": "1.11.3", diff --git a/dbm-ui/frontend/src/components/cluster-common/host-shrink/components/SelectOriginalHost.vue b/dbm-ui/frontend/src/components/cluster-common/host-shrink/components/SelectOriginalHost.vue index ec92299458..225108e77b 100644 --- a/dbm-ui/frontend/src/components/cluster-common/host-shrink/components/SelectOriginalHost.vue +++ b/dbm-ui/frontend/src/components/cluster-common/host-shrink/components/SelectOriginalHost.vue @@ -58,6 +58,11 @@ diff --git a/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/RenderTableName.vue b/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/RenderTableName.vue deleted file mode 100644 index 9e64c22df2..0000000000 --- a/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/RenderTableName.vue +++ /dev/null @@ -1,140 +0,0 @@ - - - - diff --git a/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/Row.vue b/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/Row.vue index 794a9553be..55297c04e6 100644 --- a/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/Row.vue +++ b/dbm-ui/frontend/src/views/spider-manage/checksum/pages/page1/components/RenderData/Row.vue @@ -12,76 +12,79 @@ -->