From 31d09178e3b8ff1aea5e3512a0016842420e1ccf Mon Sep 17 00:00:00 2001 From: xiepaup Date: Thu, 14 Dec 2023 15:21:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(redis):=20=E8=87=AA=E6=84=88=E9=9B=86?= =?UTF-8?q?=E7=BE=A4=E4=BF=A1=E6=81=AF=E4=BF=AE=E5=A4=8D=20#2592?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_meta/api/cluster/apis.py | 2 +- .../backend/db_services/redis/autofix/bill.py | 2 +- .../builders/redis/redis_toolbox_autofix.py | 57 +++++++++++++++---- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/dbm-ui/backend/db_meta/api/cluster/apis.py b/dbm-ui/backend/db_meta/api/cluster/apis.py index d097a3b583..538d7c9cf9 100644 --- a/dbm-ui/backend/db_meta/api/cluster/apis.py +++ b/dbm-ui/backend/db_meta/api/cluster/apis.py @@ -116,4 +116,4 @@ def query_cluster_by_hosts(hosts: List): for machine in machine_cluster.values(): machine["ports"] = machine_ports.get(machine["ip"]) - return machine_cluster.values() + return list(machine_cluster.values()) diff --git a/dbm-ui/backend/db_services/redis/autofix/bill.py b/dbm-ui/backend/db_services/redis/autofix/bill.py index d7b1170509..089a0ff0a6 100644 --- a/dbm-ui/backend/db_services/redis/autofix/bill.py +++ b/dbm-ui/backend/db_services/redis/autofix/bill.py @@ -78,7 +78,7 @@ def create_ticket(cluster: RedisAutofixCore, redis_proxies: list, redis_slaves: ticket_type=TicketType.REDIS_CLUSTER_AUTOFIX.value, group=DBType.Redis.value, status=TicketStatus.PENDING.value, - remark=_("自动发起-自愈任务-{cluster.immute_domain}"), + remark=_("自动发起-自愈任务-{}".format(cluster.immute_domain)), details=details, is_reviewed=True, ) diff --git a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_autofix.py b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_autofix.py index a1a98fe830..bfc7ba38fe 100644 --- a/dbm-ui/backend/ticket/builders/redis/redis_toolbox_autofix.py +++ b/dbm-ui/backend/ticket/builders/redis/redis_toolbox_autofix.py @@ -13,6 +13,8 @@ from rest_framework import serializers from backend.configuration.constants import AffinityEnum +from backend.db_meta.enums import InstanceRole +from backend.db_meta.models import Cluster, StorageInstance from backend.db_services.dbbase.constants import IpSource from backend.flow.engine.controller.redis import RedisController from backend.ticket import builders @@ -52,12 +54,16 @@ def post_callback(self): ticket_data = next_flow.details["ticket_data"] for info_index, info in enumerate(self.ticket_data["infos"]): - for role in ["redis_master", "proxy", "redis_slave"]: + for role in [ + InstanceRole.REDIS_MASTER.value, + InstanceRole.REDIS_PROXY.value, + InstanceRole.REDIS_SLAVE.value, + ]: role_hosts = info.get(role) if not role_hosts: continue - role_group = "backend_group" if role == "redis_master" else role + role_group = "backend_group" if role == InstanceRole.REDIS_MASTER.value else role for role_host_index, role_host in enumerate(role_hosts): role_host["target"] = nodes.get(f"{info_index}_{role_group}")[role_host_index] @@ -88,18 +94,49 @@ def patch_ticket_detail(self): super().patch_ticket_detail() resource_spec = {} + cluster_ids = [infos["cluster_id"] for infos in self.ticket.details["infos"]] + id__cluster = {cluster.id: cluster for cluster in Cluster.objects.filter(id__in=cluster_ids)} for info in self.ticket.details["infos"]: - for role in ["redis_master", "proxy", "redis_slave"]: + cluster = id__cluster[info["cluster_id"]] + for role in [ + InstanceRole.REDIS_MASTER.value, + InstanceRole.REDIS_PROXY.value, + InstanceRole.REDIS_SLAVE.value, + ]: role_hosts = info.get(role) + if not role_hosts: continue - role_group = "backend_group" if role == "redis_master" else role - role_group_affinity = AffinityEnum.CROS_SUBZONE if role_group == "backend_group" else AffinityEnum.NONE - resource_spec[role_group] = { - "spec_id": info[role][0]["spec_id"], - "count": len(role_hosts), - "affinity": role_group_affinity.value, - } + + if role == InstanceRole.REDIS_MASTER.value: + # 如果替换角色是master,则是master/slave成对替换 + resource_spec["backend_group"] = { + "spec_id": info[role][0]["spec_id"], + "count": len(role_hosts), + "location_spec": {"city": cluster.region, "sub_zone_ids": []}, + "affinity": cluster.disaster_tolerance_level, + } + elif role == InstanceRole.REDIS_SLAVE.value: + # 如果是替换slave, 需要和当前集群中的配对的 master 不同机房 + redis_slaves = StorageInstance.objects.prefetch_related("as_receiver", "machine").filter( + cluster=cluster, machine__ip__in=[host["ip"] for host in role_hosts] + ) + ip__redis_slave = {slave.machine.ip: slave for slave in redis_slaves} + for role_host in role_hosts: + redis_master = ip__redis_slave[role_host["ip"]].as_receiver.get().ejector + resource_spec[f"{role}_{role_host['ip']}"] = { + "spec_id": role_host["spec_id"], + "count": 1, + "location_spec": { + "city": cluster.region, + "sub_zone_ids": [redis_master.machine.bk_sub_zone_id], + "include_or_exclue": False, + }, + } + elif role == InstanceRole.REDIS_PROXY.value: + # TODO: proxy替换的亲和性需要衡量存量proxy的分布,暂时忽略 + resource_spec[role] = {"spec_id": info[role][0]["spec_id"], "count": len(role_hosts)} + info["resource_spec"] = resource_spec self.ticket.save(update_fields=["details"])