163 lines
3.5 KiB
Go
163 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"474420502.top/eson/requests"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type DIPWorker struct {
|
|
ForMatch map[string]*DIPGroup `yaml:"switch"`
|
|
ForLoop map[string]*DIPGroup
|
|
Restart int64 `yaml:"restart"`
|
|
Mutex *sync.Mutex
|
|
}
|
|
|
|
// ShowGroupInfo 展示实时的 Group 信息动态
|
|
func (worker *DIPWorker) ShowGroupInfo() string {
|
|
|
|
now := time.Now().Unix()
|
|
|
|
content := ""
|
|
for addr, group := range worker.ForLoop {
|
|
content += addr + ": ["
|
|
for _, dhost := range group.Group {
|
|
|
|
overtimeLabel := ""
|
|
if now-dhost.ActiveTime >= 150 {
|
|
overtimeLabel = "<☠?>"
|
|
}
|
|
tm := time.Unix(dhost.ActiveTime, 0)
|
|
tm.Format("2006-01-02 15:04:05") //2018-07-11 15:10:19
|
|
content += dhost.Host + "(" + tm.Format("2006-01-02 15:04:05") + overtimeLabel + "),"
|
|
}
|
|
content = strings.TrimRight(content, ",") + "]\n"
|
|
}
|
|
content = strings.TrimRight(content, "\n")
|
|
return content
|
|
}
|
|
|
|
type DIPGroup struct {
|
|
Group map[string]*DHost // 原始参照
|
|
Waitor map[string]*DHost
|
|
Ready map[string]*DHost
|
|
IPTableNum string
|
|
Current *DHost
|
|
|
|
Mutex *sync.Mutex
|
|
}
|
|
|
|
func NewDIPGroup() *DIPGroup {
|
|
group := DIPGroup{}
|
|
group.Group = make(map[string]*DHost)
|
|
group.Waitor = make(map[string]*DHost)
|
|
group.Ready = make(map[string]*DHost)
|
|
group.Mutex = &sync.Mutex{}
|
|
return &group
|
|
}
|
|
|
|
// Choose 选择一个正在准备的vps节点
|
|
func (group *DIPGroup) Choose(addr string) {
|
|
now := time.Now().Unix()
|
|
for ip, dhost := range group.Ready {
|
|
// 设置转换的iptable
|
|
if group.Current == nil {
|
|
group.Current = dhost
|
|
group.Current.ActiveTime = now
|
|
SetAddrForward(group.IPTableNum, addr, ip)
|
|
} else {
|
|
restartAddr := "http://" + group.Current.Host + ":8800/pppoe/restart"
|
|
if _, err := requests.NewSession().Get(restartAddr).Execute(); err != nil {
|
|
log.Println(err)
|
|
group.Current.ActiveTime += 12
|
|
} else {
|
|
group.Current = dhost
|
|
group.Current.ActiveTime = now
|
|
// log.Println("new set addr:", group.Current.Host, "restartAddr:", restartAddr, "resp", resp.Content())
|
|
SetAddrForward(group.IPTableNum, addr, ip)
|
|
}
|
|
}
|
|
|
|
group.Waitor[ip] = group.Ready[ip]
|
|
delete(group.Ready, ip)
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
type DHost struct {
|
|
Host string
|
|
ActiveTime int64
|
|
}
|
|
|
|
func NewDHost(host string) *DHost {
|
|
dh := DHost{}
|
|
dh.ActiveTime = time.Now().Unix()
|
|
dh.Host = host
|
|
return &dh
|
|
}
|
|
|
|
func (dh *DHost) OverTime(now int64, limit int64) int64 {
|
|
if now-dh.ActiveTime >= limit {
|
|
return now - dh.ActiveTime
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (dip *DIPWorker) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
var data map[string]interface{}
|
|
if err := unmarshal(&data); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(data["switch"])
|
|
myswitch := data["switch"]
|
|
|
|
dip.Restart = int64(data["restart"].(int))
|
|
|
|
num := 1
|
|
for k, v := range myswitch.(map[interface{}]interface{}) {
|
|
|
|
group := NewDIPGroup()
|
|
|
|
// sudo iptables -t nat -R IPSWITCH 1 -p icmp -j DNAT --to 1.1.1.1:8885
|
|
for _, host := range v.([]interface{}) {
|
|
dhost := NewDHost(host.(string))
|
|
group.Group[dhost.Host] = dhost
|
|
dip.ForMatch[dhost.Host] = group
|
|
}
|
|
|
|
dip.ForLoop[k.(string)] = group
|
|
group.IPTableNum = strconv.Itoa(num)
|
|
num++
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// NewDipWorker 创建一个
|
|
func NewDipWorker(filename string) *DIPWorker {
|
|
worker := DIPWorker{}
|
|
worker.ForMatch = make(map[string]*DIPGroup)
|
|
worker.ForLoop = make(map[string]*DIPGroup)
|
|
|
|
worker.Mutex = &sync.Mutex{}
|
|
|
|
data, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = yaml.Unmarshal(data, &worker)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return &worker
|
|
}
|