Skip to content

Commit

Permalink
feat(backend): 单据互斥可临时修改 & 导出数据逻辑变更 #8576
Browse files Browse the repository at this point in the history
  • Loading branch information
iSecloud committed Dec 12, 2024
1 parent 393dead commit d912038
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 24 deletions.
1 change: 1 addition & 0 deletions dbm-ui/backend/configuration/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class SystemSettingsEnum(str, StructuredEnum):
AFFINITY = EnumField("AFFINITY", _("容灾要求(各个环境可能不同,比如SG为空)"))
SYSTEM_MSG_TYPE = EnumField("SYSTEM_MSG_TYPE", _("系统消息通知方式"))
PADDING_PROXY_CLUSTER_LIST = EnumField("PADDING_PROXY_CLUSTER_LIST", _("补全proxy的集群域名列表"))
EXCLUSIVE_TICKET_MAP = EnumField("EXCLUSIVE_TICKET_MAP", _("单据互斥表(全局)"))
# ITSM配置
BK_ITSM_SERVICE_ID = EnumField("BK_ITSM_SERVICE_ID", _("DBM的流程服务ID"))
ITSM_APPROVAL_KEY = EnumField("ITSM_APPROVAL_KEY", _("ITSM审批意见key"))
Expand Down
2 changes: 1 addition & 1 deletion dbm-ui/backend/configuration/models/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def insert_setting_value(cls, key: str, value: Any, value_type: str = "str", use
)

