Commit 4f71da27 authored by duanjinfei's avatar duanjinfei

Init commit

parents
.idea
logs
go.sum
nohup.out
package appNodeInterface
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"schedulerNode/log"
"schedulerNode/models"
)
var client *http.Client
func init() {
client = &http.Client{}
}
func SendSignallingInfo(ip, port string, req *models.SendSignallingReq) *models.AppNodeResponse {
reqBody, err := json.Marshal(req)
if err != nil {
log.Error("json marshal sendSignallingReq failed ", err)
return nil
}
url := fmt.Sprintf("http://%s:%s%s", ip, port, "/v1/connectSignalling")
request, err := http.NewRequest("POST", url, bytes.NewReader(reqBody))
if err != nil {
log.Error("Error connectSignalling request ", err)
return nil
}
resp, err := client.Do(request)
if err != nil {
log.Error("Error sending", err)
return nil
}
appNodeResp := &models.AppNodeResponse{}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("Error reading response body", err)
return nil
}
err = json.Unmarshal(respBody, appNodeResp)
if err != nil {
log.Error("Unmarshal error: ", err)
return nil
}
return appNodeResp
}
func GetSignallingConnectStatus(ip, port string) *models.SignallingConnectStatus {
url := fmt.Sprintf("http://%s:%s%s", ip, port, "/v1/signalStatus")
request, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Error("GetSignallingConnectStatus Error new request: ", err)
return nil
}
resp, err := client.Do(request)
if err != nil {
log.Error("GetSignallingConnectStatus send request error: ", err)
return nil
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("GetSignallingConnectStatus read resp body error: ", err)
return nil
}
res := &models.SignallingConnectStatus{}
err = json.Unmarshal(respBody, &res)
if err != nil {
log.Error("GetSignallingConnectStatus json unmarshal error:", err)
return nil
}
return res
}
package nodeCommon
const (
SuccessCode = 200
FaileCode = 500
)
appname = schedulerNode
httpport = 8080
runmode = dev
autorender = false
copyrequestbody = true
distance = 1000
local_ip = 192.168.1.100
[chain]
rpcUrl = "http://124.193.167.71:7545"
[contract_address]
app_contract = "0xD42c37fe44f1a0e7CA50B8bf5a5Bb96747C73aAb"
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type BaseController struct {
beego.Controller
}
func (d *BaseController) ResponseInfo(code int, msg interface{}, result interface{}) {
switch code {
case 500:
logs.Error(msg, result)
d.Data["json"] = map[string]interface{}{"code": "500", "msg": msg, "data": result}
case 200:
logs.Info(msg, result)
d.Data["json"] = map[string]interface{}{"code": "200", "msg": msg, "data": result}
}
d.ServeJSON()
}
package controllers
import (
"encoding/json"
"github.com/astaxie/beego"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"math/big"
"schedulerNode/appNodeInterface"
nodeCommon "schedulerNode/common"
application "schedulerNode/contract/go_file"
"schedulerNode/log"
"schedulerNode/models"
"schedulerNode/utils"
"strings"
)
type SignalingController struct {
BaseController
}
func (c *SignalingController) GetConnectSignalingStatus() {
// TODO: 获取前端传入的ExternalIp 以及 Port
body := c.Ctx.Input.RequestBody
signallingStatus := models.SignallingConnectStatusReq{}
err := json.Unmarshal(body, &signallingStatus)
if err != nil {
c.ResponseInfo(500, "Error unmarshalling", err)
return
}
rpcUrl := beego.AppConfig.String("chain::rpcUrl")
appContract := beego.AppConfig.String("contract_address::app_contract")
client, err := ethclient.Dial(rpcUrl)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error connecting", err)
}
defer client.Close()
appContractAddr := common.HexToAddress(appContract)
applicationInstance, err := application.NewApplication(appContractAddr, client)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error creating application", err)
}
network, err := applicationInstance.GetNodeNetwork(&bind.CallOpts{}, signallingStatus.NodeId)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error get NodeNetwork application", err)
}
// TODO: 调用App节点接口获取连接信令状态
statusResp := appNodeInterface.GetSignallingConnectStatus(network.ExternalIp, network.ServerPort)
if !statusResp.Status || statusResp.Code != nodeCommon.SuccessCode {
c.ResponseInfo(nodeCommon.SuccessCode, "disconnected", nil)
}
c.ResponseInfo(nodeCommon.SuccessCode, "success", nil)
}
func (c *SignalingController) GetAppNodeInfo() {
body := c.Ctx.Input.RequestBody
connectAppReq := &models.ConnectAppReq{}
err := json.Unmarshal(body, connectAppReq)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error unmarshalling", err)
}
rpcUrl := beego.AppConfig.String("chain::rpcUrl")
appContract := beego.AppConfig.String("contract_address::app_contract")
client, err := ethclient.Dial(rpcUrl)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error connecting", err)
}
defer client.Close()
// TODO 获取全部的节点Id
appContractAddr := common.HexToAddress(appContract)
applicationInstance, err := application.NewApplication(appContractAddr, client)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error creating application", err)
}
nodeIds, err := applicationInstance.GetNodeIds(&bind.CallOpts{}, connectAppReq.AppId, 0, 100)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error GetNodeIds ", err)
}
if len(nodeIds) == 0 {
c.ResponseInfo(nodeCommon.SuccessCode, "There is currently no node provided to launch the application", nil)
}
nodeNetworkInfo := models.AppNodeNetworkInfo{}
// TODO 通过节点ID获取网络信息
for _, nodeId := range nodeIds {
network, err := applicationInstance.GetNodeNetwork(&bind.CallOpts{}, nodeId)
if err != nil {
c.ResponseInfo(nodeCommon.FaileCode, "Error GetAppNodeNetwork ", err)
}
//if i == len(nodeIds)-1 {
if utils.IsCreateVmCondition(network.ExternalIp) {
nodeNetworkInfo.NodeId = nodeId
nodeNetworkInfo.ExternalIp = network.ExternalIp
nodeNetworkInfo.ServerPort = network.ServerPort
nodeNetworkInfo.StunIp = network.StunIp
nodeNetworkInfo.TurnIp = network.TurnIp
nodeNetworkInfo.TurnUser = network.TurnUser
nodeNetworkInfo.TurnPwd = network.TurnPwd
nodeNetworkInfo.SignallingHttpIp = network.SignallingHttpIp
nodeNetworkInfo.SignallingWsIp = network.SignallingWsIp
break
}
//}
}
// TODO 如果没有对应的服务信息
updateServerInfo(&nodeNetworkInfo)
// TODO 通知应用节点连接信令节点
sendSignallingReq := handlerSendSignallingInfo(&nodeNetworkInfo)
rep := appNodeInterface.SendSignallingInfo(nodeNetworkInfo.ExternalIp, nodeNetworkInfo.ServerPort, sendSignallingReq)
if rep.Code != nodeCommon.SuccessCode {
log.Error("Error sending signalling information failed", rep.Msg)
c.ResponseInfo(nodeCommon.FaileCode, "Notice signalling information failed", rep.Msg)
}
// TODO: 反馈前端信息
res := models.AppNodeInfoRep{
NodeID: nodeNetworkInfo.NodeId,
ExternalIp: nodeNetworkInfo.ExternalIp,
StunIp: nodeNetworkInfo.StunIp,
SignallingHttpIp: nodeNetworkInfo.SignallingHttpIp,
SignallingWsIp: nodeNetworkInfo.SignallingWsIp,
}
turnInfoArr := make([]*models.TurnInfo, 0)
for i := 0; i < len(nodeNetworkInfo.TurnIp); i++ {
turnInfo := &models.TurnInfo{
TurnIp: nodeNetworkInfo.TurnIp[i],
User: nodeNetworkInfo.TurnUser[i],
Pwd: nodeNetworkInfo.TurnPwd[i],
}
turnInfoArr = append(turnInfoArr, turnInfo)
}
res.TurnInfo = turnInfoArr
c.ResponseInfo(nodeCommon.SuccessCode, "success", res)
}
func handlerSendSignallingInfo(nodeNetworkInfo *models.AppNodeNetworkInfo) *models.SendSignallingReq {
signallingHttpIpInfo := nodeNetworkInfo.SignallingHttpIp
signallingHttpIpPort := strings.Split(signallingHttpIpInfo, ":")
signallingHttpPort, _ := new(big.Int).SetString(signallingHttpIpPort[1], 10)
signallingWsInfo := nodeNetworkInfo.SignallingWsIp
signallingWsIpPort := strings.Split(signallingWsInfo, ":")
signallingWsPort, _ := new(big.Int).SetString(signallingWsIpPort[1], 10)
turnInfoReqArr := make([]*models.TurnInfoReq, 0)
for i := 0; i < len(nodeNetworkInfo.TurnIp); i++ {
turnInfoReq := &models.TurnInfoReq{
Url: nodeNetworkInfo.TurnIp[i],
UserName: nodeNetworkInfo.TurnUser[i],
Credential: nodeNetworkInfo.TurnPwd[i],
}
turnInfoReqArr = append(turnInfoReqArr, turnInfoReq)
}
sendSignallingReq := &models.SendSignallingReq{
MQTTConnectInfo: &models.MQTTConnectInfo{
Broker: signallingHttpIpPort[0],
Port: signallingHttpPort,
WsPort: signallingWsPort,
},
ICEConnectInfo: &models.ICEConnectInfo{
Stuns: nodeNetworkInfo.StunIp,
Turns: turnInfoReqArr,
},
}
return sendSignallingReq
}
func updateServerInfo(info *models.AppNodeNetworkInfo) {
// TODO: 获取网关合约提供的服务信息
if len(info.TurnIp) == 0 {
}
if len(info.StunIp) == 0 {
}
if info.SignallingHttpIp == "" && info.SignallingWsIp == "" {
}
log.Info("updateServer", info.ExternalIp)
}
module schedulerNode
go 1.19
require github.com/astaxie/beego v1.12.1
require (
github.com/ethereum/go-ethereum v1.13.3
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/oschwald/geoip2-golang v1.9.0
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.9.3
github.com/smartystreets/goconvey v1.6.4
)
require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/bits-and-blooms/bitset v1.5.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.10.0 // indirect
github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum/c-kzg-4844 v0.3.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-ole/go-ole v1.2.5 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
package log
import (
"context"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"os"
"path"
"time"
)
var (
mlog = logrus.New()
)
type LogConfig struct {
Save uint `json:"save"`
Path string `json:"path"`
Level string `json:"level"`
}
func InitLog(logConfig LogConfig) {
mlog.Out = os.Stdout
var loglevel logrus.Level
err := loglevel.UnmarshalText([]byte(logConfig.Level))
if err != nil {
mlog.Panicf("set log level failed: %v", err)
}
mlog.SetLevel(loglevel)
mlog.Formatter = &logrus.TextFormatter{FullTimestamp: true, TimestampFormat: "2006-01-2 15:04:05.000"}
localFilesystemLogger(mlog, logConfig.Path, logConfig.Save)
}
func logWriter(logPath string, level string, save uint) *rotatelogs.RotateLogs {
logFullPath := path.Join(logPath, level)
logWriter, err := rotatelogs.New(
logFullPath+".%Y%m%d",
rotatelogs.WithLinkName(logFullPath),
rotatelogs.WithRotationCount(save),
rotatelogs.WithRotationTime(24*time.Hour),
)
if err != nil {
panic(err)
}
return logWriter
}
func localFilesystemLogger(log *logrus.Logger, logPath string, save uint) {
lfHook := lfshook.NewHook(lfshook.WriterMap{
logrus.DebugLevel: logWriter(logPath, "debug", save), // 为不同级别设置不同的输出目的
logrus.InfoLevel: logWriter(logPath, "info", save),
logrus.WarnLevel: logWriter(logPath, "warn", save),
logrus.ErrorLevel: logWriter(logPath, "error", save),
logrus.FatalLevel: logWriter(logPath, "fatal", save),
logrus.PanicLevel: logWriter(logPath, "panic", save),
}, &logrus.TextFormatter{FullTimestamp: true, TimestampFormat: "2006-01-2 15:04:05.000"})
log.AddHook(lfHook)
}
// WithField allocates a new entry and adds a field to it.
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
// this new returned entry.
// If you want multiple fields, use `WithFields`.
func WithField(key string, value interface{}) *logrus.Entry {
return mlog.WithField(key, value)
}
// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func WithFields(fields logrus.Fields) *logrus.Entry {
return mlog.WithFields(fields)
}
// Add an error as single field to the log entry. All it does is call
// `WithError` for the given `error`.
func WithError(err error) *logrus.Entry {
return mlog.WithError(err)
}
// Add a context to the log entry.
func WithContext(ctx context.Context) *logrus.Entry {
return mlog.WithContext(ctx)
}
// Overrides the time of the log entry.
func WithTime(t time.Time) *logrus.Entry {
return mlog.WithTime(t)
}
func Logf(level logrus.Level, format string, args ...interface{}) {
mlog.Logf(level, format, args...)
}
func Tracef(format string, args ...interface{}) {
mlog.Tracef(format, args...)
}
func Debugf(format string, args ...interface{}) {
mlog.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) {
mlog.Infof(format, args...)
}
func Printf(format string, args ...interface{}) {
mlog.Printf(format, args...)
}
func Warnf(format string, args ...interface{}) {
mlog.Warnf(format, args...)
}
func Warningf(format string, args ...interface{}) {
mlog.Warningf(format, args...)
}
func Errorf(format string, args ...interface{}) {
mlog.Errorf(format, args)
}
func Fatalf(format string, args ...interface{}) {
mlog.Fatalf(format, args...)
}
func Panicf(format string, args ...interface{}) {
mlog.Panicf(format, args...)
}
func Log(level logrus.Level, args ...interface{}) {
mlog.Log(level, args...)
}
func LogFn(level logrus.Level, fn logrus.LogFunction) {
mlog.LogFn(level, fn)
}
func Trace(args ...interface{}) {
mlog.Trace(args...)
}
func Debug(args ...interface{}) {
mlog.Debug(args...)
}
func Info(args ...interface{}) {
mlog.Info(args...)
}
func Print(args ...interface{}) {
mlog.Print(args...)
}
func Warn(args ...interface{}) {
mlog.Warn(args...)
}
func Warning(args ...interface{}) {
mlog.Warning(args...)
}
func Error(args ...interface{}) {
mlog.Error(args...)
}
func Fatal(args ...interface{}) {
mlog.Fatal(args...)
}
func Panic(args ...interface{}) {
mlog.Panic(args...)
}
func TraceFn(fn logrus.LogFunction) {
mlog.TraceFn(fn)
}
func DebugFn(fn logrus.LogFunction) {
mlog.DebugFn(fn)
}
func InfoFn(fn logrus.LogFunction) {
mlog.InfoFn(fn)
}
func PrintFn(fn logrus.LogFunction) {
mlog.PrintFn(fn)
}
func WarnFn(fn logrus.LogFunction) {
mlog.WarnFn(fn)
}
func WarningFn(fn logrus.LogFunction) {
mlog.WarningFn(fn)
}
func ErrorFn(fn logrus.LogFunction) {
mlog.ErrorFn(fn)
}
func FatalFn(fn logrus.LogFunction) {
mlog.FatalFn(fn)
}
func PanicFn(fn logrus.LogFunction) {
mlog.PanicFn(fn)
}
func Logln(level logrus.Level, args ...interface{}) {
mlog.Logln(level, args...)
}
func Traceln(args ...interface{}) {
mlog.Traceln(args...)
}
func Debugln(args ...interface{}) {
mlog.Debugln(args...)
}
func Infoln(args ...interface{}) {
mlog.Infoln(args...)
}
func Println(args ...interface{}) {
mlog.Println(args...)
}
func Warnln(args ...interface{}) {
mlog.Warnln(args...)
}
func Warningln(args ...interface{}) {
mlog.Warningln(args...)
}
func Errorln(args ...interface{}) {
mlog.Errorln(args...)
}
func Fatalln(args ...interface{}) {
mlog.Fatalln(args...)
}
func Panicln(args ...interface{}) {
mlog.Panicln(args...)
}
package main
import (
"github.com/astaxie/beego"
"schedulerNode/log"
"schedulerNode/middleware"
_ "schedulerNode/routers"
)
func main() {
beego.InsertFilter("*", beego.BeforeRouter, middleware.CorsMiddleware)
log.InitLog(log.LogConfig{Path: "logs", Level: "debug", Save: 3})
beego.Run()
}
package middleware
import "github.com/astaxie/beego/context"
func CorsMiddleware(ctx *context.Context) {
// 设置允许跨域的域名
ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
// 允许的方法
ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
// 允许的请求标头
ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type")
// 允许跨域 cookie 传递
ctx.ResponseWriter.Header().Set("Access-Control-Allow-Credentials", "true")
// 预检请求的处理
if ctx.Input.Method() == "OPTIONS" {
ctx.ResponseWriter.Header().Set("Access-Control-Max-Age", "86400") // 预检请求结果的缓存时间,单位秒
ctx.ResponseWriter.WriteHeader(200)
}
}
package models
type AppNodeNetworkInfo struct {
NodeId string
ExternalIp string
ServerPort string
StunIp []string
TurnIp []string
TurnUser []string
TurnPwd []string
SignallingHttpIp string
SignallingWsIp string
}
type TurnInfo struct {
TurnIp string
User string
Pwd string
}
package models
import "math/big"
type SignallingConnectStatusReq struct {
NodeId string `json:"nodeId"`
}
type ConnectAppReq struct {
AppId string `json:"appId"`
}
type SendSignallingReq struct {
MQTTConnectInfo *MQTTConnectInfo `json:"MQTTConnectInfo"`
ICEConnectInfo *ICEConnectInfo `json:"ICEConnectInfo"`
}
type MQTTConnectInfo struct {
Broker string `json:"broker"`
Port *big.Int `json:"port"`
WsPort *big.Int `json:"ws_port"`
}
type ICEConnectInfo struct {
Stuns []string `json:"stuns"`
Turns []*TurnInfoReq `json:"turns"`
}
type TurnInfoReq struct {
Url string `json:"url"`
UserName string `json:"username"`
Credential string `json:"credential"`
}
package models
type AppNodeInfoRep struct {
NodeID string `json:"nodeID"`
ExternalIp string `json:"externalIp"`
StunIp []string `json:"stunIp"`
TurnInfo []*TurnInfo `json:"turnInfo"`
SignallingHttpIp string `json:"signallingHttpIp"`
SignallingWsIp string `json:"signallingWsIp"`
}
type SignallingConnectStatusRep struct {
Status string `json:"status"`
}
type AppNodeResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
type SignallingConnectStatus struct {
Code int `json:"code"`
Status bool `json:"status"`
}
package routers
import (
"github.com/astaxie/beego"
"schedulerNode/controllers"
)
func init() {
beego.Router("/api/v1/connect/app", &controllers.SignalingController{}, "post:GetAppNodeInfo")
beego.Router("/api/v1/get/connectStatus", &controllers.SignalingController{}, "post:GetConnectSignalingStatus")
}
package test
import (
"net/http"
"net/http/httptest"
"path/filepath"
"runtime"
_ "schedulerNode/routers"
"testing"
"github.com/astaxie/beego"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
_, file, _, _ := runtime.Caller(0)
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
beego.TestBeegoInit(apppath)
}
// TestBeego is a sample to run an endpoint test
func TestBeego(t *testing.T) {
r, _ := http.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
beego.BeeApp.Handlers.ServeHTTP(w, r)
beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())
Convey("Subject: Test Station Endpoint\n", t, func() {
Convey("Status Code Should Be 200", func() {
So(w.Code, ShouldEqual, 200)
})
Convey("The Result Should Not Be Empty", func() {
So(w.Body.Len(), ShouldBeGreaterThan, 0)
})
})
}
package utils
import (
"fmt"
"github.com/astaxie/beego"
"github.com/oschwald/geoip2-golang"
"math"
"net"
"schedulerNode/log"
)
// EarthRadius 地球半径(单位:千米)
const EarthRadius = 6371
// Coordinates 经纬度坐标结构体
type Coordinates struct {
Latitude float64 // 纬度
Longitude float64 // 经度
}
// IsCreateVmCondition 本机是否符合创建Vm的要求
func IsCreateVmCondition(callerIp string) bool {
localIp := beego.AppConfig.String("local_ip")
distance := calculateDistance(getIpAddr(callerIp), getIpAddr(localIp))
settingDistance := beego.AppConfig.DefaultFloat("distance", 1000)
if distance <= settingDistance {
return true
}
return true
}
// 将角度转换为弧度
func degreesToRadians(degrees float64) float64 {
return degrees * (math.Pi / 180.0)
}
// CalculateDistance 计算两个经纬度坐标之间的距离(单位:千米)
func calculateDistance(coord1, coord2 *Coordinates) float64 {
lat1 := degreesToRadians(coord1.Latitude)
lat2 := degreesToRadians(coord2.Latitude)
lon1 := degreesToRadians(coord1.Longitude)
lon2 := degreesToRadians(coord2.Longitude)
// Haversine 公式
dlon := lon2 - lon1
dlat := lat2 - lat1
a := math.Pow(math.Sin(dlat/2), 2) + math.Cos(lat1)*math.Cos(lat2)*math.Pow(math.Sin(dlon/2), 2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
distance := EarthRadius * c
return distance
}
// GetIpAddr 获取Ip地址信息
func getIpAddr(ipAddress string) *Coordinates {
// 打开 MaxMind 的 GeoIP2 数据库文件
db, err := geoip2.Open("GeoLite2-City.mmdb")
if err != nil {
log.Error(" geoip2 open error:", err)
return nil
}
defer func(db *geoip2.Reader) {
err := db.Close()
if err != nil {
log.Error(" geoip2 close error:", err)
}
}(db)
// 解析 IP 地址
ip := net.ParseIP(ipAddress)
// 查询 IP 地址的位置信息
record, err := db.City(ip)
if err != nil {
log.Error("Get ip city error:", err)
return nil
}
// 打印经纬度信息
fmt.Printf("IP地址: %s\n", ipAddress)
fmt.Printf("经度: %f\n", record.Location.Longitude)
fmt.Printf("纬度: %f\n", record.Location.Latitude)
res := &Coordinates{
Latitude: record.Location.Latitude,
Longitude: record.Location.Longitude,
}
return res
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment