Skip to content

Commit

Permalink
fix: bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
iSecloud committed Feb 13, 2025
1 parent b3bdda4 commit d9fe4fb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 34 deletions.
11 changes: 9 additions & 2 deletions dbm-ui/backend/ticket/flow_manager/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from backend.ticket.flow_manager.resource import ResourceApplyFlow, ResourceBatchApplyFlow, ResourceDeliveryFlow
from backend.ticket.flow_manager.timer import TimerFlow
from backend.ticket.models import Ticket
from backend.ticket.tasks.ticket_tasks import create_recycle_ticket

SUPPORTED_FLOW_MAP = {
FlowType.BK_ITSM.value: ItsmFlow,
Expand Down Expand Up @@ -104,13 +105,19 @@ def update_ticket_status(self):
return
origin_status, ticket.status = ticket.status, target_status
ticket.save(update_fields=["status", "update_at"])
self.ticket_status_trigger(origin_status, target_status)

# 执行状态更新钩子函数
self.ticket_status_trigger(origin_status, target_status)

def ticket_status_trigger(self, origin_status, target_status):
"""单据状态更新后的钩子函数"""
"""单据状态更新后的钩子函数。注:如果钩子函数非关键链路,请异步发起"""

# 单据状态变更后,发送通知。
# 忽略运行中:流转到内置任务无需通知,待继续在todo创建时才触发通知
# 忽略待补货:到资源申请节点,单据状态总会流转为待补货,但是只有待补货todo创建才触发通知
if target_status not in [TicketStatus.RUNNING, TicketStatus.RESOURCE_REPLENISH]:
notify.send_msg.apply_async(args=(self.ticket.id,))

# 如果是inner flow的终止,要联动回收主机。
if target_status == TicketStatus.TERMINATED and self.current_flow_obj.flow_type == FlowType.INNER_FLOW:
create_recycle_ticket.apply_async(args=(self.ticket.id,))
55 changes: 30 additions & 25 deletions dbm-ui/backend/ticket/models/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,39 +244,22 @@ def create_ticket(
return ticket

@classmethod
def create_recycle_ticket(cls, revoke_ticket_id: int):
"""
从一个终止单据派生产生另一个清理单据
:param revoke_ticket_id: 终止单据ID
"""
from backend.ticket.builders import BuilderFactory

revoke_ticket = cls.objects.get(id=revoke_ticket_id)
# 忽略非回收单据
if revoke_ticket.ticket_type not in BuilderFactory.apply_ticket_type:
return None
def __create_recycle_ticket(cls, recycle_hosts, revoke_ticket, ip_recycle, flow_name):
if not recycle_hosts:
return

# 获取回收机器,
# 判定是否允许回收:主机的实例的phase不能是online
from backend.db_meta.models import Machine
from backend.ticket.builders.common.base import fetch_apply_hosts

recycle_hosts = fetch_apply_hosts(revoke_ticket.details)
if not recycle_hosts:
return

host_ids = [host["bk_host_id"] for host in recycle_hosts]
online_filter = Q(storageinstance__phase=InstancePhase.ONLINE) | Q(proxyinstance__phase=InstancePhase.ONLINE)
if Machine.objects.filter(online_filter, bk_host_id__in=host_ids).count():
logger.error(_("机器存在正在运行的实例,不允许清理"))
return

# 创建回收单据流程,SQLServer暂时回收到故障池
ip_dest = IpDest.Fault if revoke_ticket.group == DBType.Sqlserver else IpDest.Resource
details = {
"recycle_hosts": recycle_hosts,
"ip_recycle": {"ip_dest": ip_dest, "for_biz": revoke_ticket.bk_biz_id},
"group": revoke_ticket.group,
}
# 创建回收单据流程
details = {"recycle_hosts": recycle_hosts, "ip_recycle": ip_recycle, "group": revoke_ticket.group}
recycle_ticket = cls.create_ticket(
ticket_type=TicketType.RECYCLE_HOST,
creator=revoke_ticket.creator,
Expand All @@ -290,10 +273,32 @@ def create_recycle_ticket(cls, revoke_ticket_id: int):
ticket=revoke_ticket,
flow_type=FlowType.DELIVERY.value,
details={"recycle_ticket": recycle_ticket.id},
flow_alias=_("申请主机清理释放"),
flow_alias=flow_name,
)

return recycle_ticket
@classmethod
def create_recycle_ticket(cls, revoke_ticket_id: int):
"""
从一个终止单据派生产生另一个清理单据
:param revoke_ticket_id: 终止单据ID
"""
from backend.ticket.builders import BuilderFactory
from backend.ticket.builders.common.base import fetch_apply_hosts, fetch_recycle_hosts

revoke_ticket = cls.objects.get(id=revoke_ticket_id)

# 对新申请机器进行回收
if revoke_ticket.ticket_type in BuilderFactory.apply_ticket_type:
recycle_hosts = fetch_apply_hosts(revoke_ticket.details)
ip_dest = IpDest.Fault if revoke_ticket.group == DBType.Sqlserver else IpDest.Resource
ip_recycle = {"ip_dest": ip_dest, "for_biz": revoke_ticket.bk_biz_id}
cls.__create_recycle_ticket(recycle_hosts, revoke_ticket, ip_recycle, flow_name=_("新申请机器进行回收"))

# 对将要下架机器进行回收
if revoke_ticket.ticket_type in BuilderFactory.recycle_ticket_type:
recycle_hosts = fetch_recycle_hosts(revoke_ticket.details)
ip_recycle = revoke_ticket.details["ip_recycle"]
cls.__create_recycle_ticket(recycle_hosts, revoke_ticket, ip_recycle, flow_name=_("下架机器进行回收"))

@classmethod
def create_ticket_from_bk_monitor(cls, callback_data):
Expand Down
8 changes: 1 addition & 7 deletions dbm-ui/backend/ticket/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
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 backend.ticket.constants import FlowType, TicketFlowStatus
from backend.ticket.flow_manager.manager import TicketFlowManager
from backend.ticket.models import Flow, Ticket
from backend.ticket.models import Flow


def update_ticket_status(sender, instance: Flow, **kwargs):
Expand All @@ -19,9 +18,4 @@ def update_ticket_status(sender, instance: Flow, **kwargs):
"""
if not instance.pk:
return

# 如果是inner flow的终止,要联动回收主机。TODO:等通知合并后,应该放到ticket trigger里面
if instance.flow_type == FlowType.INNER_FLOW and instance.status == TicketFlowStatus.TERMINATED:
Ticket.create_recycle_ticket(revoke_ticket_id=instance.ticket.id)

TicketFlowManager(instance.ticket).update_ticket_status()
6 changes: 6 additions & 0 deletions dbm-ui/backend/ticket/tasks/ticket_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,9 @@ def apply_ticket_task(
raise TicketTaskTriggerException(_("不支持的定时类型: {}").format(eta))

return res


@shared_task
def create_recycle_ticket(revoke_ticket_id: int):
"""创建主机回收单据"""
Ticket.create_recycle_ticket(revoke_ticket_id)

0 comments on commit d9fe4fb

Please sign in to comment.