@classmethod
def get_external_whitelist_cluster_ids(cls) -> List[int]:
def get_external_whitelist_cluster_ids(cls) -> List:
return [
conf["cluster_id"]
for conf in cls.get_setting_value(
Expand Down
2 changes: 2 additions & 0 deletions dbm-ui/backend/ticket/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

def init_ticket_flow_config(sender, **kwargs):
from backend.ticket.handler import TicketHandler
from backend.ticket.models import ClusterOperateRecord

try:
TicketHandler.ticket_flow_config_init()
ClusterOperateRecord.objects.get_exclusive_ticket_map(force=True)
except Exception as err: # pylint: disable=broad-except:
logger.warning(f"ticket_flow_config_init occur error, {err}")

Expand Down
24 changes: 15 additions & 9 deletions dbm-ui/backend/ticket/builders/mysql/mysql_dump_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,16 @@ class MySQLDumpDataDetailSerializer(MySQLBaseOperateDetailSerializer):
dump_data = serializers.BooleanField(help_text=_("是否导出表数据"))
force = serializers.BooleanField(help_text=_("是否强制执行"), default=False)

def to_internal_value(self, data):
data = super().to_internal_value(data)
data["is_external"] = getattr(self.context["request"], "is_external", False)
return data


class MySQLDumpDataItsmFlowParamsBuilder(builders.ItsmParamBuilder):
def get_params(self):
params = super().get_params()
bk_biz_id = self.ticket.bk_biz_id
# 数据导出的审批人是该业务下的产品,如果没有产品则按照原来审批人
approve_index = [field["key"] for field in params["fields"]].index("approver")
old_approver = params["fields"].pop(approve_index)["value"]
biz_productor = AppCache.get_app_attr_from_cc(bk_biz_id, attr_name="bk_biz_productor") or old_approver
params["fields"].append({"key": "approver", "value": biz_productor})
return params
def get_approvers(self):
bk_biz_maintainer = AppCache.get_app_attr_from_cc(self.ticket.bk_biz_id, attr_name="bk_biz_maintainer")
return bk_biz_maintainer or super().get_approvers()


class MySQLDumpDataFlowParamBuilder(builders.FlowParamBuilder):
Expand Down Expand Up @@ -77,3 +76,10 @@ class MySQLDumpDataFlowBuilder(BaseMySQLTicketFlowBuilder):
inner_flow_builder = MySQLDumpDataFlowParamBuilder
inner_flow_name = _("数据导出执行")
itsm_flow_builder = MySQLDumpDataItsmFlowParamsBuilder

@property
def need_itsm(self):
# 1. 导出数据和表结构 :运维人员审批
# 2.导出数据 :运维人员审批
# 3.导出表结构 :正常情况 - 不需要审批,PO环境 - 运维人员审批
return self.ticket.details["dump_data"] or self.ticket.details["is_external"]
Binary file modified dbm-ui/backend/ticket/exclusive_ticket.xlsx
Binary file not shown.
34 changes: 20 additions & 14 deletions dbm-ui/backend/ticket/models/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from backend import env
from backend.bk_web.constants import LEN_L_LONG, LEN_LONG, LEN_NORMAL, LEN_SHORT
from backend.bk_web.models import AuditedModel
from backend.configuration.constants import PLAT_BIZ_ID, DBType
from backend.configuration.constants import PLAT_BIZ_ID, DBType, SystemSettingsEnum
from backend.configuration.models import SystemSettings
from backend.db_monitor.exceptions import AutofixException
from backend.ticket.constants import (
EXCLUSIVE_TICKET_EXCEL_PATH,
Expand Down Expand Up @@ -272,13 +273,13 @@ def filter_actives(self, cluster_id, *args, **kwargs):
return self.filter(cluster_id=cluster_id, ticket__status=TicketFlowStatus.RUNNING, *args, **kwargs)

def filter_inner_actives(self, cluster_id, *args, **kwargs):
"""获取集群正在运行的inner flow的单据记录。此时认为集群会在互斥阶段"""
"""获取集群正在 运行/失败 的inner flow的单据记录。此时认为集群会在互斥阶段"""
# 排除特定的单据,如自身单据重试排除自身
exclude_ticket_ids = kwargs.pop("exclude_ticket_ids", [])
return self.filter(
cluster_id=cluster_id,
flow__flow_type=FlowType.INNER_FLOW,
flow__status=TicketFlowStatus.RUNNING,
flow__status__in=[TicketFlowStatus.RUNNING, TicketFlowStatus.FAILED],
*args,
**kwargs,
).exclude(flow__ticket_id__in=exclude_ticket_ids)
Expand All @@ -290,28 +291,33 @@ def get_cluster_operations(self, cluster_id, **kwargs):
def has_exclusive_operations(self, ticket_type, cluster_id, **kwargs):
"""判断当前单据类型与集群正在进行中的单据是否互斥"""
active_records = self.filter_inner_actives(cluster_id, **kwargs)
exclusive_ticket_map = self.get_exclusive_ticket_map()
exclusive_infos = []
for record in active_records:
active_ticket_type = record.ticket.ticket_type
# 记录互斥信息。不存在互斥表默认为互斥
if self.exclusive_ticket_map[ticket_type].get(active_ticket_type, True):
if exclusive_ticket_map[ticket_type].get(active_ticket_type, True):
exclusive_infos.append({"exclusive_ticket": record.ticket, "root_id": record.flow.flow_obj_id})
return exclusive_infos

@property
def exclusive_ticket_map(self):
if hasattr(self, "_exclusive_ticket_map"):
return self._exclusive_ticket_map
@staticmethod
def get_exclusive_ticket_map(force=False):
"""获取单据互斥状态表, force为True表示强制刷新"""
exclusive_map = SystemSettings.get_setting_value(key=SystemSettingsEnum.EXCLUSIVE_TICKET_MAP, default={})
if exclusive_map and not force:
return exclusive_map

_exclusive_matrix = ExcelHandler.paser_matrix(EXCLUSIVE_TICKET_EXCEL_PATH)
_exclusive_ticket_map = defaultdict(dict)
for row_label, inner_dict in _exclusive_matrix.items():
exclusive_map = defaultdict(dict)
exclusive_matrix = ExcelHandler.paser_matrix(EXCLUSIVE_TICKET_EXCEL_PATH)
for row_label, inner_dict in exclusive_matrix.items():
for col_label, value in inner_dict.items():
row_key, col_key = TicketType.get_choice_value(row_label), TicketType.get_choice_value(col_label)
_exclusive_ticket_map[row_key][col_key] = value == "N"
exclusive_map[row_key][col_key] = value == "N"

setattr(self, "_exclusive_ticket_map", _exclusive_ticket_map)
return self._exclusive_ticket_map
SystemSettings.insert_setting_value(
key=SystemSettingsEnum.EXCLUSIVE_TICKET_MAP, value=exclusive_map, value_type="dict"
)
return exclusive_map


class ClusterOperateRecord(AuditedModel):
Expand Down

0 comments on commit d912038

Please sign in to comment.