mirror of
https://github.com/hansjone/netx.git
synced 2026-10-10 19:20:46 +08:00
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:
parent
a65c9fc420
commit
285c19e5a3
67 changed files with 9510 additions and 723 deletions
|
|
@ -253,6 +253,11 @@ const en = {
|
|||
filterColumn: "Column",
|
||||
filterAllCols: "All columns",
|
||||
listFilterPh: "Filter NE / IP / vendor / status",
|
||||
purposeFilter: "Task purpose",
|
||||
purposeAll: "All purposes",
|
||||
purposePortrait: "Portrait",
|
||||
purposeCutoverHf: "Cutover HF",
|
||||
colPurpose: "Purpose",
|
||||
colNe: "NE",
|
||||
colStatus: "Status",
|
||||
colLast: "Last collect",
|
||||
|
|
@ -366,7 +371,10 @@ const en = {
|
|||
"One pair per line: before_if,after_if (comma / tab / pipe). Example:\ngei-0/1/1,gei-0/1/2\nxgei-0/1/0,xgei-0/2/0\n# comments start with #. Not slash-grouped A,B/C,D.",
|
||||
mappingSaved: "Mapping saved",
|
||||
mappingOptionalHint:
|
||||
"Optional. Empty = ignore local port renames (match on non-interface keys). Fill to apply port map.",
|
||||
"Optional. Empty = ignore local port renames (match on non-interface keys). Fill to apply port map. Main-port pairs also cover .subinterfaces (suffix kept).",
|
||||
ifaceNormalize: "Interface normalize",
|
||||
ifaceNormalizeHint:
|
||||
"Template rules, one per line: alias,canonical. Applied before port mapping. Example:\nGE,gei\nSG,smartgroup\nXGE,xgei",
|
||||
createJob: "Create compare job",
|
||||
defaultJobName: "Cutover compare",
|
||||
jobName: "Name",
|
||||
|
|
@ -475,45 +483,78 @@ const en = {
|
|||
"Metric focus: port status (interface_brief / admin·phy·prot). Baseline → pick ports → evaluate board.",
|
||||
hintShort: "Monitor template sets rules; bind collect + dual baselines → expect → evaluate board.",
|
||||
create: "Create task",
|
||||
createHint: "Name the task and bind old/new business-monitor collect tasks. Mapping and baselines can be set later.",
|
||||
createHintShort: "Name + old/new collect tasks; template, mapping, baselines can come later.",
|
||||
createHint:
|
||||
"Except portrait baselines, the full cutover flow runs on this page; create auto-spawns HF biz-monitor tasks on schedule.",
|
||||
createHintShort:
|
||||
"Pick old/new NEs → monitor template & metrics → interval/window → baselines → port map → create. HF tasks are auto-created.",
|
||||
pickOldNe: "Old NE",
|
||||
pickNewNe: "New NE",
|
||||
pickNe: "Pick NE",
|
||||
pickNeHint: "Click to pick a device",
|
||||
hideNePicker: "Hide list",
|
||||
nePairReady: "Both NEs selected — continue, or click a card to re-pick.",
|
||||
needNePair: "Enter a name and select old/new NEs",
|
||||
needProjectName: "Enter a task name",
|
||||
needMonitorTemplate: "Select a monitor template",
|
||||
needMetrics: "Select at least one metric",
|
||||
noPortraitBaseline:
|
||||
"No portrait task/batches for this NE yet — run portrait collect in business monitor first (baselines can be set later).",
|
||||
baselineOptionalHint: "Baselines can be set later in detail; pick from portrait batches when available.",
|
||||
metricInterval: "Per-metric interval (sec)",
|
||||
metricIntervalOptional: "Per-metric interval (optional)",
|
||||
metricIntervalHint: "Leave blank to use the global interval; a filled value creates a separate HF task.",
|
||||
scheduleHint:
|
||||
"Enter the window in your local time; stored as UTC. Scheduler pauses HF outside the window.",
|
||||
sectionSchedule: "Collect interval & window",
|
||||
sectionBaseline: "Baselines & mapping",
|
||||
sectionDevices: "Old / new NEs",
|
||||
sectionMetrics: "Collect metrics",
|
||||
createSteps: "Create steps",
|
||||
stepDevices: "Devices",
|
||||
stepTemplate: "Template",
|
||||
stepSchedule: "Schedule",
|
||||
stepBaseline: "Baselines",
|
||||
next: "Next",
|
||||
back: "Back",
|
||||
colHf: "HF",
|
||||
hfReady: "Ready",
|
||||
hfMissing: "Missing",
|
||||
showCreateMore: "More: template / mapping / baselines",
|
||||
hideCreateMore: "Hide more",
|
||||
setupHintShort: "Collect tasks are fixed at create; set monitor template, mapping and dual baselines here.",
|
||||
setupHintShort: "Portrait tasks feed baselines; HF tasks feed cutover collect. Configure template, metrics, window and dual baselines here.",
|
||||
createProject: "Create task",
|
||||
projectName: "Task name",
|
||||
projectNamePh: "e.g. CN1/CN2 night-1 cutover",
|
||||
projectNamePh: "e.g. PE-A / PE-B cutover-1",
|
||||
sectionName: "1. Task name",
|
||||
sectionTasks: "2. Bind collect tasks (required)",
|
||||
sectionTasksHint: "Pick the old-device and new-device business-monitor tasks.",
|
||||
sectionOptional: "3. Monitor template, mapping & baselines (optional)",
|
||||
sectionOptionalHint:
|
||||
"Skip for now if needed; set later under Baseline. Defaults to the port cutover monitor template when omitted.",
|
||||
"Skip for now if needed; set later under Baseline. Defaults to the system monitor template when omitted.",
|
||||
sectionPair: "Bound collect tasks",
|
||||
sectionPairHint: "Collect tasks are fixed at create time; adjust monitor template, mapping and baselines here.",
|
||||
sectionBaseline: "Baseline batches",
|
||||
sectionBaselineHint: "Both old and new baselines are required; old lists expect objects, new feeds dual-side verdict.",
|
||||
optionalNone: "None",
|
||||
monitorTemplate: "Monitor template",
|
||||
monitorTemplateHint: "Chooses which metrics to compare and dual-side success semantics. Defaults to port cutover.",
|
||||
monitorTemplateHint: "Chooses which metrics to compare and dual-side success semantics. Defaults to the system monitor template.",
|
||||
compareTemplate: "Compare template",
|
||||
compareTemplateBound: "Bound compare template: {{name}}",
|
||||
portMappingHint:
|
||||
"With a mapping, iface metrics compare only mapped ports (they must appear after cutover). Same-name ports outside the map are not a migration; old down + new up is an anomaly. No mapping means same-name compare. BGP/PW still use the batch expect set.",
|
||||
baselineNeedTask: "Select the matching collect task first",
|
||||
baselinePickHint: "Choose from that task’s collect batches",
|
||||
oldTask: "Old-device collect task",
|
||||
newTask: "New-device collect task",
|
||||
oldTask: "Old-device portrait task",
|
||||
newTask: "New-device portrait task",
|
||||
portMapping: "Port mapping",
|
||||
oldBaseline: "Old baseline batch",
|
||||
newBaseline: "New baseline batch",
|
||||
needProjectFields: "Enter a name and pick old/new collect tasks",
|
||||
needProjectFields: "Enter a name and pick old/new portrait tasks",
|
||||
needExpectPorts: "Select at least one expected object for this batch",
|
||||
needBaselineFirst: "Save an old baseline batch first to list expect objects",
|
||||
needBothBaselines: "Save both old and new baseline batches before evaluating",
|
||||
errOldBaselineRequired: "Old baseline batch is required",
|
||||
errNewBaselineRequired: "New baseline batch is required",
|
||||
needBizStateTasks: "No business-monitor tasks yet. Create one first:",
|
||||
needBizStateTasks: "No portrait business-monitor tasks yet. Create one first:",
|
||||
projectCreated: "Task created",
|
||||
projects: "Tasks",
|
||||
empty: "No cutover tasks yet.",
|
||||
|
|
@ -538,42 +579,66 @@ const en = {
|
|||
tabSetup: "Baseline",
|
||||
tabBatches: "Batches",
|
||||
tabBoard: "Board",
|
||||
saveBaseline: "Save baseline / mapping / template",
|
||||
saveBaseline: "Save",
|
||||
baselineSaved: "Baseline saved",
|
||||
pickExpectPorts: "Expected objects (from old baseline)",
|
||||
portFilterPh: "Filter object / description",
|
||||
emptyBaselinePorts:
|
||||
"No matching metric rows in baseline (confirm monitor template and collect profiles)",
|
||||
pickExpectPorts: "Expect",
|
||||
portFilterPh: "Filter",
|
||||
emptyBaselinePorts: "No baseline data",
|
||||
batchLabel: "Batch label",
|
||||
defaultBatchLabel: "Night N",
|
||||
expectPorts: "Expected ports (old side)",
|
||||
expectPortsPh: "Comma or newline separated",
|
||||
createBatch: "New batch",
|
||||
createBatch: "New",
|
||||
batchCreated: "Batch created",
|
||||
batches: "Batches",
|
||||
startBatch: "Start batch",
|
||||
finishBatch: "Finish batch",
|
||||
evaluate: "Evaluate now",
|
||||
evaluated: "Evaluation done",
|
||||
startBatch: "Start",
|
||||
finishBatch: "Finish",
|
||||
evaluate: "Evaluate",
|
||||
evaluated: "Done",
|
||||
statusUpdated: "Status updated",
|
||||
board: "Progress board",
|
||||
board: "Board",
|
||||
metricPort: "Port status",
|
||||
progress: "Progress",
|
||||
anomaly: "Anomaly",
|
||||
onlyExpect: "Expected objects only",
|
||||
onlyExpect: "Expect only",
|
||||
onlyExpectHint: "Shows all drift by default; check to filter to this batch's expect set",
|
||||
pinCurrentBatches: "Current collect batches",
|
||||
pinOldBatch: "Old current batch",
|
||||
pinNewBatch: "New current batch",
|
||||
pinLatest: "Auto latest success",
|
||||
runHistory: "Run history",
|
||||
runLatest: "Latest run",
|
||||
pinOldBatch: "Old current",
|
||||
pinNewBatch: "New current",
|
||||
pinLatest: "Latest",
|
||||
runHistory: "Runs",
|
||||
runLatest: "Latest",
|
||||
colRuleHit: "Rule hit",
|
||||
mappingBound: "Mapping saved and bound to this project",
|
||||
allMetrics: "All metrics",
|
||||
colMetric: "Metric",
|
||||
colKey: "Object",
|
||||
colPort: "Old port",
|
||||
openRedChip: "Red {{n}}",
|
||||
metaPortrait: "Portrait",
|
||||
metaHf: "HF",
|
||||
metaBaseline: "Baseline",
|
||||
baselineOk: "set",
|
||||
baselineMissing: "missing",
|
||||
needBaselineFirst: "Set baseline first",
|
||||
enableHighfreq: "Enable HF",
|
||||
highfreqReady: "HF ready",
|
||||
collectNow: "Collect now",
|
||||
collectTriggered: "Collect triggered",
|
||||
openBizState: "Biz monitor",
|
||||
hfNotBound: "Unbound",
|
||||
projectCollectMetrics: "Metrics",
|
||||
hfInterval: "Interval(s)",
|
||||
hfStart: "Start",
|
||||
hfEnd: "End",
|
||||
markProjectDone: "Done / stop HF",
|
||||
confirmProjectDone: "Complete project and pause all HF?",
|
||||
projectMarkedDone: "Done; HF paused",
|
||||
deleteProject: "Delete",
|
||||
confirmDeleteProject: "Delete project? HF will pause and batches removed.",
|
||||
projectDeleted: "Deleted",
|
||||
acceptPassedShort: "Pass",
|
||||
acceptFailedShort: "Fail",
|
||||
colMapped: "Mapped new",
|
||||
colDesc: "Description",
|
||||
colOldPort: "Old port",
|
||||
|
|
@ -592,27 +657,34 @@ const en = {
|
|||
verdictNotInvolved: "Not involved",
|
||||
verdictUnexpected: "Unexpected new",
|
||||
verdictOk: "OK",
|
||||
enableHighfreq: "Enable high-freq collect",
|
||||
highfreqHint:
|
||||
"Creates/reuses high-freq biz-state tasks on old/new NEs using the monitor template’s collect_metric_ids (empty = all compare-template metrics).",
|
||||
highfreqReady: "High-freq collect tasks ready and bound to this task",
|
||||
collectNow: "Collect old+new now",
|
||||
collectTriggered: "Collect triggered",
|
||||
openBizState: "Open business monitor",
|
||||
boundTasks: "Bound collect tasks",
|
||||
acceptTitle: "Batch acceptance summary",
|
||||
acceptPassed: "Batch acceptance passed",
|
||||
acceptFailed: "Batch acceptance failed ({{n}} red tickets; you may continue)",
|
||||
acceptPassedShort: "Passed",
|
||||
acceptFailedShort: "Failed",
|
||||
newBaselineMissingBanner: "These sheets have no usable new baseline rows; verdicts are unreliable: {{metrics}}",
|
||||
acceptCarryHint: "Failure does not block the next batch; red tickets stay until resolved.",
|
||||
openRedHint: "{{n}} open red ticket(s) on this task (carry allowed)",
|
||||
highfreqHint: "",
|
||||
boundTasks: "Bound tasks",
|
||||
oldPortraitTask: "Old portrait",
|
||||
newPortraitTask: "New portrait",
|
||||
oldHfTask: "Old HF",
|
||||
newHfTask: "New HF",
|
||||
projectCollectHint: "",
|
||||
hfWindowInactive: "HF window inactive or project done",
|
||||
baselinePortraitOnly: "",
|
||||
collectSkipped: "skipped",
|
||||
collectSkippedBanner: "Skipped: {{metrics}}",
|
||||
currentMissing: "no current",
|
||||
currentMissingBanner: "No current: {{metrics}}",
|
||||
highfreqReadyInactive: "HF bound (window inactive, no collect)",
|
||||
collectPartial: "Partial fail (ok {{ok}} / fail {{fail}})",
|
||||
errMetricNeedsBindings: "Metric \"{{metric}}\" needs bindings ({{params}}); not supported for cutover HF — remove it",
|
||||
errNoProfileForMetric: "Metric \"{{metric}}\" has no collect profile for this vendor",
|
||||
acceptTitle: "Acceptance",
|
||||
acceptPassed: "Passed",
|
||||
acceptFailed: "Failed ({{n}} red)",
|
||||
newBaselineMissingBanner: "Missing new baseline: {{metrics}}",
|
||||
acceptCarryHint: "May continue with red",
|
||||
openRedHint: "Red {{n}}",
|
||||
redTitle: "Red tickets",
|
||||
redOpen: "open",
|
||||
resolveRed: "Resolve",
|
||||
redResolved: "Red ticket resolved",
|
||||
batchCreatedWithRed: "Batch created ({{n}} open red tickets; carry allowed)",
|
||||
redResolved: "Resolved",
|
||||
batchCreatedWithRed: "Batch created ({{n}} red)",
|
||||
colStatus: "Status",
|
||||
verdictUnfinished: "Unfinished",
|
||||
},
|
||||
|
|
@ -632,7 +704,7 @@ const en = {
|
|||
listFilterPh: "Filter name / compare template / note",
|
||||
kpiTotal: "Templates",
|
||||
colName: "Name",
|
||||
namePh: "e.g. Port+BGP cutover monitor",
|
||||
namePh: "e.g. Status cutover monitor",
|
||||
colCompare: "Compare template",
|
||||
colCollect: "HF collect metrics",
|
||||
colNote: "Note",
|
||||
|
|
@ -640,6 +712,15 @@ const en = {
|
|||
needName: "Name is required",
|
||||
defaultsInvalid: "Invalid defaults JSON",
|
||||
overridesInvalid: "Invalid sheet_overrides JSON",
|
||||
exportTemplate: "Export",
|
||||
importTemplate: "Import",
|
||||
templateExported: "Template exported",
|
||||
templateImported: "Template imported",
|
||||
templateImportInvalid:
|
||||
"Invalid import file: need name and compare_template_id (or compare_template_name)",
|
||||
templateImportHint: "Import/export JSON to share monitor templates (no job/batch data)",
|
||||
templateImportCompareMissing:
|
||||
"Matching compare template not found — import or create it first",
|
||||
formHint: "Pick a compare template → same sheet tabs appear → set success conditions per sheet.",
|
||||
compareHint: "Owns which sheets and Key/compare fields; here you only set dual verdict rules.",
|
||||
pickCompare: "Pick compare template…",
|
||||
|
|
@ -816,7 +897,7 @@ const en = {
|
|||
prev: "Back",
|
||||
next: "Next",
|
||||
fieldTitle: "Task name",
|
||||
titlePh: "e.g. Access uplinks",
|
||||
titlePh: "e.g. Uplink group",
|
||||
titleRequired: "Task name is required",
|
||||
portsRequired: "Select at least one interface",
|
||||
interval: "Interval (sec)",
|
||||
|
|
@ -2450,7 +2531,7 @@ const en = {
|
|||
sourceTopology: "Topology placeholder",
|
||||
sourceWebcrt: "WebCRT",
|
||||
regexTitle: "Regex find",
|
||||
patternPh: "Regex, e.g. ^CORE- or -BJ-",
|
||||
patternPh: "Regex, e.g. ^CORE- or -EDGE-",
|
||||
fieldName: "Name",
|
||||
fieldNameIp: "Name+IP",
|
||||
findMatches: "Find matches",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue