196 lines
5.2 KiB
Go
196 lines
5.2 KiB
Go
package actions
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"strconv"
|
|
"zzman/clients/jd"
|
|
"zzman/model"
|
|
u "zzman/util"
|
|
)
|
|
|
|
type UpdateArgs struct {
|
|
Mock bool
|
|
}
|
|
|
|
func Update(args ...UpdateArgs) error {
|
|
var tx = model.DB
|
|
var arg UpdateArgs
|
|
if len(args) > 0 {
|
|
arg = args[0]
|
|
} else {
|
|
arg.Mock = false
|
|
}
|
|
|
|
gateways, err := FindGateways(tx)
|
|
if err != nil {
|
|
return fmt.Errorf("获取所有网关失败:%w", err)
|
|
}
|
|
|
|
cities, err := FindCitiesWithEdgesCount(tx)
|
|
if err != nil {
|
|
return fmt.Errorf("获取所有城市失败:%w", err)
|
|
}
|
|
|
|
// 准备网关查找表,初始化网关配置表
|
|
type ConfigInfo struct {
|
|
Item jd.EdgeInfo
|
|
Type int // 0: 不变, 1: 更新, 2: 新增
|
|
}
|
|
var oldConfigsMap = make(map[model.Gateway]map[string]model.Config)
|
|
var newConfigs = make(map[model.Gateway][]ConfigInfo)
|
|
for _, gateway := range gateways {
|
|
newConfigs[gateway] = make([]ConfigInfo, len(cities))
|
|
|
|
oldConfigs, err := FindConfigsByGateway(tx, gateway.Macaddr)
|
|
if err != nil {
|
|
return fmt.Errorf("获取网关 %s 城市节点失败:%w", gateway.Macaddr, err)
|
|
}
|
|
|
|
oldConfigsMap[gateway] = make(map[string]model.Config)
|
|
for _, config := range oldConfigs {
|
|
oldConfigsMap[gateway][config.Cityhash] = config
|
|
}
|
|
}
|
|
|
|
// 按城市循环,对比并更新网关配置
|
|
for iCity, city := range cities {
|
|
|
|
// 如果每个网关在此城市都有节点且无需改变,就不需要从云端拉取城市节点信息
|
|
// 相当于直接重新提交配置,此流程下配置更新是幂等的
|
|
var gateways2Update []model.Gateway
|
|
for _, gateway := range gateways {
|
|
oldConfig, exists := oldConfigsMap[gateway][city.Hash]
|
|
if exists && oldConfig.IsChange != 1 {
|
|
newConfigs[gateway][iCity] = ConfigInfo{
|
|
Type: 0, // 不变
|
|
Item: jd.EdgeInfo{
|
|
Mac: oldConfig.Macaddr,
|
|
City: oldConfig.Cityhash,
|
|
},
|
|
}
|
|
} else {
|
|
gateways2Update = append(gateways2Update, gateway)
|
|
}
|
|
}
|
|
if len(gateways2Update) == 0 {
|
|
continue
|
|
}
|
|
|
|
// 否则,正常从云端拉取城市节点信息
|
|
offset := city.Offset
|
|
count := len(gateways2Update)
|
|
if count > city.EdgesCount {
|
|
slog.Warn("城市节点数量不足,跳过本次更新", "城市", city.Name, "节点数", city.EdgesCount, "网关数", count)
|
|
continue
|
|
}
|
|
|
|
if offset+count > city.EdgesCount {
|
|
slog.Debug("城市节点不足,将循环使用节点", "城市", city.Name, "节点数", city.EdgesCount, "网关数", count)
|
|
offset = 0
|
|
}
|
|
|
|
edges, err := SliceActiveEdgesByCity(tx, city.Id, offset, count)
|
|
if err != nil {
|
|
return fmt.Errorf("查询城市 %s 可用节点失败:%w", city.Name, err)
|
|
}
|
|
|
|
// 更新网关配置
|
|
var configs2Create []model.Config
|
|
var configs2Update []model.ConfigUpdate
|
|
|
|
for iGateway, gateway := range gateways2Update {
|
|
|
|
oldConfig, exists := oldConfigsMap[gateway][city.Hash]
|
|
newConfig := edges[iGateway]
|
|
|
|
if exists {
|
|
fmt.Printf("\t网关 %s 变更节点: %s -> %s\n", gateway.Macaddr, oldConfig.Macaddr, newConfig.Macaddr)
|
|
|
|
configs2Update = append(configs2Update, model.ConfigUpdate{
|
|
Id: oldConfig.Id,
|
|
Macaddr: u.P(oldConfig.Macaddr),
|
|
IsChange: u.P(0),
|
|
})
|
|
|
|
newConfigs[gateway][iCity] = ConfigInfo{
|
|
Type: 1, // 更新
|
|
Item: jd.EdgeInfo{
|
|
Mac: oldConfig.Macaddr,
|
|
City: city.Hash,
|
|
},
|
|
}
|
|
} else {
|
|
fmt.Printf("\t网关 %s 新增节点: %s\n", gateway.Macaddr, newConfig.Macaddr)
|
|
|
|
configs2Create = append(configs2Create, model.Config{
|
|
Cityhash: city.Hash,
|
|
CityLabel: city.Label,
|
|
GatewayMac: gateway.Macaddr,
|
|
Macaddr: newConfig.Macaddr,
|
|
Table: strconv.Itoa(iCity + 1),
|
|
User: fmt.Sprintf("jdzz%ddt%d", iGateway+1, iCity+1),
|
|
Network: fmt.Sprintf("172.30.168.%d", iCity+2),
|
|
InnerIp: fmt.Sprintf("172.16.%d.%d", iGateway+1, iCity+2),
|
|
})
|
|
|
|
newConfigs[gateway][iCity] = ConfigInfo{
|
|
Type: 2, // 新增
|
|
Item: jd.EdgeInfo{
|
|
Mac: oldConfig.Macaddr,
|
|
City: city.Hash,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
err = CreateConfigs(tx, configs2Create)
|
|
if err != nil {
|
|
return fmt.Errorf("创建新配置失败:%w", err)
|
|
}
|
|
err = UpdateConfigs(tx, configs2Update)
|
|
if err != nil {
|
|
return fmt.Errorf("更新配置失败:%w", err)
|
|
}
|
|
err = AppendCityOffset(tx, city.Id, offset+count)
|
|
if err != nil {
|
|
return fmt.Errorf("更新城市 %s 的偏移量失败:%w", city.Name, err)
|
|
}
|
|
}
|
|
|
|
// 提交所有网关配置到云端
|
|
for gateway, infos := range newConfigs {
|
|
change := 0
|
|
setup := 0
|
|
edges := make([]jd.EdgeInfo, len(infos))
|
|
for i, info := range infos {
|
|
edges[i] = info.Item
|
|
switch info.Type {
|
|
case 1:
|
|
change++
|
|
case 2:
|
|
setup++
|
|
}
|
|
}
|
|
fmt.Printf("提交网关 %s 配置: %d 变更, %d 新增\n", gateway.Macaddr, change, setup)
|
|
|
|
// 提交配置到云端:配置版本 gateway.ConfigVersion
|
|
if arg.Mock {
|
|
fmt.Printf("[MOCK] 配置网关 %s:\n%v\n", gateway.Macaddr, edges)
|
|
} else {
|
|
err := jd.GatewayConfigSet(gateway.ConfigVersion, gateway.Macaddr, edges)
|
|
if err != nil {
|
|
return fmt.Errorf("配置网关 %s 失败:%w", gateway.Macaddr, err)
|
|
}
|
|
}
|
|
|
|
// 更新配置版本
|
|
err = AppendGatewayConfigVersion(tx, gateway.Id)
|
|
if err != nil {
|
|
return fmt.Errorf("更新网关 %s 配置版本失败:%w", gateway.Macaddr, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|