ipcenter/dip.go

197 lines
4.4 KiB
Go
Raw Normal View History

2018-12-16 18:58:52 +00:00
package main
import (
"io/ioutil"
"log"
"strconv"
"strings"
"sync"
"time"
2018-12-17 18:53:09 +00:00
"474420502.top/eson/requests"
2018-12-16 18:58:52 +00:00
"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)
2018-12-24 08:58:01 +00:00
// tm.Format(time.RFC3339) //2018-07-11 15:10:19
content += dhost.Host + "(" + tm.Format(time.RFC3339) + overtimeLabel + "),"
2018-12-16 18:58:52 +00:00
}
content = strings.TrimRight(content, ",") + "]\n"
}
content = strings.TrimRight(content, "\n")
return content
}
2018-12-24 08:58:01 +00:00
// DIPGroup 动态ip组, 一个组指的是一条可动态切换的线
2018-12-16 18:58:52 +00:00
type DIPGroup struct {
Group map[string]*DHost // 原始参照
2018-12-16 19:22:25 +00:00
Waitor map[string]*DHost
2018-12-16 18:58:52 +00:00
Ready map[string]*DHost
IPTableNum string
Current *DHost
2018-12-17 02:25:09 +00:00
City string
2018-12-16 18:58:52 +00:00
Mutex *sync.Mutex
}
2018-12-24 08:58:01 +00:00
// NewDIPGroup 创建一个,动态ip组, 一个组指的是一条可动态切换的线
2018-12-16 18:58:52 +00:00
func NewDIPGroup() *DIPGroup {
group := DIPGroup{}
group.Group = make(map[string]*DHost)
2018-12-16 19:22:25 +00:00
group.Waitor = make(map[string]*DHost)
2018-12-16 18:58:52 +00:00
group.Ready = make(map[string]*DHost)
group.Mutex = &sync.Mutex{}
return &group
}
2018-12-16 19:22:25 +00:00
// Choose 选择一个正在准备的vps节点
2018-12-16 18:58:52 +00:00
func (group *DIPGroup) Choose(addr string) {
now := time.Now().Unix()
for ip, dhost := range group.Ready {
// 设置转换的iptable
if group.Current == nil {
2018-12-24 08:58:01 +00:00
log.Println(addr, " Current is nil")
2018-12-16 18:58:52 +00:00
} else {
2018-12-21 19:30:25 +00:00
2018-12-24 08:58:01 +00:00
i := 0
for ; i < 2; i++ {
2018-12-24 08:58:01 +00:00
imokURL := "http://" + dhost.Host + ":8800/pppoe/imok"
ses := requests.NewSession()
ses.SetConfig(requests.CRequestTimeout, 5)
2018-12-24 08:58:01 +00:00
if _, err := ses.Get(imokURL).Execute(); err != nil {
2018-12-21 19:30:25 +00:00
log.Println(err)
2018-12-24 08:58:01 +00:00
} else { // 如果ping 通下个切换的主机就切换
for ii := 0; ii < 3; ii++ {
restartURL := "http://" + group.Current.Host + ":8800/pppoe/restart"
if _, err := ses.Get(restartURL).Execute(); err != nil {
2018-12-24 08:58:01 +00:00
log.Println(err)
} else {
break // 可以切换 ii := 0; ii < 3; ii++
}
}
break // for ; i < 3; i++ {
2018-12-21 19:30:25 +00:00
}
2018-12-16 18:58:52 +00:00
}
2018-12-21 19:30:25 +00:00
2018-12-24 08:58:01 +00:00
if i == 3 {
// 下个需要切换的DHost错误
group.Current.ActiveTime = now + 15
2018-12-24 08:58:01 +00:00
delete(group.Ready, ip)
return // 不执行下面的 切换操作 for ip, dhost := range group.Ready
2018-12-24 08:58:01 +00:00
}
2018-12-21 19:30:25 +00:00
2018-12-16 18:58:52 +00:00
}
2018-12-24 08:58:01 +00:00
group.Current = dhost
group.Current.ActiveTime = now
SetAddrForward(group.IPTableNum, addr, ip)
2018-12-16 19:22:25 +00:00
group.Waitor[ip] = group.Ready[ip]
2018-12-16 18:58:52 +00:00
delete(group.Ready, ip)
2018-12-21 19:14:05 +00:00
return
2018-12-16 18:58:52 +00:00
}
}
2018-12-24 08:58:01 +00:00
// DHost 动态IP的一个vps
// Host vps的host属性 指定ip
// ActiveTime ActiveTime活跃时间
2018-12-16 18:58:52 +00:00
type DHost struct {
Host string
ActiveTime int64
}
2018-12-24 08:58:01 +00:00
// NewDHost 创建一个DHost host 为 ip
2018-12-16 18:58:52 +00:00
func NewDHost(host string) *DHost {
dh := DHost{}
dh.ActiveTime = time.Now().Unix()
dh.Host = host
return &dh
}
2018-12-24 08:58:01 +00:00
// OverTime dhost对比时间是否超过limit的限制, 超时判断
2018-12-16 19:22:25 +00:00
func (dh *DHost) OverTime(now int64, limit int64) int64 {
if now-dh.ActiveTime >= limit {
2018-12-17 02:25:09 +00:00
return 1
2018-12-16 18:58:52 +00:00
}
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()
2018-12-17 02:25:09 +00:00
addrmap := v.(map[interface{}]interface{})
2018-12-16 18:58:52 +00:00
// sudo iptables -t nat -R IPSWITCH 1 -p icmp -j DNAT --to 1.1.1.1:8885
2018-12-17 02:25:09 +00:00
city := addrmap["city"].(string)
group.City = city
for _, host := range addrmap["group"].([]interface{}) {
2018-12-16 18:58:52 +00:00
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
}