diff --git a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_ins_migrate.py b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_ins_migrate.py index 52926262c8..95ab83aaff 100644 --- a/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_ins_migrate.py +++ b/dbm-ui/backend/flow/engine/bamboo/scene/redis/redis_ins_migrate.py @@ -169,7 +169,7 @@ def get_redis_install_sub_pipelines(self, act_kwargs, master_ip, slave_ip, spec_ self.data, act_kwargs, install_master_redis_params, - dbmon_install=True, + to_install_dbmon=True, to_trans_files=False, to_install_puglins=False, ) @@ -192,7 +192,7 @@ def get_redis_install_sub_pipelines(self, act_kwargs, master_ip, slave_ip, spec_ self.data, act_kwargs, install_slave_redis_params, - dbmon_install=True, + to_install_dbmon=True, to_trans_files=False, to_install_puglins=False, ) diff --git a/dbm-ui/backend/ticket/builders/redis/base.py b/dbm-ui/backend/ticket/builders/redis/base.py index 69fd4a341d..028d8559e7 100644 --- a/dbm-ui/backend/ticket/builders/redis/base.py +++ b/dbm-ui/backend/ticket/builders/redis/base.py @@ -40,6 +40,8 @@ class BaseRedisInstanceTicketFlowBuilder(RedisTicketFlowBuilderPatchMixin, Ticke ClusterType.TendisTwemproxyRedisInstance.value, ClusterType.TwemproxyTendisSSDInstance.value, ClusterType.TendisRedisInstance.value, + ClusterType.RedisCluster.value, + ClusterType.RedisInstance.value, ] diff --git a/dbm-ui/backend/ticket/builders/redis/redis_cluster_ins_migrate.py b/dbm-ui/backend/ticket/builders/redis/redis_cluster_ins_migrate.py new file mode 100644 index 0000000000..50c27e79db --- /dev/null +++ b/dbm-ui/backend/ticket/builders/redis/redis_cluster_ins_migrate.py @@ -0,0 +1,98 @@ +# -*- 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 import serializers + +from backend.db_meta.enums import ClusterType +from backend.db_meta.models import Cluster +from backend.db_services.dbbase.constants import IpSource +from backend.flow.engine.controller.redis import RedisController +from backend.ticket import builders +from backend.ticket.builders.common.base import SkipToRepresentationMixin, fetch_cluster_ids +from backend.ticket.builders.redis.base import BaseRedisInstanceTicketFlowBuilder +from backend.ticket.constants import TicketType + + +class RedisClusterInsMigrateDetailSerializer(SkipToRepresentationMixin, serializers.Serializer): + class RedisClusterInsMigrateItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + resource_spec = serializers.JSONField(help_text=_("资源规格")) + old_nodes = serializers.JSONField(help_text=_("旧节点信息集合")) + + ip_source = serializers.ChoiceField( + help_text=_("主机来源"), choices=IpSource.get_choices(), default=IpSource.RESOURCE_POOL + ) + infos = serializers.ListSerializer(help_text=_("实例迁移单据详情"), child=RedisClusterInsMigrateItemSerializer()) + + def validate(self, attrs): + self.validate_cluster_can_access(attrs) + return attrs + + def validate_cluster_can_access(self, attrs): + """校验集群状态是否可以提单""" + clusters = Cluster.objects.filter(id__in=fetch_cluster_ids(details=attrs)) + + for cluster in clusters: + if cluster.cluster_type != ClusterType.RedisCluster: + raise serializers.ValidationError( + _(f"Redis cluster[{cluster.id}] type is not {ClusterType.RedisCluster}") + ) + + def to_internal_value(self, data): + pass + + +class RedisClusterInsMigrateBuilder(builders.FlowParamBuilder): + controller = RedisController.redis_cluster_ins_migrate + + def format_ticket_data(self): + cluster_id = self.ticket_data["infos"][0]["cluster_id"] + cluster = Cluster.objects.get(id=cluster_id) + self.ticket_data.update( + cluster_id=cluster.id, + bk_cloud_id=cluster.bk_cloud_id, + resource_spec=self.ticket_data["infos"][0]["resource_spec"], + ) + + +class RedisClusterInstanceApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): + def format(self): + # 资源申请的一些参数补充 + cluster_id = self.ticket_data["infos"][0]["cluster_id"] + cluster = Cluster.objects.get(id=cluster_id) + self.ticket_data.update( + cluster_id=cluster.id, + bk_cloud_id=cluster.bk_cloud_id, + resource_spec=self.ticket_data["infos"][0]["resource_spec"], + ) + self.patch_info_affinity_location(roles=["backend_group"]) + + def post_callback(self): + next_flow = self.ticket.next_flow() + ticket_data = next_flow.details["ticket_data"] + for info in ticket_data["infos"]: + migrate_list = { + "src_master": f'{info["old_nodes"]["master"][0]["ip"]}:{info["old_nodes"]["master"][0]["port"]}', + "src_slave": f'{info["old_nodes"]["slave"][0]["ip"]}:{info["old_nodes"]["slave"][0]["port"]}', + "dest_master": f'{ticket_data["nodes"]["backend_group"][0]["master"]["ip"]}', + "dest_slave": f'{ticket_data["nodes"]["backend_group"][0]["slave"]["ip"]}', + "resource_spec": ticket_data["resource_spec"], + } + info["migrate_list"] = migrate_list + next_flow.save(update_fields=["details"]) + + +@builders.BuilderFactory.register(TicketType.REDIS_CLUSTER_INS_MIGRATE) +class RedisClusterInsMigrateBuilder(BaseRedisInstanceTicketFlowBuilder): + serializer = RedisClusterInsMigrateDetailSerializer + inner_flow_builder = RedisClusterInsMigrateBuilder + resource_apply_builder = RedisClusterInstanceApplyResourceParamBuilder + inner_flow_name = _("Redis 集群指定实例迁移") diff --git a/dbm-ui/backend/ticket/builders/redis/redis_single_ins_migrate.py b/dbm-ui/backend/ticket/builders/redis/redis_single_ins_migrate.py new file mode 100644 index 0000000000..d792eef13b --- /dev/null +++ b/dbm-ui/backend/ticket/builders/redis/redis_single_ins_migrate.py @@ -0,0 +1,109 @@ +# -*- 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 import serializers + +from backend.db_meta.enums import ClusterType +from backend.db_meta.models import Cluster +from backend.db_services.dbbase.constants import IpSource +from backend.flow.engine.controller.redis import RedisController +from backend.ticket import builders +from backend.ticket.builders.common.base import SkipToRepresentationMixin, fetch_cluster_ids +from backend.ticket.builders.redis.base import BaseRedisInstanceTicketFlowBuilder +from backend.ticket.constants import TicketType + + +class RedisSingleInsMigrateDetailSerializer(SkipToRepresentationMixin, serializers.Serializer): + class RedisSingleInsMigrateItemSerializer(serializers.Serializer): + cluster_id = serializers.IntegerField(help_text=_("集群ID")) + resource_spec = serializers.JSONField(help_text=_("资源规格")) + old_nodes = serializers.JSONField(help_text=_("旧节点信息集合")) + + ip_source = serializers.ChoiceField( + help_text=_("主机来源"), choices=IpSource.get_choices(), default=IpSource.RESOURCE_POOL + ) + infos = serializers.ListSerializer(help_text=_("实例迁移单据详情"), child=RedisSingleInsMigrateItemSerializer()) + + def validate(self, attrs): + self.validate_cluster_can_access(attrs) + return attrs + + def validate_cluster_can_access(self, attrs): + """校验集群状态是否可以提单""" + clusters = Cluster.objects.filter(id__in=fetch_cluster_ids(details=attrs)) + + for cluster in clusters: + if cluster.cluster_type != ClusterType.RedisInstance: + raise serializers.ValidationError( + _(f"Redis cluster[{cluster.id}] type is not {ClusterType.RedisInstance}") + ) + + +class RedisSingleInsMigrateBuilder(builders.FlowParamBuilder): + controller = RedisController.redis_single_ins_migrate + + def format_ticket_data(self): + cluster_id = self.ticket_data["infos"][0]["cluster_id"] + cluster = Cluster.objects.get(id=cluster_id) + self.ticket_data.update( + cluster_id=cluster.id, + bk_cloud_id=cluster.bk_cloud_id, + db_version=cluster.major_version, + resource_spec=self.ticket_data["infos"][0]["resource_spec"], + ) + + +class RedisSingleInstanceApplyResourceParamBuilder(builders.ResourceApplyParamBuilder): + def format(self): + # 资源申请的一些参数补充 + cluster_id = self.ticket_data["infos"][0]["cluster_id"] + cluster = Cluster.objects.get(id=cluster_id) + self.ticket_data.update( + cluster_id=cluster.id, + bk_cloud_id=cluster.bk_cloud_id, + db_version=cluster.major_version, + resource_spec=self.ticket_data["infos"][0]["resource_spec"], + ) + self.patch_info_affinity_location(roles=["backend_group"]) + + def fetch_cluster_map(self, ticket_data): + cluster_ids = fetch_cluster_ids(ticket_data) + clusters = Cluster.objects.filter(id__in=cluster_ids) + cluster_id__cluster = {cluster.id: cluster for cluster in clusters} + return cluster_id__cluster + + def patch_instance_migrate_info(self, ticket_data): + """补充实例迁移的信息""" + cluster_id__cluster = self.fetch_cluster_map(ticket_data) + for index, info in enumerate(ticket_data["infos"]): + cluster = cluster_id__cluster[info["cluster_id"]] + info.update( + cluster_id=cluster.id, + db_version=cluster.major_version, + src_master=f'{info["old_nodes"]["master"][0]["ip"]}:{info["old_nodes"]["master"][0]["port"]}', + src_slave=f'{info["old_nodes"]["slave"][0]["ip"]}:{info["old_nodes"]["slave"][0]["port"]}', + dest_master=f'{ticket_data["nodes"]["backend_group"][0]["master"]["ip"]}', + dest_slave=f'{ticket_data["nodes"]["backend_group"][0]["slave"]["ip"]}', + resource_spec=ticket_data["resource_spec"], + ) + + def post_callback(self): + next_flow = self.ticket.next_flow() + self.patch_instance_migrate_info(next_flow.details["ticket_data"]) + next_flow.save(update_fields=["details"]) + + +@builders.BuilderFactory.register(TicketType.REDIS_SINGLE_INS_MIGRATE) +class RedisSingleInsMigrateBuilder(BaseRedisInstanceTicketFlowBuilder): + serializer = RedisSingleInsMigrateDetailSerializer + inner_flow_builder = RedisSingleInsMigrateBuilder + resource_apply_builder = RedisSingleInstanceApplyResourceParamBuilder + inner_flow_name = _("Redis 主从指定实例迁移") diff --git a/dbm-ui/backend/ticket/constants.py b/dbm-ui/backend/ticket/constants.py index 9308ee4212..ae417a3b15 100644 --- a/dbm-ui/backend/ticket/constants.py +++ b/dbm-ui/backend/ticket/constants.py @@ -341,7 +341,9 @@ def get_cluster_type_by_ticket(cls, ticket_type): REDIS_CLUSTER_RENAME_DOMAIN = TicketEnumField("REDIS_CLUSTER_RENAME_DOMAIN", _("Redis集群域名重命名"), _("集群维护")) REDIS_CLUSTER_MAXMEMORY_SET = TicketEnumField("REDIS_CLUSTER_MAXMEMORY_SET", _("Redis 集群设置maxmemory")) # noqa REDIS_CLUSTER_LOAD_MODULES = TicketEnumField("REDIS_CLUSTER_LOAD_MODULES", _("Redis 集群加载modules")) # noqa - REDIS_TENDISPLUS_LIGHTNING_DATA= TicketEnumField("REDIS_TENDISPLUS_LIGHTNING_DATA", _("Tendisplus闪电导入数据"), _("集群维护")) # noqa + REDIS_TENDISPLUS_LIGHTNING_DATA = TicketEnumField("REDIS_TENDISPLUS_LIGHTNING_DATA", _("Tendisplus闪电导入数据"), _("集群维护")) # noqa + REDIS_CLUSTER_INS_MIGRATE = TicketEnumField("REDIS_CLUSTER_INS_MIGRATE", _("Redis 集群指定实例迁移"), _("集群管理")) + REDIS_SINGLE_INS_MIGRATE = TicketEnumField("REDIS_SINGLE_INS_MIGRATE", _("Redis 主从指定实例迁移"), _("集群管理")) # 大数据 KAFKA_APPLY = TicketEnumField("KAFKA_APPLY", _("Kafka 集群部署"), register_iam=False)