Skip to content

Commit

Permalink
feat(mysql): mysql、tendbcluster集群列表展示优化 TencentBlueKing#6686
Browse files Browse the repository at this point in the history
# Reviewed, transaction id: 17907
  • Loading branch information
peterxucai committed Sep 10, 2024
1 parent 6c13511 commit 4543c70
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 1 deletion.
57 changes: 56 additions & 1 deletion dbm-ui/backend/db_meta/models/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +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 itertools
import json
import logging
from datetime import datetime, timezone
Expand Down Expand Up @@ -419,6 +419,61 @@ def enable_dbha(self):
ClusterDBHAExt.objects.filter(cluster=self).delete()
self.refresh_from_db()

@classmethod
def get_cluster_id__primary_address_map(cls, cluster_ids: List[int]) -> Dict[int, str]:
"""
通过集群id列表批量
查询并返回 tendbcluster 的中控 primary
集群类型不是 TenDBCluster 时会抛出异常
返回值是 {cluster_id:"ip:port"} 形式的字典
"""
clusters = cls.objects.filter(id__in=cluster_ids).order_by("bk_cloud_id")

cluster_id__primary_address_map = {}
ctl_address__cluster_id_map = {}

grouped_clusters = itertools.groupby(clusters, key=lambda x: x.bk_cloud_id)
for bk_cloud_id, group in grouped_clusters:
addresses = []
for cluster in group:
if cluster.cluster_type != ClusterType.TenDBCluster.value:
logger.error(_("集群id:{} {} 类型集群没有中控节点".format(cluster.id, cluster.cluster_type)))
continue

spider_instance = cluster.proxyinstance_set.filter(
tendbclusterspiderext__spider_role=TenDBClusterSpiderRole.SPIDER_MASTER
).first() # 随便拿一个spider-master接入层

ctl_address = "{}{}{}".format(spider_instance.machine.ip, IP_PORT_DIVIDER, spider_instance.port + 1000)
addresses.append(ctl_address)
ctl_address__cluster_id_map[ctl_address] = cluster.id

logger.info("addresses: {}".format(addresses))

res = DRSApi.rpc(
{
"addresses": addresses,
"cmds": ["tdbctl get primary"],
"force": False,
"bk_cloud_id": bk_cloud_id,
}
)
logger.info("tdbctl get primary res: {}".format(res))

for item in res:
if item["error_msg"]:
logger.error(_("get primary failed: {}".format(item["error_msg"])))
continue

primary_info_table_data = item["cmd_results"][0]["table_data"]
if primary_info_table_data:
cluster_id__primary_address_map[ctl_address__cluster_id_map[item["address"]]] = "{}{}{}".format(
primary_info_table_data[0]["HOST"], IP_PORT_DIVIDER, primary_info_table_data[0]["PORT"]
)
else:
cluster_id__primary_address_map[ctl_address__cluster_id_map[item["address"]]] = item["address"]
return cluster_id__primary_address_map


class ClusterDBHAExt(AuditedModel):
"""
Expand Down
6 changes: 6 additions & 0 deletions dbm-ui/backend/db_meta/models/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ def find_storage_instance_by_ip(cls, addresses: List[Union[str, Dict]]):
address_filters = reduce(operator.or_, [Q(machine__ip=address) for address in addresses])
return cls.objects.select_related("machine").filter(address_filters)

@property
def simple_desc(self):
desc = super().simple_desc
desc["is_stand_by"] = self.is_stand_by
return desc


class ProxyInstance(InstanceMixin, AuditedModel):
version = models.CharField(max_length=64, default="", help_text=_("版本号"), blank=True, null=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def get_remote_infos(insts: List[StorageInstance]):
role: [inst.simple_desc for inst in cluster.proxies if inst.tendbclusterspiderext.spider_role == role]
for role in TenDBClusterSpiderRole.get_values()
}

remote_db, remote_dr = get_remote_infos(cluster.storages)
# 计算machine分组
machine_list = list(set([inst["bk_host_id"] for inst in [*remote_db, *remote_dr]]))
Expand Down Expand Up @@ -285,3 +286,8 @@ def retrieve_instance(cls, bk_biz_id: int, cluster_id: int, instance: str) -> di
"Error: Instance %s of cluster %s under %s is not exist" % (instance, cluster_id, bk_biz_id)
)
return cls._retrieve_instance(instance_details[0], cluster_id)

@classmethod
def get_cluster_primary(cls, cluster_ids: list) -> list:
cluster_id__primary_address_map = Cluster.get_cluster_id__primary_address_map(cluster_ids)
return [{"cluster_id": k, "primary": v} for k, v in cluster_id__primary_address_map.items()]
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"""
from django.utils.decorators import method_decorator
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response

from backend.bk_web.swagger import common_swagger_auto_schema
from backend.configuration.constants import DBType
Expand Down Expand Up @@ -102,3 +104,9 @@ def _external_perm_param_field(kwargs):
ResourceEnum.BUSINESS.id: kwargs["bk_biz_id"],
ResourceEnum.DBTYPE.id: kwargs["view_class"].db_type.value,
}

@action(methods=["POST"], detail=False, url_path="get_cluster_primary")
def get_cluster_primary(self, request, bk_biz_id: int):
"""获取集群primary"""
cluster_ids = request.data.get("cluster_ids")
return Response(self.query_class.get_cluster_primary(cluster_ids))

0 comments on commit 4543c70

Please sign in to comment.