Decouple cutover HF from portrait and tighten ops UI.

Portrait stays on biz-monitor; cutover create/ensure owns purpose=cutover_hf slots with project collect override, multi-interval bindings, window pause, and industrial detail UX. Also expand ZTE collect/config parsers and TextFSM for route/BGP/L2VPN/VRRP coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-19 21:11:31 +08:00
parent a65c9fc420
commit 285c19e5a3
67 changed files with 9510 additions and 723 deletions

View file

@ -14,20 +14,40 @@ from ._types import JsonType as _JsonType
class BizMigrationProject(Base):
"""Cutover project linking old/new collect tasks + baselines."""
"""Cutover project linking old/new portrait + HF collect tasks + baselines.
``old_task_id`` / ``new_task_id`` = portrait (biz-monitor) tasks — baseline source.
``old_hf_task_id`` / ``new_hf_task_id`` = cutover high-freq tasks — current source.
"""
__tablename__ = "biz_migration_project"
id: Mapped[str] = mapped_column(String(64), primary_key=True, default=lambda: uuid4().hex)
name: Mapped[str] = mapped_column(String(256), default="", index=True)
# Portrait / biz-monitor tasks (baseline batches come from these)
old_task_id: Mapped[str] = mapped_column(String(64), default="", index=True)
new_task_id: Mapped[str] = mapped_column(String(64), default="", index=True)
# Cutover high-freq tasks (current batches for evaluate)
old_hf_task_id: Mapped[str] = mapped_column(String(64), default="", index=True)
new_hf_task_id: Mapped[str] = mapped_column(String(64), default="", index=True)
old_baseline_batch_id: Mapped[str] = mapped_column(String(64), default="", index=True)
new_baseline_batch_id: Mapped[str] = mapped_column(String(64), default="", index=True)
# Reuse biz_port_mapping (before_if=old, after_if=new)
mapping_id: Mapped[str] = mapped_column(String(64), default="", index=True)
# BizMonitorTemplate — HOW (via compare template) + dual/status rules
monitor_template_id: Mapped[str] = mapped_column(String(64), default="", index=True)
# Project-level collect override (empty = use monitor template)
collect_metric_ids_json: Mapped[list] = mapped_column(_JsonType, default=list)
# Per-metric interval overrides: {"interface_brief": 60, "bgp_peer": 300}
metric_interval_sec_json: Mapped[dict] = mapped_column(_JsonType, default=dict)
# HF bindings (may be multiple tasks when intervals differ):
# [{"task_id":"...","metric_ids":["interface_brief"],"interval_sec":60}, ...]
old_hf_bindings_json: Mapped[list] = mapped_column(_JsonType, default=list)
new_hf_bindings_json: Mapped[list] = mapped_column(_JsonType, default=list)
# HF schedule window (project-level)
hf_interval_sec: Mapped[int] = mapped_column(Integer, default=60)
hf_start_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
hf_end_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
status: Mapped[str] = mapped_column(String(32), default="draft", index=True) # draft|active|done
note: Mapped[str] = mapped_column(String(512), default="")
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive, index=True)

View file

@ -30,6 +30,8 @@ class BizStateTask(Base):
vendor: Mapped[str] = mapped_column(String(64), default="")
device_type: Mapped[str] = mapped_column(String(64), default="")
note: Mapped[str] = mapped_column(String(256), default="")
# "" | portrait | cutover_hf — filter cutover HF in biz-state list
purpose: Mapped[str] = mapped_column(String(32), default="", index=True)
status: Mapped[str] = mapped_column(String(32), default="draft", index=True) # draft|running|paused|stopped
interval_sec: Mapped[int] = mapped_column(Integer, default=300)
# Keep snapshots for N calendar days (protected baselines/refs never auto-deleted)
@ -223,6 +225,8 @@ class BizCompareTemplate(Base):
compare_fields: Mapped[list] = mapped_column(_JsonType, default=list)
ignore_fields: Mapped[list] = mapped_column(_JsonType, default=list)
metrics_json: Mapped[list] = mapped_column(_JsonType, default=list)
# Template-owned type aliases: [{"from":"GE","to":"gei"}, ...]
iface_normalize_json: Mapped[list] = mapped_column(_JsonType, default=list)
note: Mapped[str] = mapped_column(String(512), default="")
created_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive, index=True)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=utcnow_naive)