diff --git a/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/mongo_deinstall.go b/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/mongo_deinstall.go index 62bdeb29bc..a60d0174eb 100644 --- a/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/mongo_deinstall.go +++ b/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/mongo_deinstall.go @@ -25,6 +25,7 @@ type DeInstallConfParams struct { NodeInfo []string `json:"nodeInfo" validate:"required"` // []string ip,ip 如果为复制集节点,则为复制集所有节点的ip;如果为mongos,则为mongos的ip InstanceType string `json:"instanceType" validate:"required"` // mongod mongos Force bool `json:"force"` // 不检查连接,强制卸载 + RenameDir bool `json:"renameDir"` // 关闭进程后是否重命名目录 true 重命名目录,false 不重命名目录 } // DeInstall 添加分片到集群 @@ -199,6 +200,10 @@ func (d *DeInstall) shutdownProcess() error { // DirRename 打包数据目录 func (d *DeInstall) DirRename() error { // renameDb数据目录 + // 关闭进程后不重命名目录 + if d.ConfParams.RenameDir == false { + return nil + } flag := util.FileExists(d.PortDir) if flag == true { d.runtime.Logger.Info("start to rename db directory") diff --git a/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/start_process.go b/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/start_process.go new file mode 100644 index 0000000000..9f88b58d05 --- /dev/null +++ b/dbm-services/mongodb/db-tools/dbactuator/pkg/atomjobs/atommongodb/start_process.go @@ -0,0 +1,137 @@ +package atommongodb + +import ( + "dbm-services/mongodb/db-tools/dbactuator/pkg/common" + "dbm-services/mongodb/db-tools/dbactuator/pkg/consts" + "dbm-services/mongodb/db-tools/dbactuator/pkg/jobruntime" + "encoding/json" + "fmt" + "path/filepath" + "strconv" + + "github.com/go-playground/validator/v10" +) + +// StartProcessConfParams 开启进程参数 +type StartProcessConfParams struct { + IP string `json:"ip" validate:"required"` + Port int `json:"port" validate:"required"` + InstanceType string `json:"instanceType" validate:"required"` // mongos mongod + Auth bool `json:"auth"` // true->auth false->noauth +} + +// MongoStartProcess 开启mongo进程 +type MongoStartProcess struct { + BaseJob + runtime *jobruntime.JobGenericRuntime + BinDir string + DataDir string + DbpathDir string + Mongo string + OsUser string // MongoDB安装在哪个用户下 + OsGroup string + ConfParams *StartProcessConfParams + AuthConfFilePath string + NoAuthConfFilePath string +} + +// NewMongoStartProcess 实例化结构体 +func NewMongoStartProcess() jobruntime.JobRunner { + return &MongoStartProcess{} +} + +// Name 获取原子任务的名字 +func (s *MongoStartProcess) Name() string { + return "mongo_start" +} + +// Run 运行原子任务 +func (s *MongoStartProcess) Run() error { + // 启动服务 + if err := s.startup(); err != nil { + return err + } + + return nil +} + +// Retry 重试 +func (s *MongoStartProcess) Retry() uint { + return 2 +} + +// Rollback 回滚 +func (s *MongoStartProcess) Rollback() error { + return nil +} + +// Init 初始化 +func (s *MongoStartProcess) Init(runtime *jobruntime.JobGenericRuntime) error { + // 获取安装参数 + s.runtime = runtime + s.runtime.Logger.Info("start to init") + s.BinDir = consts.UsrLocal + s.DataDir = consts.GetMongoDataDir() + s.OsUser = consts.GetProcessUser() + s.OsGroup = consts.GetProcessUserGroup() + s.Mongo = filepath.Join(s.BinDir, "mongodb", "bin", "mongo") + + // 获取MongoDB配置文件参数 + if err := json.Unmarshal([]byte(s.runtime.PayloadDecoded), &s.ConfParams); err != nil { + s.runtime.Logger.Error(fmt.Sprintf( + "get parameters of mongo restart fail by json.Unmarshal, error:%s", err)) + return fmt.Errorf("get parameters of mongo restart fail by json.Unmarshal, error:%s", err) + } + + // 设置各种路径 + strPort := strconv.Itoa(s.ConfParams.Port) + s.DbpathDir = filepath.Join(s.DataDir, "mongodata", strPort, "db") + s.AuthConfFilePath = filepath.Join(s.DataDir, "mongodata", strPort, "mongo.conf") + s.NoAuthConfFilePath = filepath.Join(s.DataDir, "mongodata", strPort, "noauth.conf") + s.runtime.Logger.Info("init successfully") + + // 安装前进行校验 + if err := s.checkParams(); err != nil { + return err + } + + return nil +} + +// checkParams 校验参数 +func (s *MongoStartProcess) checkParams() error { + // 校验重启配置参数 + validate := validator.New() + s.runtime.Logger.Info("start to validate parameters of restart") + if err := validate.Struct(s.ConfParams); err != nil { + s.runtime.Logger.Error(fmt.Sprintf("validate parameters of restart fail, error:%s", err)) + return fmt.Errorf("validate parameters of restart fail, error:%s", err) + } + s.runtime.Logger.Info("validate parameters of restart successfully") + return nil +} + +// startup 开启服务 +func (s *MongoStartProcess) startup() error { + // 检查服务是否存在 + s.runtime.Logger.Info("start to check %s service", s.ConfParams.InstanceType) + result, _, err := common.CheckMongoService(s.ConfParams.Port) + if err != nil { + s.runtime.Logger.Error("check %s service fail, error:%s", s.ConfParams.InstanceType, err) + return fmt.Errorf("check %s service fail, error:%s", s.ConfParams.InstanceType, err) + } + if result == true { + s.runtime.Logger.Info("%s service has been open", s.ConfParams.InstanceType) + return nil + } + s.runtime.Logger.Info("check %s service successfully", s.ConfParams.InstanceType) + + // 开启服务 + s.runtime.Logger.Info("start to startup %s", s.ConfParams.InstanceType) + if err = common.StartMongoProcess(s.BinDir, s.ConfParams.Port, s.OsUser, s.ConfParams.Auth); err != nil { + s.runtime.Logger.Error("startup %s fail, error:%s", s.ConfParams.InstanceType, err) + return fmt.Errorf("startup %s fail, error:%s", s.ConfParams.InstanceType, err) + } + s.runtime.Logger.Info("startup %s successfully", s.ConfParams.InstanceType) + return nil +} diff --git a/dbm-services/mongodb/db-tools/dbactuator/pkg/jobmanager/jobmanager.go b/dbm-services/mongodb/db-tools/dbactuator/pkg/jobmanager/jobmanager.go index 28738f3036..4882ad3913 100644 --- a/dbm-services/mongodb/db-tools/dbactuator/pkg/jobmanager/jobmanager.go +++ b/dbm-services/mongodb/db-tools/dbactuator/pkg/jobmanager/jobmanager.go @@ -147,6 +147,7 @@ func (m *JobGenericManager) RegisterAtomJob() { atommongodb.NewPitrRecoverJob, atommongodb.NewRemoveNsJob, atommongodb.NewInstallDbmonJob, + atommongodb.NewMongoStartProcess, } { m.atomJobMapper[f().Name()] = f } diff --git a/dbm-ui/backend/flow/consts.py b/dbm-ui/backend/flow/consts.py index b39d596f58..0ffd8f6713 100644 --- a/dbm-ui/backend/flow/consts.py +++ b/dbm-ui/backend/flow/consts.py @@ -448,6 +448,7 @@ class MongoDBActuatorActionEnum(str, StructuredEnum): MongoDReplace = EnumField("mongod_replace", _("mongod_replace")) MongoDeInstall = EnumField("mongo_deinstall", _("mongo_deinstall")) InstallDBMon = EnumField("install_dbmon", _("install_dbmon")) + MongoStart = EnumField("mongo_start", _("mongo_start")) class EsActuatorActionEnum(str, StructuredEnum): diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/mongodb_enable_disable.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/mongodb_enable_disable.py new file mode 100644 index 0000000000..1699952f36 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/mongodb_enable_disable.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 logging.config +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.flow.engine.bamboo.scene.common.builder import Builder +from backend.flow.engine.bamboo.scene.mongodb.sub_task import cluster_enable_disable +from backend.flow.plugins.components.collections.mongodb.exec_actuator_job import ExecuteDBActuatorJobComponent +from backend.flow.plugins.components.collections.mongodb.send_media import ExecSendMediaOperationComponent +from backend.flow.utils.mongodb.mongodb_dataclass import ActKwargs + +logger = logging.getLogger("flow") + + +class MongoEnableDisableFlow(object): + """MongoDB禁用启用flow""" + + 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 + self.get_kwargs = ActKwargs() + self.get_kwargs.payload = data + self.get_kwargs.get_file_path() + + def prepare_job(self, pipeline: Builder): + """ + 准备工作 + """ + + # 介质下发——job的api可以多个IP并行执行 + kwargs = self.get_kwargs.get_send_media_kwargs(media_type="actuator") + pipeline.add_act( + act_name=_("MongoDB-介质下发"), act_component_code=ExecSendMediaOperationComponent.code, kwargs=kwargs + ) + + # 创建原子任务执行目录 + kwargs = self.get_kwargs.get_create_dir_kwargs() + pipeline.add_act( + act_name=_("MongoDB-创建原子任务执行目录"), act_component_code=ExecuteDBActuatorJobComponent.code, kwargs=kwargs + ) + + def multi_cluster_flow(self, enable: bool): + """ + multi replicaset create/delete user流程 + enable True:启用 + enable False:禁用 + """ + + # 创建流程实例 + pipeline = Builder(root_id=self.root_id, data=self.data) + + # 获取所有的cluster主机信息 + self.get_kwargs.get_hosts_deinstall() + + # 下发介质 + self.prepare_job(pipeline=pipeline) + + # cluster启用/禁用——子流程并行 + sub_pipelines = [] + for cluster_id in self.data["cluster_ids"]: + sub_pipline = cluster_enable_disable( + root_id=self.root_id, + ticket_data=self.data, + sub_kwargs=self.get_kwargs, + cluster_id=cluster_id, + enable=enable, + ) + sub_pipelines.append(sub_pipline) + pipeline.add_parallel_sub_pipeline(sub_flow_list=sub_pipelines) + + # 运行流程 + pipeline.run_pipeline() diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/__init__.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/__init__.py index 669848463e..d2c4c25eba 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/__init__.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/__init__.py @@ -10,6 +10,7 @@ """ +from .cluster_enable_disable import cluster_enable_disable from .cluster_increase_node import cluster_increase_node from .cluster_reduce_node import cluster_reduce_node from .cluster_replace import cluster_replace diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/cluster_enable_disable.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/cluster_enable_disable.py new file mode 100644 index 0000000000..a3b499e8f1 --- /dev/null +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/cluster_enable_disable.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 copy import deepcopy +from typing import Dict, Optional + +from django.utils.translation import ugettext as _ + +from backend.db_meta.enums.cluster_type import ClusterType +from backend.flow.consts import MongoDBInstanceType +from backend.flow.engine.bamboo.scene.common.builder import SubBuilder +from backend.flow.plugins.components.collections.mongodb.enable_disable_mongodb import ( + EnableDisableMongoDBOperationComponent, +) +from backend.flow.plugins.components.collections.mongodb.exec_actuator_job import ExecuteDBActuatorJobComponent +from backend.flow.utils.mongodb.mongodb_dataclass import ActKwargs + + +def cluster_enable_disable( + root_id: str, ticket_data: Optional[Dict], sub_kwargs: ActKwargs, cluster_id: int, enable: bool +) -> SubBuilder: + """ + cluster禁用启用流程 + """ + + # 获取变量 + sub_get_kwargs = deepcopy(sub_kwargs) + + # 创建子流程 + sub_pipeline = SubBuilder(root_id=root_id, data=ticket_data) + + # 设置参数 + sub_get_kwargs.payload["app"] = sub_get_kwargs.payload["bk_app_abbr"] + + # 获取集群信息 + sub_get_kwargs.get_cluster_info_deinstall(cluster_id=cluster_id) + + acts_list = [] + name = "" + # 启用 + if enable: + name = "enable" + if sub_get_kwargs.payload["cluster_type"] == ClusterType.MongoReplicaSet.value: + for node in sub_get_kwargs.payload["nodes"]: + kwargs = sub_get_kwargs.get_mongo_start_kwargs( + node_info=node, + instance_type=MongoDBInstanceType.MongoD.value, + ) + acts_list.append( + { + "act_name": _("MongoDB-{}:{}-mongod开启进程".format(node["ip"], str(node["port"]))), + "act_component_code": ExecuteDBActuatorJobComponent.code, + "kwargs": kwargs, + } + ) + elif sub_get_kwargs.payload["cluster_type"] == ClusterType.MongoShardedCluster.value: + for mongos in sub_get_kwargs.payload["mongos_nodes"]: + kwargs = sub_get_kwargs.get_mongo_start_kwargs( + node_info=mongos, + instance_type=MongoDBInstanceType.MongoS.value, + ) + acts_list.append( + { + "act_name": _("MongoDB-{}:{}-mongos开启进程".format(mongos["ip"], str(mongos["port"]))), + "act_component_code": ExecuteDBActuatorJobComponent.code, + "kwargs": kwargs, + } + ) + # 禁用 + else: + name = "disable" + if sub_get_kwargs.payload["cluster_type"] == ClusterType.MongoReplicaSet.value: + for node in sub_get_kwargs.payload["nodes"]: + kwargs = sub_get_kwargs.get_mongo_deinstall_kwargs( + node_info=node, + instance_type=MongoDBInstanceType.MongoD.value, + nodes_info=sub_get_kwargs.payload["nodes"], + force=True, + rename_dir=False, + ) + acts_list.append( + { + "act_name": _("MongoDB-{}:{}-mongod关闭进程".format(node["ip"], node["port"])), + "act_component_code": ExecuteDBActuatorJobComponent.code, + "kwargs": kwargs, + } + ) + elif sub_get_kwargs.payload["cluster_type"] == ClusterType.MongoShardedCluster.value: + for mongos in sub_get_kwargs.payload["mongos_nodes"]: + print("=" * 100) + print(mongos) + kwargs = sub_get_kwargs.get_mongo_deinstall_kwargs( + node_info=mongos, + instance_type=MongoDBInstanceType.MongoS.value, + nodes_info=[mongos], + force=True, + rename_dir=False, + ) + acts_list.append( + { + "act_name": _("MongoDB-{}:{}-mongos关闭进程".format(mongos["ip"], mongos["port"])), + "act_component_code": ExecuteDBActuatorJobComponent.code, + "kwargs": kwargs, + } + ) + sub_pipeline.add_parallel_acts(acts_list=acts_list) + + # 修改cluster状态 + kwargs = {"cluster_id": cluster_id, "enable": enable} + sub_pipeline.add_act( + act_name=_("修改meta"), + act_component_code=EnableDisableMongoDBOperationComponent.code, + kwargs=kwargs, + ) + + return sub_pipeline.build_sub_process(sub_name=_("MongoDB--cluster-{}".format(name))) diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/deinstall.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/deinstall.py index 64aab0ba5b..74405510e8 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/deinstall.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/deinstall.py @@ -32,7 +32,7 @@ def mongo_deinstall_parallel(sub_get_kwargs: ActKwargs, nodes: list, instance_ty acts_list = [] for node in nodes: kwargs = sub_get_kwargs.get_mongo_deinstall_kwargs( - node_info=node, nodes_info=nodes, instance_type=instance_type, force=force + node_info=node, nodes_info=nodes, instance_type=instance_type, force=force, rename_dir=True ) acts_list.append( { diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongod_replace.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongod_replace.py index b9bda3398f..4e2b0e20f1 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongod_replace.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongod_replace.py @@ -187,6 +187,7 @@ def mongod_replace( instance_type=MongoDBInstanceType.MongoD.value, nodes_info=sub_sub_get_kwargs.payload["nodes"], force=force, + rename_dir=True, ) sub_sub_pipeline.add_act( act_name=_("MongoDB-老实例下架-{}:{}".format(info["ip"], str(sub_sub_get_kwargs.db_instance["port"]))), diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongos_replace.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongos_replace.py index 410c4556f6..fc95333add 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongos_replace.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/mongos_replace.py @@ -143,6 +143,7 @@ def mongos_replace(root_id: str, ticket_data: Optional[Dict], sub_sub_kwargs: Ac instance_type=MongoDBInstanceType.MongoS.value, nodes_info=sub_sub_get_kwargs.payload["mongos_nodes"], force=True, + rename_dir=True, ) sub_sub_pipeline.add_act( act_name=_("MongoDB-老实例下架-{}:{}".format(info["ip"], str(sub_sub_get_kwargs.db_instance["port"]))), diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/reduce_mongod.py b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/reduce_mongod.py index 182a30a453..3fc6b44208 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/reduce_mongod.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/mongodb/sub_task/reduce_mongod.py @@ -84,10 +84,7 @@ def reduce_mongod(root_id: str, ticket_data: Optional[Dict], sub_kwargs: ActKwar # mongod下架 kwargs = sub_get_kwargs.get_mongo_deinstall_kwargs( - node_info=node, - instance_type=MongoDBInstanceType.MongoD.value, - nodes_info=[node], - force=True, + node_info=node, instance_type=MongoDBInstanceType.MongoD.value, nodes_info=[node], force=True, rename_dir=True ) sub_pipeline.add_act( act_name=_("MongoDB-{}-mongod下架".format(node["ip"])), diff --git a/dbm-ui/backend/flow/engine/controller/mongodb.py b/dbm-ui/backend/flow/engine/controller/mongodb.py index 8ef59aab9a..9ea1b21842 100644 --- a/dbm-ui/backend/flow/engine/controller/mongodb.py +++ b/dbm-ui/backend/flow/engine/controller/mongodb.py @@ -11,6 +11,7 @@ from backend.flow.engine.bamboo.scene.mongodb.mongodb_backup import MongoBackupFlow from backend.flow.engine.bamboo.scene.mongodb.mongodb_cluster_scale_mongos import ScaleMongoSFlow from backend.flow.engine.bamboo.scene.mongodb.mongodb_deinstall import MongoDBDeInstallFlow +from backend.flow.engine.bamboo.scene.mongodb.mongodb_enable_disable import MongoEnableDisableFlow from backend.flow.engine.bamboo.scene.mongodb.mongodb_exec_script import MongoExecScriptFlow from backend.flow.engine.bamboo.scene.mongodb.mongodb_fake_install import MongoFakeInstallFlow from backend.flow.engine.bamboo.scene.mongodb.mongodb_install import MongoDBInstallFlow @@ -164,3 +165,19 @@ def reduce_node(self): flow = MongoScaleNodeFlow(root_id=self.root_id, data=self.ticket_data) flow.multi_cluster_scale_node_flow(increase=False) + + def enable_cluster(self): + """ + 启用cluster + """ + + flow = MongoEnableDisableFlow(root_id=self.root_id, data=self.ticket_data) + flow.multi_cluster_flow(enable=True) + + def disable_cluster(self): + """ + 禁用cluster + """ + + flow = MongoEnableDisableFlow(root_id=self.root_id, data=self.ticket_data) + flow.multi_cluster_flow(enable=False) diff --git a/dbm-ui/backend/flow/plugins/components/collections/mongodb/enable_disable_mongodb.py b/dbm-ui/backend/flow/plugins/components/collections/mongodb/enable_disable_mongodb.py new file mode 100644 index 0000000000..6da57b590a --- /dev/null +++ b/dbm-ui/backend/flow/plugins/components/collections/mongodb/enable_disable_mongodb.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. +""" +import logging +from typing import List + +from pipeline.component_framework.component import Component +from pipeline.core.flow.activity import Service + +from backend.db_meta.models import Cluster +from backend.flow.plugins.components.collections.common.base_service import BaseService + +logger = logging.getLogger("json") + + +class EnableDisableMongoDBOperation(BaseService): + """ + EnableDisableMongoDB服务 + """ + + def _execute(self, data, parent_data) -> bool: + """ + 执行创建名字服务功能的函数 + global_data 单据全局变量,格式字典 + kwargs 私有变量 + {"cluster_id": 1, "enable": True} + "enable": True 启用 False 禁用 + """ + + # 从流程节点中获取变量 + kwargs = data.get_one_of_inputs("kwargs") + + # 修改meta + if kwargs["enable"]: + phase = "online" + else: + phase = "offline" + try: + cluster = Cluster.objects.get(id=kwargs["cluster_id"]) + cluster.phase = phase + cluster.save() + except Exception as e: + logger.error("change cluster phase status:{} fail, error:{}".format(phase, e)) + return False + self.log_info("change cluster phase status:{} successfully".format(phase)) + 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 EnableDisableMongoDBOperationComponent(Component): + """ + EnableDisableMongoDBOperation组件 + """ + + name = __name__ + code = "enable_disable_mongodb_operation" + bound_service = EnableDisableMongoDBOperation diff --git a/dbm-ui/backend/flow/urls.py b/dbm-ui/backend/flow/urls.py index 4ef9d6743a..772c69b594 100644 --- a/dbm-ui/backend/flow/urls.py +++ b/dbm-ui/backend/flow/urls.py @@ -75,6 +75,8 @@ MongoDBCreateUserView, MongoDBDeInstallView, MongoDBDeleteUserView, + MongoDBDisableClusterView, + MongoDBEnableClusterView, MongoDBExecScriptView, MongoDBIncreaseMongoSView, MongoDBIncreaseNodeView, @@ -306,6 +308,8 @@ url(r"^scene/cluster_scale$", MongoDBScaleView.as_view()), url(r"^scene/multi_cluster_increase_node$", MongoDBIncreaseNodeView.as_view()), url(r"^scene/multi_cluster_reduce_node$", MongoDBReduceNodeView.as_view()), + url(r"^scene/multi_cluster_enable$", MongoDBEnableClusterView.as_view()), + url(r"^scene/multi_cluster_disable$", MongoDBDisableClusterView.as_view()), # mongodb end # mysql upgrade url(r"^scene/upgrade_mysql_proxy$", UpgradeMySQLProxySceneApiView.as_view()), diff --git a/dbm-ui/backend/flow/utils/mongodb/mongodb_dataclass.py b/dbm-ui/backend/flow/utils/mongodb/mongodb_dataclass.py index eacd6575a8..1c48d0c5b6 100644 --- a/dbm-ui/backend/flow/utils/mongodb/mongodb_dataclass.py +++ b/dbm-ui/backend/flow/utils/mongodb/mongodb_dataclass.py @@ -696,7 +696,7 @@ def get_cluster_info_user(self, cluster_id: int, admin_user: str): """创建/删除用户获取cluster信息""" # 获取集群信息 - cluster_info = MongoRepository().fetch_one_cluster(id=cluster_id) + cluster_info = MongoRepository().fetch_one_cluster(set_get_domain=False, id=cluster_id) bk_cloud_id = cluster_info.bk_cloud_id self.cluster_type = cluster_info.cluster_type exec_ip: str = None @@ -813,7 +813,7 @@ def get_hosts_deinstall(self): hosts = set() bk_cloud_id: int = None for cluster_id in self.payload["cluster_ids"]: - cluster_info = MongoRepository().fetch_one_cluster(id=cluster_id) + cluster_info = MongoRepository().fetch_one_cluster(set_get_domain=False, id=cluster_id) if cluster_info.cluster_type == ClusterType.MongoReplicaSet.value: shard = cluster_info.get_shards()[0] bk_cloud_id = shard.members[0].bk_cloud_id @@ -839,7 +839,7 @@ def get_hosts_deinstall(self): def get_cluster_info_deinstall(self, cluster_id: int): """卸载流程获取cluster信息""" - cluster_info = MongoRepository().fetch_one_cluster(id=cluster_id) + cluster_info = MongoRepository().fetch_one_cluster(set_get_domain=True, id=cluster_id) self.payload["cluster_type"] = cluster_info.cluster_type self.payload["set_id"] = cluster_info.name self.payload["cluster_name"] = cluster_info.name @@ -926,7 +926,9 @@ def get_cluster_info_deinstall(self, cluster_id: int): self.payload["shards_nodes"] = shards_nodes self.payload["config_nodes"] = config_nodes - def get_mongo_deinstall_kwargs(self, node_info: dict, instance_type: str, nodes_info: list, force: bool) -> dict: + def get_mongo_deinstall_kwargs( + self, node_info: dict, instance_type: str, nodes_info: list, force: bool, rename_dir: bool + ) -> dict: """卸载mongo的kwargs""" nodes = [] @@ -948,6 +950,7 @@ def get_mongo_deinstall_kwargs(self, node_info: dict, instance_type: str, nodes_ "nodeInfo": nodes, "instanceType": instance_type, "force": force, + "renameDir": rename_dir, }, }, } @@ -1640,26 +1643,6 @@ def calc_reduce_node(self, info: dict): hosts.append({"ip": host, "bk_cloud_id": bk_cloud_id}) self.payload["hosts"] = hosts - # def get_host_reduce_node(self): - # """cluster减少node获取主机""" - # - # hosts_set = set() - # hosts = [] - # if self.payload["cluster_type"] == ClusterType.MongoReplicaSet.value: - # bk_cloud_id = self.payload["db_instances"][0]["bk_cloud_id"] - # for host in self.payload["db_instances"]: - # hosts_set.add(host["ip"]) - # for host in hosts_set: - # hosts.append({"ip": host, "bk_cloud_id": bk_cloud_id}) - # elif self.payload["cluster_type"] == ClusterType.MongoShardedCluster.value: - # for shard in self.payload["shards_instance_relationships"].values(): - # for node in shard: - # hosts_set.add(node["ip"]) - # - # - # - # self.payload["hosts"] = hosts - def get_reduce_node_kwargs(self, info: dict) -> dict: """减少node的kwargs""" @@ -1687,6 +1670,48 @@ def get_reduce_node_kwargs(self, info: dict) -> dict: }, } + def get_hosts_enable_disable(self): + """获取所有需要启用或禁用的cluster的hosts""" + + hosts = set() + bk_cloud_id: int = None + for cluster_id in self.payload["cluster_ids"]: + cluster_info = MongoRepository().fetch_one_cluster(set_get_domain=False, id=cluster_id) + if cluster_info.cluster_type == ClusterType.MongoReplicaSet.value: + shard = cluster_info.get_shards()[0] + bk_cloud_id = shard.members[0].bk_cloud_id + for member in shard.members: + hosts.add(member.ip) + elif cluster_info.cluster_type == ClusterType.MongoShardedCluster.value: + mongos = cluster_info.get_mongos() + bk_cloud_id = mongos[0].bk_cloud_id + for mongo in mongos: + hosts.add(mongo.ip) + list_hosts = [] + for host in hosts: + list_hosts.append({"ip": host, "bk_cloud_id": bk_cloud_id}) + self.payload["hosts"] = list_hosts + + def get_mongo_start_kwargs(self, node_info: dict, instance_type: str) -> dict: + """卸载mongo的kwargs""" + + return { + "set_trans_data_dataclass": CommonContext.__name__, + "get_trans_data_ip_var": None, + "bk_cloud_id": self.payload["bk_cloud_id"], + "exec_ip": node_info["ip"], + "db_act_template": { + "action": MongoDBActuatorActionEnum.MongoStart, + "file_path": self.file_path, + "payload": { + "ip": node_info["ip"], + "port": node_info["port"], + "instanceType": instance_type, + "auth": True, + }, + }, + } + @dataclass() class CommonContext: diff --git a/dbm-ui/backend/flow/utils/mongodb/mongodb_repo.py b/dbm-ui/backend/flow/utils/mongodb/mongodb_repo.py index b5f6bb7f38..43b348091e 100644 --- a/dbm-ui/backend/flow/utils/mongodb/mongodb_repo.py +++ b/dbm-ui/backend/flow/utils/mongodb/mongodb_repo.py @@ -211,13 +211,17 @@ def __init__(self): pass @classmethod - def fetch_many_cluster(cls, **kwargs): + def fetch_many_cluster(cls, set_get_domain: bool, **kwargs): + # set_get_domain 是否获取复制集的域名 rows: List[MongoDBCluster] = [] v = Cluster.objects.filter(**kwargs) for i in v: if i.cluster_type == ClusterType.MongoReplicaSet.value: # MongoReplicaSet 只有一个Set - shard = ReplicaSet(i.name, [MongoNode.from_instance(m) for m in i.storageinstance_set.all()]) + if set_get_domain: + shard = ReplicaSet(i.name, [MongoNode.from_proxy_instance(m) for m in i.storageinstance_set.all()]) + else: + shard = ReplicaSet(i.name, [MongoNode.from_instance(m) for m in i.storageinstance_set.all()]) row = ReplicaSetCluster( bk_cloud_id=i.bk_cloud_id, @@ -266,8 +270,8 @@ def fetch_many_cluster(cls, **kwargs): return rows @classmethod - def fetch_one_cluster(cls, **kwargs): - rows = cls.fetch_many_cluster(**kwargs) + def fetch_one_cluster(cls, set_get_domain: bool, **kwargs): + rows = cls.fetch_many_cluster(set_get_domain, **kwargs) if len(rows) > 0: return rows[0] return None diff --git a/dbm-ui/backend/flow/views/mongodb_scene.py b/dbm-ui/backend/flow/views/mongodb_scene.py index 6191ad1c80..4a1d154052 100644 --- a/dbm-ui/backend/flow/views/mongodb_scene.py +++ b/dbm-ui/backend/flow/views/mongodb_scene.py @@ -212,3 +212,27 @@ def post(request): root_id = uuid.uuid1().hex MongoDBController(root_id=root_id, ticket_data=request.data).reduce_node() return Response({"root_id": root_id}) + + +class MongoDBEnableClusterView(FlowTestView): + """ + 启用mongodb + """ + + @staticmethod + def post(request): + root_id = uuid.uuid1().hex + MongoDBController(root_id=root_id, ticket_data=request.data).enable_cluster() + return Response({"root_id": root_id}) + + +class MongoDBDisableClusterView(FlowTestView): + """ + 禁用mongodb + """ + + @staticmethod + def post(request): + root_id = uuid.uuid1().hex + MongoDBController(root_id=root_id, ticket_data=request.data).disable_cluster() + return Response({"root_id": root_id})