106 lines
2.7 KiB
Go
106 lines
2.7 KiB
Go
package workflow
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"auto-check/pkg/config"
|
||
"auto-check/pkg/discovery"
|
||
"auto-check/pkg/report"
|
||
"auto-check/pkg/stress"
|
||
)
|
||
|
||
// Workflow 固定工作流:扫描 → 压测 → 打印状态,按间隔循环
|
||
// 状态数据由各包自持(discovery/stress/report),workflow 直接调用其包级函数
|
||
type Workflow struct {
|
||
cfg config.Config
|
||
base context.Context
|
||
cancel context.CancelFunc
|
||
}
|
||
|
||
// New 创建工作流
|
||
func New(cfg config.Config) *Workflow {
|
||
base, cancel := context.WithCancel(context.Background())
|
||
return &Workflow{cfg: cfg, base: base, cancel: cancel}
|
||
}
|
||
|
||
// Start 启动固定工作流循环(永久运行,直至取消)
|
||
func (w *Workflow) Start() error {
|
||
interval := w.cfg.Workflow.Interval
|
||
if interval <= 0 {
|
||
interval = 10 * time.Second
|
||
}
|
||
|
||
fmt.Printf("══ 工作流启动(间隔 %v,设备以 IP 为 key)══\n\n", interval)
|
||
w.round() // 首轮立即执行
|
||
|
||
ticker := time.NewTicker(interval)
|
||
defer ticker.Stop()
|
||
|
||
for {
|
||
select {
|
||
case <-w.base.Done():
|
||
fmt.Println("══ 工作流已停止 ══")
|
||
return nil
|
||
case <-ticker.C:
|
||
w.round()
|
||
}
|
||
}
|
||
}
|
||
|
||
// Stop 停止工作流
|
||
func (w *Workflow) Stop() {
|
||
w.cancel()
|
||
}
|
||
|
||
// round 单轮:扫描 → 压测 → 打印状态变化
|
||
func (w *Workflow) round() {
|
||
fmt.Printf("════ 轮次开始 [%s] ════\n", time.Now().Format("15:04:05"))
|
||
|
||
// 1. 扫描(discovery 包),更新设备表
|
||
cfg := w.cfg
|
||
discovery.NewScanner(cfg.Scan.CIDR, cfg.Scan.Timeout, cfg.Scan.Concurrency).Discover()
|
||
fmt.Printf(" [扫描] 设备 %d 台\n", len(discovery.Devices))
|
||
|
||
// 2. 压测未通过设备(stress.TestDevice 执行,report 保存+打印)
|
||
for ip, dev := range discovery.Devices {
|
||
if stress.IsPassed(stress.Results[ip]) {
|
||
continue // 已通过,跳过
|
||
}
|
||
fmt.Printf(" [测试] %s (%s) 开始压测...\n", ip, dev.MAC)
|
||
rpt := stress.TestDevice(ip, w.cfg)
|
||
stress.Results[ip] = rpt
|
||
if stress.IsSSHFail(rpt) {
|
||
fmt.Printf(" [测试] %s SSH 连接失败,跳过报告输出: %s\n", ip, rpt.Results[0].Error)
|
||
continue
|
||
}
|
||
report.SaveAndPrintDeviceReport(&dev, rpt, cfg.Report.Path, cfg.Report.Print, cfg.Report.HTML)
|
||
}
|
||
|
||
// 3. 打印状态变化(首次或与上次不一致)
|
||
for ip, rpt := range stress.Results {
|
||
dev, ok := discovery.Devices[ip]
|
||
if !ok {
|
||
continue // 设备本轮缺席,状态保留等它回来
|
||
}
|
||
status := stress.Status(rpt)
|
||
if prev, ok := report.Printed[ip]; !ok || prev != status {
|
||
fmt.Printf(" [状态] %s %s → %s\n", dev.Label(), statusIcon(status), status)
|
||
report.Printed[ip] = status
|
||
}
|
||
}
|
||
}
|
||
|
||
// statusIcon 图标
|
||
func statusIcon(s string) string {
|
||
switch s {
|
||
case "pass":
|
||
return "✓"
|
||
case "fail":
|
||
return "✗"
|
||
default:
|
||
return "○"
|
||
}
|
||
}
|