Commit f6c93ea5 authored by duanjinfei's avatar duanjinfei

init commit

parents
File added
.idea
logs
go.sum
nohup.out
package asyncLog
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"hashrateNode/cache"
hashrateCommon "hashrateNode/common"
vm "hashrateNode/contract/VmContract"
vmCreate "hashrateNode/contract/VmCreateContract"
"hashrateNode/log"
"hashrateNode/models"
"hashrateNode/pveApi"
"hashrateNode/utils"
"math/big"
"strconv"
"strings"
"time"
)
var tranOpts *bind.TransactOpts
var err error
var hostName, fromAddr string
var nonce uint64
func init() {
tranOpts, err = utils.GetTranOpts()
if err != nil {
log.Error("GetTranOpts error:", err)
return
}
hostName = beego.AppConfig.String("pve::host_name")
fromAddr = beego.AppConfig.String("sendTranAddress")
}
func VmCreateContractHandler(vLog types.Log) error {
logs.Info("handle vm create contract logs.")
stakeAbiInfo, _ := abi.JSON(strings.NewReader(vmCreate.VmCreateABI))
{
method := vLog.Topics[0]
switch method.String() {
case hashrateCommon.VmCreateEvent:
{
rp, err := stakeAbiInfo.Unpack("AddCreateVMInfoEvent", vLog.Data)
sockets, _ := new(big.Int).SetString(rp[4].(string), 10)
cores, _ := new(big.Int).SetString(rp[5].(string), 10)
gpuNum, _ := new(big.Int).SetString(rp[7].(string), 10)
memory, _ := new(big.Int).SetString(rp[8].(string), 10)
osType, _ := new(big.Int).SetString(rp[9].(string), 10)
vmCreateEvent := &models.VmConfig{
TaskId: rp[0].(string),
Owner: rp[1].(common.Address),
CallerIp: rp[2].(string),
Cpu: rp[3].(string),
Sockets: sockets,
Cores: cores,
Gpu: rp[6].(string),
GpuNum: gpuNum,
Memory: memory,
OsType: osType,
Disk: bighundred,
}
//vmCreateEvent := &models.VmConfig{}
//err = stakeAbiInfo.UnpackIntoInterface(vmCreateEvent, "AddCreateVMInfoEvent", vLog.Data)
if err != nil {
cache.Redis.LpushByte(hashrateCommon.EventList, utils.Marshal(vmCreateEvent))
}
if !IsCreateVmCondition(vmCreateEvent.CallerIp) {
return nil
}
isSnatch, err := snatchTask(vmCreateEvent)
if err != nil || !isSnatch {
return err
}
}
case hashrateCommon.VmStatusEvent:
{
vmStatusEvent := &models.VmStatusEvent{}
err = stakeAbiInfo.UnpackIntoInterface(vmStatusEvent, "VmStatusEvent", vLog.Data)
if err != nil {
cache.Redis.LpushByte(hashrateCommon.EventList, utils.Marshal(vmStatusEvent))
}
if vmStatusEvent.Progress.Int64() != bighundred.Int64() {
return nil
}
}
}
}
return nil
}
// IsCreateVmCondition 本机是否符合创建Vm的要求
func IsCreateVmCondition(callerIp string) bool {
localIp := beego.AppConfig.String("local_ip")
distance := utils.CalculateDistance(utils.GetIpAddr(callerIp), utils.GetIpAddr(localIp))
if distance <= 1000 {
return true
}
return true
}
// snatchTask 进行抢占任务
func snatchTask(vmCfg *models.VmConfig) (bool, error) {
rpcUrl := beego.AppConfig.String("chain_rpc_url")
client, err := ethclient.Dial(rpcUrl)
if err != nil {
log.Error("Eth client.Dial error:", err)
return false, err
}
defer client.Close()
nonce, err = utils.EthGetTransactionCount(client, fromAddr)
if err != nil {
return false, err
}
vmCreate, err := vmCreate.NewVmCreate(common.HexToAddress(hashrateCommon.VmCreateContract), client)
if err != nil {
log.Error("New vmCreate error:", err)
return false, err
}
// 查询 创建vm的操作系统对应的vmId
updateTranOptsNonce(0)
// 调用合约抢占任务
task, err := vmCreate.SnatchTask(tranOpts, vmCfg.TaskId, vmCfg.Owner)
if err != nil {
log.Error("SnatchTask error:", err)
return false, err
}
log.Info("SnatchTask success:", task.Hash())
ticket, err := pveApi.GetCreateVmTicket()
if err != nil {
return false, err
}
vmId, newId := getCloneVmInfo(vmCfg, ticket)
if vmId == "" || newId == "" {
return false, nil
}
user, password := generateUser()
vm := &models.VM{
VmId: vmId,
NewId: newId,
VmCfg: vmCfg,
Name: fmt.Sprintf("Clone%s", newId),
User: user,
Password: password,
HeaderInfo: ticket,
}
updateTranOptsNonce(1)
updateVmProgress(vmCreate, vm.VmCfg.TaskId, big.NewInt(1), bigTwenty)
// 创建VM、并且设置配置
_, err = pveApi.CreateVm(vm)
if err != nil {
return false, err
}
setRes, err := pveApi.SetVmConfig(vm)
if err != nil || setRes == nil {
return false, err
}
updateTranOptsNonce(1)
updateVmProgress(vmCreate, vm.VmCfg.TaskId, big.NewInt(2), bigThirty)
// 开启虚拟机
_, err = pveApi.StartVm(vm)
if err != nil {
return false, err
}
updateTranOptsNonce(1)
updateVmProgress(vmCreate, vm.VmCfg.TaskId, big.NewInt(3), bigForty)
// 轮训查询状态
for {
vmStatus, err := pveApi.VmStatus(vm)
if err != nil {
return false, err
}
if vmStatus.Status == hashrateCommon.Running {
updateTranOptsNonce(1)
updateVmProgress(vmCreate, vm.VmCfg.TaskId, big.NewInt(4), bigSixty)
break
}
time.Sleep(time.Second * 2)
}
time.Sleep(time.Second * 20)
netWorks, err := pveApi.GetVmNetWork(vm)
if err != nil {
return false, err
}
//loginUser, err := pveApi.SetVmLoginUser(vm)
//if err != nil {
// return false, err
//}
updateVmNetWorkInfo(client, netWorks, vm)
updateVmProgress(vmCreate, vm.VmCfg.TaskId, big.NewInt(5), bighundred)
return true, nil
}
// updateVmNetWorkInfo 更新vm的网络信息
func updateVmNetWorkInfo(client *ethclient.Client, networkInfos []*models.NetworkInfo, vmInfo *models.VM) {
internalIp := ""
for _, netWork := range networkInfos {
if netWork.Name == hashrateCommon.Ens18 {
for _, ipInfo := range netWork.IpAddresses {
if ipInfo.IpAddressType == hashrateCommon.Ipv4 {
internalIp = ipInfo.IpAddress
log.Info("internalIp:", internalIp)
break
}
}
}
}
if internalIp == "" {
log.Error("In networkInfo is not found ip info")
return
}
vmContract, err := vm.NewVm(common.HexToAddress(hashrateCommon.VmContract), client)
if err != nil {
return
}
// 调用NPS 映射外网ip
externalIp := internalIp
externalPort := "22"
vmId := new(big.Int)
vmId.SetString(vmInfo.NewId, 10)
updateTranOptsNonce(1)
addVirtualMachine, err := vmContract.AddVirtualMachine(tranOpts, vmInfo.VmCfg.Owner, vmInfo.VmCfg.TaskId, vmId, "", vmInfo.VmCfg.TaskId, hostName, vmInfo.Name, "ubuntu")
if err != nil {
return
}
log.Info("Add virtual machine success:", addVirtualMachine.Hash())
updateTranOptsNonce(1)
updateVmNetworkInfo, err := vmContract.UpdateVmNetworkInfo(tranOpts, vmId, "", externalIp, externalPort, "", "", "")
if err != nil {
return
}
log.Info("Update virtual machine networkInfo success:", updateVmNetworkInfo.Hash())
updateTranOptsNonce(1)
updateVMInfoEvent, err := vmContract.UpdateVMInfoEvent(tranOpts, vmId, vmInfo.VmCfg.Sockets.Uint64(), vmInfo.VmCfg.Memory.Uint64(), vmInfo.VmCfg.GpuNum.Uint64(), vmInfo.VmCfg.Disk)
if err != nil {
return
}
log.Info("Update virtual machine info success:", updateVMInfoEvent.Hash())
updateTranOptsNonce(1)
userTran, err := vmContract.AddVmUser(tranOpts, vmId, vmInfo.User, vmInfo.Password)
if err != nil {
log.Error("Add vm user error:", err)
return
}
log.Info("Update virtual machine info success:", userTran.Hash())
}
func generateUser() (string, string) {
return "cloud", "123456"
}
// getCloneVmInfo 获取能够克隆的vmId
func getCloneVmInfo(vmInfo *models.VmConfig, headerInfo *models.HeaderInfo) (string, string) {
qemuList, err := pveApi.GetQemuList(headerInfo)
if err != nil {
return "", ""
}
var maxVmId int64
for _, qemu := range qemuList {
if qemu.VmId > maxVmId {
maxVmId = qemu.VmId
}
}
maxVmId++
return "104", strconv.FormatInt(maxVmId, 10)
}
// updateVmProgress 更新vm的创建进度
func updateVmProgress(contractInstance *vmCreate.VmCreate, taskId string, stage *big.Int, progress *big.Int) bool {
task, err := contractInstance.UpdateVmCreateProgress(tranOpts, taskId, stage, progress)
if err != nil {
log.Error("UpdateVmCreateProgress error:", err)
return false
}
log.Info("Update vm create progress success:", task.Hash())
return true
}
func updateTranOptsNonce(incrementNum uint64) {
nonce += incrementNum
nonceUint64 := new(big.Int).SetUint64(nonce)
tranOpts.Nonce = nonceUint64
}
package asyncLog
import (
"context"
"fmt"
"github.com/astaxie/beego"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"hashrateNode/cache"
hashrateCommon "hashrateNode/common"
"hashrateNode/log"
"math/big"
"strings"
"time"
)
const (
LastSyncBlockKey = "lastSyncBlock"
)
var (
pullTask *PullEvent
bigOne = big.NewInt(1)
bigTen = big.NewInt(10)
bigTwenty = big.NewInt(20)
bigThirty = big.NewInt(30)
bigForty = big.NewInt(40)
bigFifty = big.NewInt(50)
bigSixty = big.NewInt(60)
bigSeventy = big.NewInt(70)
bigEighty = big.NewInt(80)
bigNinety = big.NewInt(90)
bighundred = big.NewInt(100)
bigK = big.NewInt(1000)
)
type logHandler func(log types.Log) error
type PullEvent struct {
ctx context.Context
client *ethclient.Client
lastBlock *big.Int
contractList []common.Address
contractHandler map[common.Address]logHandler
}
func init() {
var err error
rpc := beego.AppConfig.String("chain_rpc_url")
deployBlock := beego.AppConfig.String("deployedBlock")
log.Info("connect chain rpc url:", rpc)
pullTask = &PullEvent{contractHandler: make(map[common.Address]logHandler)}
client, err := ethclient.Dial(rpc)
if err != nil {
panic(fmt.Sprintf("ethclient dial failed, err:%s", err.Error()))
} else {
pullTask.client = client
lastBlock := cache.Redis.Get(LastSyncBlockKey)
if len(lastBlock) == 0 {
lastBlock = deployBlock
}
blockNumber, _ := new(big.Int).SetString(lastBlock, 10)
pullTask.lastBlock = blockNumber
}
pullTask.ctx = context.Background()
pullTask.contractList = make([]common.Address, 0)
{
vmCreateAddrArr := getAddress(hashrateCommon.VmCreateContract)
for _, stakeAddr := range vmCreateAddrArr {
if len(stakeAddr) > 0 {
addr := common.HexToAddress(stakeAddr)
pullTask.contractList = append(pullTask.contractList, addr)
pullTask.contractHandler[addr] = VmCreateContractHandler
}
}
}
}
func SyncLogs() {
pullTask.GetLogs()
}
func (p *PullEvent) GetLogs() {
query := ethereum.FilterQuery{}
query.FromBlock = p.lastBlock
query.ToBlock = new(big.Int).Add(p.lastBlock, big.NewInt(1))
query.Addresses = p.contractList
for {
query.FromBlock = p.lastBlock
log.Info("start filter start at ", p.lastBlock.Text(10))
height, _ := p.client.BlockNumber(p.ctx)
if height <= p.lastBlock.Uint64() {
time.Sleep(time.Second)
continue
} else if height > 1000 && (height-1000) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigK)
} else if height > 100 && (height-100) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bighundred)
} else if height > 10 && (height-10) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigTen)
} else {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigOne)
}
allLogs, err := p.client.FilterLogs(p.ctx, query)
if err != nil {
log.Error("filter logs failed", err)
continue
}
if len(allLogs) > 0 {
for _, vlog := range allLogs {
handle, exist := p.contractHandler[vlog.Address]
if exist {
handle(vlog)
}
}
}
p.lastBlock = new(big.Int).Add(query.ToBlock, bigOne)
cache.Redis.Set(LastSyncBlockKey, p.lastBlock.Text(10))
}
}
func getAddress(multiAddrArr string) []string {
addrArr := strings.Split(multiAddrArr, ",")
ret := make([]string, 0)
for _, addr := range addrArr {
if len(addr) > 0 {
ret = append(ret, addr)
}
}
return ret
}
package cache
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/garyburd/redigo/redis"
red "hashrateNode/cache/redis"
"time"
)
var Redis red.IRedis
var pool *redis.Pool
func init() {
conn := beego.AppConfig.String("cache::conn")
dbNum := beego.AppConfig.String("cache::dbNum")
password := beego.AppConfig.String("cache::password")
if err := NewPool(conn, dbNum, password); err != nil {
logs.Error(err)
return
}
Redis = red.NewStoreRedis(pool)
}
func NewPool(conn, dbNum, password string) error {
fmt.Println("redis连接池里的连接为空,重新创建连接池,starting...")
pool = &redis.Pool{
MaxIdle: 50, //最大空闲连接数
MaxActive: 0, //若为0,则活跃数没有限制
Wait: true,
IdleTimeout: 30 * time.Second, //最大空闲连接时间
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", conn)
if err != nil {
panic(err)
return nil, err
}
// 设置密码
if _, err := c.Do("AUTH", password); err != nil {
panic(err)
return nil, err
}
// 选择db
c.Do("SELECT", dbNum)
return c, nil
},
}
return nil
}
package redis
type IRedis interface {
Set(key, value string) error
Get(key string) string
LpushByte(key string, value []byte) error
Close()
RPopByte(key string) ([]byte, error)
LLen(key string) (int64, error)
RPopLPushByte(key, key1 string) ([]byte, error)
}
package redis
import (
"github.com/garyburd/redigo/redis"
"hashrateNode/log"
"reflect"
"strings"
"unsafe"
)
type StoreRedis struct {
pool *redis.Pool
}
func NewStoreRedis(pool *redis.Pool) IRedis {
sr := new(StoreRedis)
sr.pool = pool
return sr
}
/*
*
此方法没有使用
*/
func (s *StoreRedis) errorLogic(e error) {
i := strings.Index(e.Error(), "connect: connection refused")
if i == -1 {
log.Warning(i, "不包含")
}
}
/*
*
设置key,value数据
*/
func (s *StoreRedis) Set(key, value string) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/*
*
设置key,value数据
*/
func (s *StoreRedis) SetBytes(key string, value []byte) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/*
*
设置key的过期时间
*/
func (s *StoreRedis) SetKvAndExp(key, value string, expire int) error {
_, err := s.pool.Get().Do("SET", key, value, "EX", expire)
defer s.Close()
if err != nil {
return err
}
return nil
}
func (s *StoreRedis) SetKvInt(key string, value int) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/*
*
根据key获取对应数据
*/
func (s *StoreRedis) Get(key string) string {
value, err := redis.String(s.pool.Get().Do("GET", key))
defer s.Close()
if err != nil {
log.Error("redis get failed:", err)
}
return value
}
/*
*
根据key获取对应数据
*/
func (s *StoreRedis) GetBytes(key string) []byte {
value, err := s.pool.Get().Do("GET", key)
defer s.Close()
if err != nil {
log.Error("redis get failed:", err)
}
if value == nil {
return nil
}
return value.([]byte)
}
/*
*
判断key是否存在
*/
func (s *StoreRedis) IsKeyExists(key string) bool {
is_key_exit, _ := redis.Bool(s.pool.Get().Do("EXISTS", key))
defer s.Close()
return is_key_exit
}
/*
*
删除key
*/
func (s *StoreRedis) Del(key string) bool {
is_key_delete, err := redis.Bool(s.pool.Get().Do("DEL", key))
defer s.Close()
if err != nil {
log.Error("error:", err)
}
return is_key_delete
}
/*
*
删除key
*/
func (s *StoreRedis) HDel(key string, field string) bool {
is_key_delete, err := redis.Bool(s.pool.Get().Do("HDEL", key, field))
defer s.Close()
if err != nil {
log.Error("error:", err)
}
return is_key_delete
}
/*
*
对象转换成json后进行存储
*/
func (s *StoreRedis) Setnx(key string, value []byte) error {
_, err := s.pool.Get().Do("SETNX", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
func (s *StoreRedis) LpushByte(key string, value []byte) error {
_, err := s.pool.Get().Do("lpush", key, value)
if err != nil {
defer s.Close()
return err
}
defer s.Close()
return nil
}
func (s *StoreRedis) RPopByte(key string) ([]byte, error) {
v, err := redis.Bytes(s.pool.Get().Do("rpop", key))
if err != nil {
defer s.Close()
return nil, err
}
defer s.Close()
return v, nil
}
func (s *StoreRedis) LPop(key string) (string, error) {
v, err := s.pool.Get().Do("lpop", key)
if err != nil {
defer s.Close()
return "", err
}
defer s.Close()
if v == nil {
return "", nil
}
vv := BytesToString(v.([]byte))
return vv, nil
}
func BytesToString(b []byte) string {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := reflect.StringHeader{bh.Data, bh.Len}
return *(*string)(unsafe.Pointer(&sh))
}
func (s *StoreRedis) LLen(key string) (int64, error) {
v, err := s.pool.Get().Do("llen", key)
if err != nil {
defer s.Close()
return 0, err
}
defer s.Close()
if v == nil {
return 0, nil
}
return v.(int64), nil
}
func (s *StoreRedis) Close() {
s.pool.Get().Close()
}
/*
*
Hincryby方法
*/
func (s *StoreRedis) HINCRBY(key, field string) {
s.pool.Get().Do("HINCRBY", key, field, 1)
defer s.Close()
}
/*
*
HGet方法
*/
func (s *StoreRedis) HGet(key, field string) (interface{}, error) {
value, err := s.pool.Get().Do("HGET", key, field)
defer s.Close()
return value, err
}
/*
*
HGetAll方法
*/
func (s *StoreRedis) HGetAll(key string) ([][]byte, error) {
inter, err := redis.ByteSlices(s.pool.Get().Do("HGetAll", key))
defer s.Close()
return inter, err
}
/*
*
Hset方法
*/
func (s *StoreRedis) HSet(key string, field string, value string) (interface{}, error) {
inter, err := s.pool.Get().Do("HSET", key, field, value)
defer s.Close()
return inter, err
}
/*
*
Hset方法
*/
func (s *StoreRedis) HSetByte(key string, field string, value []byte) (interface{}, error) {
inter, err := s.pool.Get().Do("HSET", key, field, value)
defer s.Close()
return inter, err
}
/*
*
SADD方法
*/
func (s *StoreRedis) SAdd(args []interface{}) (interface{}, error) {
inter, err := s.pool.Get().Do("SADD", args...)
defer s.Close()
return inter, err
}
/*
*
Scard方法
*/
func (s *StoreRedis) SCard(key string) (interface{}, error) {
inter, err := s.pool.Get().Do("SCARD", key)
defer s.Close()
return inter, err
}
/*
*
Spop方法
*/
func (s *StoreRedis) SPop(key string) (interface{}, error) {
inter, err := s.pool.Get().Do("SPOP", key)
defer s.Close()
vv := BytesToString(inter.([]byte))
return vv, err
}
func (s *StoreRedis) RPopLPushByte(key, key1 string) ([]byte, error) {
v, err := redis.Bytes(s.pool.Get().Do("RPOPLPUSH", key, key1))
if err != nil {
defer s.Close()
return nil, err
}
defer s.Close()
return v, nil
}
package common
const (
Stopped = "stopped"
Running = "running"
Ens18 = "ens18"
Ipv4 = "ipv4"
Ipv6 = "ipv6"
SuccessCode = 200
)
package common
const (
EventList = "event"
)
// VmCreateEvent 虚拟机创建事件
const (
VmCreateEvent = "0x95a3474b7f17a50dbe31a066616a43275e294ecc845b2b15719fc1020a530828"
VmStatusEvent = "0x6d74ccc6dd7ac077e79f02d90ad1be6fc9b7a6fc9294398d29659ba748efda7a"
)
// VmCreateContract 虚拟机创建合约
const (
VmCreateContract = "0x4a5001cC1CF65392Ea3386254c5eF0427E872a5B"
VmContract = "0x17aa4736acd9d5043c43d80Fb432699990189aCc"
)
appname = hashrateNode
httpport = 8080
runmode = dev
chain_rpc_url = http://127.0.0.1:7545
chainID = 5777
local_ip = 192.168.1.108
secret = bdcd61d5-6d48-4a0b-ac74-509ec0c3ecde
sendTranAddress = 0xdeD9a4A4983D2025251FDE94c52Cb63A134f8f57
sendTranPrv = 0x2556a944727463313701b8892ea4dca8113461af4bbc059ced93668b90520c42
deployedBlock = 1
[pve]
ip = 192.168.1.230
port = 8006
user = root@pam
pass = "2023!@#WSX#@!"
host_name = "node-230"
ticket_api = /api2/json/access/ticket
nodes_api = /api2/json/nodes
access_prefix = "PVEAuthCookie="
# redis config
[cache]
collectionName = redis
conn = 127.0.0.1:6379
dbNum = 1
password = 123456
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
[
{
"inputs": [
{
"internalType": "address",
"name": "const",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "taskId",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": false,
"internalType": "string",
"name": "callerIp",
"type": "string"
},
{
"indexed": false,
"internalType": "string",
"name": "cpuModel",
"type": "string"
},
{
"indexed": false,
"internalType": "uint64",
"name": "cpuNum",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint64",
"name": "cpuCores",
"type": "uint64"
},
{
"indexed": false,
"internalType": "string",
"name": "gpuModel",
"type": "string"
},
{
"indexed": false,
"internalType": "uint64",
"name": "gpuNum",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint64",
"name": "memNum",
"type": "uint64"
},
{
"indexed": false,
"internalType": "string",
"name": "os",
"type": "string"
}
],
"name": "AddCreateVMInfoEvent",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "taskId",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "creater",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "snatcher",
"type": "address"
}
],
"name": "SnatchTaskEvent",
"type": "event"
},
{
"inputs": [],
"name": "_const",
"outputs": [
{
"internalType": "contract ICloudConstant",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_admin",
"type": "address"
}
],
"name": "addAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "taskId",
"type": "string"
},
{
"internalType": "string",
"name": "callerIp",
"type": "string"
},
{
"internalType": "string",
"name": "cpuModel",
"type": "string"
},
{
"internalType": "uint64",
"name": "cpuNum",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "cpuCores",
"type": "uint64"
},
{
"internalType": "string",
"name": "gpuModel",
"type": "string"
},
{
"internalType": "uint64",
"name": "gpuNum",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "memNum",
"type": "uint64"
},
{
"internalType": "string",
"name": "os",
"type": "string"
}
],
"name": "addVirtualMachine",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_admin",
"type": "address"
}
],
"name": "delAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getTaskId",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "taskId",
"type": "string"
}
],
"name": "getVmCreateProgress",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "isAdmin",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "const",
"type": "address"
}
],
"name": "setConstant",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "taskId",
"type": "string"
},
{
"internalType": "address",
"name": "creater",
"type": "address"
}
],
"name": "snatchTask",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "",
"type": "string"
},
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"name": "taskProgress",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "taskId",
"type": "string"
},
{
"internalType": "uint256",
"name": "createStage",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "createProgress",
"type": "uint256"
}
],
"name": "updateVmCreateProgress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
\ No newline at end of file
This diff is collapsed.
module hashrateNode
go 1.19
require github.com/astaxie/beego v1.12.3
require (
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
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/Knetic/govaluate v3.0.0+incompatible // indirect
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd // indirect
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/casbin/casbin v1.7.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d // indirect
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 // indirect
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 // indirect
github.com/elastic/go-elasticsearch/v6 v6.8.5 // indirect
github.com/ethereum/go-ethereum v1.12.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/garyburd/redigo v1.6.4 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-redis/redis v6.14.2+incompatible // indirect
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6 // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/lib/pq v1.0.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/oschwald/geoip2-golang v1.9.0 // indirect
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
github.com/pelletier/go-toml v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // 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/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 // indirect
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // 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"
"hashrateNode/asyncLog"
"hashrateNode/log"
)
func main() {
asyncLog.SyncLogs()
log.InitLog(log.LogConfig{Path: "logs", Level: "debug", Save: 3})
beego.Run()
}
package models
import "math/big"
type CreteVmEvent struct {
Ip string `json:"ip"`
VmId string `json:"vmid"`
}
type VmStatusEvent struct {
TaskId string `json:"taskId"`
Progress *big.Int `json:"progress"`
}
package models
import (
"github.com/ethereum/go-ethereum/common"
"math/big"
"time"
)
// HeaderInfo 请求头的信息
type HeaderInfo struct {
CSRFPreventionToken string `json:"CSRFPreventionToken"`
Ticket string `json:"ticket"`
}
// VM 虚拟机的数据
type VM struct {
NewId string `json:"newId"` // 克隆虚拟机模版新id
VmId string `json:"vmId"` // 虚拟机模版id
Name string `json:"name"`
VmCfg *VmConfig `json:"vmConfig"`
User string `json:"user"`
Password string `json:"password"`
HeaderInfo *HeaderInfo `json:"headerInfo"`
}
// VmConfig 虚拟机的配置信息
type VmConfig struct {
CallerIp string `json:"callerIp"`
TaskId string `json:"taskId"`
Owner common.Address `json:"owner"`
Cpu string `json:"cpu"` // 指定虚拟CPU的类型、特性和配置。
Cores *big.Int `json:"cores"` // 设置每个CPU插槽中的核心数量。
Sockets *big.Int `json:"sockets"` // 设置CPU插槽的数量。
Memory *big.Int `json:"memory"` // 设置虚拟机的内存大小。
OsType *big.Int `json:"osType"` // 客户操作系统的类型。
Gpu string `json:"gpu"` // 指定虚拟GPU的类型、特性和配置。
GpuNum *big.Int `json:"gpuNum"` // 设置虚拟机的Gpu数量。
StartDate time.Time `json:"startDate"` // 设置虚拟机的初始日期和时间。
Disk *big.Int `json:"disk"`
}
package models
import "math/big"
type VmStatusRep struct {
Status string `json:"status"`
}
type ResponseArr struct {
Data []interface{} `json:"data"`
}
type Response struct {
Data map[string]interface{} `json:"data"`
}
type ResponseStr struct {
Data string `json:"data"`
}
type QemuList struct {
Cpus int64 `json:"cpus"`
VmId int64 `json:"vmid"`
Pid int64 `json:"pid"`
MaxMem *big.Int `json:"maxMem"`
Template int64 `json:"template"`
}
type NetWorkResult struct {
Result []*NetworkInfo `json:"result"`
}
type NetworkInfo struct {
IpAddresses []IpInfo `json:"ip-addresses"`
Name string `json:"name"`
}
type IpInfo struct {
IpAddress string `json:"ip-address"`
Prefix int `json:"prefix"`
IpAddressType string `json:"ip-address-type"`
}
package pveApi
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/astaxie/beego"
hashrateCommon "hashrateNode/common"
"hashrateNode/log"
"hashrateNode/models"
"io/ioutil"
"net/http"
"net/url"
)
var pveTicketApi, pveNodesPrefixApi string
var client *http.Client
var hostName string
func init() {
ip := beego.AppConfig.String("pve::ip")
port := beego.AppConfig.String("pve::port")
path := beego.AppConfig.String("pve::ticket_api")
hostName = beego.AppConfig.String("pve::host_name")
url := "https://" + ip + ":" + port
pveNodesPrefixApi = url + beego.AppConfig.String("pve::nodes_api") + fmt.Sprintf("/%s/qemu", hostName)
pveTicketApi = url + path
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 忽略 SSL 证书错误
}
client = &http.Client{Transport: tr}
}
// GetCreateVmTicket 获取调用api的ticket
func GetCreateVmTicket() (*models.HeaderInfo, error) {
data := url.Values{}
data.Set("username", beego.AppConfig.String("pve::user"))
data.Set("password", beego.AppConfig.String("pve::pass"))
isSuccess, _, result, err := sendPostForm(pveTicketApi, data, nil)
if err != nil || !isSuccess {
return nil, err
}
ticket := new(models.HeaderInfo)
dataMarshal, err := json.Marshal(result)
if err != nil {
log.Error("GetCreateVmTicket json marshal error:", err)
return nil, err
}
err = json.Unmarshal(dataMarshal, ticket)
if err != nil {
log.Error("GetCreateVmTicket json Unmarshal error:", err)
return nil, err
}
ticket.Ticket = beego.AppConfig.String("pve::access_prefix") + ticket.Ticket
return ticket, nil
}
func StartVm(vm *models.VM) (interface{}, error) {
uriSuffix := fmt.Sprintf("/%s/status/start", vm.NewId)
uri := pveNodesPrefixApi + uriSuffix
data := url.Values{}
data.Set("node", hostName)
data.Set("vmid", vm.NewId)
isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
return result, nil
}
// CreateVm 通过模版克隆对应的vm
func CreateVm(vm *models.VM) (interface{}, error) {
uriSuffix := fmt.Sprintf("/%s/clone", vm.VmId)
uri := pveNodesPrefixApi + uriSuffix
data := url.Values{}
data.Set("node", hostName)
data.Set("vmid", vm.VmId)
data.Set("newid", vm.NewId)
data.Set("name", vm.Name)
isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
return result, nil
}
// SetVmConfig 设置vm的配置信息
func SetVmConfig(vm *models.VM) (interface{}, error) {
uriSuffix := fmt.Sprintf("/%s/config", vm.NewId)
uri := pveNodesPrefixApi + uriSuffix
data := url.Values{}
data.Set("node", hostName)
data.Set("vmid", vm.NewId)
data.Set("cores", vm.VmCfg.Cores.String())
data.Set("sockets", vm.VmCfg.Sockets.String())
data.Set("memory", vm.VmCfg.Memory.String())
isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
return result, nil
}
func GetVmNetWork(vm *models.VM) ([]*models.NetworkInfo, error) {
uriSuffix := fmt.Sprintf("/%s/agent/network-get-interfaces", vm.NewId)
uri := pveNodesPrefixApi + uriSuffix
isSuccess, _, resp, err := sendGetRequest(uri, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
networkResult := &models.NetWorkResult{}
respMarshal, err := json.Marshal(resp)
if err != nil {
return nil, err
}
if err := json.Unmarshal(respMarshal, networkResult); err != nil {
fmt.Println("JSON解析错误:", err)
return nil, err
}
return networkResult.Result, nil
}
// VmStatus 获取虚拟机的状态 stopped|running
func VmStatus(vm *models.VM) (*models.VmStatusRep, error) {
uriSuffix := fmt.Sprintf("/%s/status/current", vm.NewId)
uri := pveNodesPrefixApi + uriSuffix
isSuccess, _, resp, err := sendGetRequest(uri, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
vmStatus := &models.VmStatusRep{}
respMarshal, err := json.Marshal(resp)
if err != nil {
return nil, err
}
if err := json.Unmarshal(respMarshal, vmStatus); err != nil {
fmt.Println("JSON解析错误:", err)
return nil, err
}
return vmStatus, nil
}
func GetQemuList(headerInfo *models.HeaderInfo) ([]*models.QemuList, error) {
isSuccess, responseArr, _, err := sendGetRequest(pveNodesPrefixApi, headerInfo)
if err != nil || !isSuccess {
return nil, err
}
qemuList := make([]*models.QemuList, 0)
respMarshal, err := json.Marshal(responseArr)
if err != nil {
return nil, err
}
if err := json.Unmarshal(respMarshal, qemuList); err != nil {
fmt.Println("JSON解析错误:", err)
return nil, err
}
return qemuList, nil
}
func SetVmLoginUser(vm *models.VM) (interface{}, error) {
uriSuffix := fmt.Sprintf("/%s/agent/set-user-password", vm.NewId)
uri := pveNodesPrefixApi + uriSuffix
data := url.Values{}
data.Set("node", hostName)
data.Set("vmid", vm.NewId)
data.Set("password", vm.VmCfg.Cores.String())
data.Set("username", vm.VmCfg.Sockets.String())
isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
if err != nil || !isSuccess {
return nil, err
}
return result, nil
}
// sendPostForm 发送postForm请求
func sendPostForm(uri string, data url.Values, headInfo *models.HeaderInfo) (bool, []interface{}, map[string]interface{}, error) {
request, err := http.NewRequest("POST", uri, bytes.NewBufferString(data.Encode()))
if err != nil {
return false, nil, nil, err
}
if headInfo != nil {
request.Header.Set("Cookie", headInfo.Ticket)
request.Header.Set("CSRFPreventionToken", headInfo.CSRFPreventionToken)
}
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
isSuccess, responseArr, response, err := handlerResponse(request)
if err != nil {
return false, nil, nil, err
}
log.Infof("request uri:%s , request method:%s,request result:%s", uri, "post", response)
return isSuccess, responseArr, response, nil
}
// sendGetRequest 发送Get请求
func sendGetRequest(uri string, headInfo *models.HeaderInfo) (bool, []interface{}, map[string]interface{}, error) {
request, err := http.NewRequest("GET", uri, nil)
if headInfo != nil {
request.Header.Set("Cookie", headInfo.Ticket)
request.Header.Set("CSRFPreventionToken", headInfo.CSRFPreventionToken)
}
isSuccess, responseArr, response, err := handlerResponse(request)
if err != nil {
return false, nil, nil, err
}
log.Infof("request uri:%s,request method:%s,request result:%s", uri, "get", response)
return isSuccess, responseArr, response, nil
}
// handlerResponse 处理相应数据
func handlerResponse(request *http.Request) (bool, []interface{}, map[string]interface{}, error) {
resp, err := client.Do(request)
if err != nil {
log.Errorf("Send get request error: %s , uri: %s", err.Error(), request.URL.String())
return false, nil, nil, err
}
defer resp.Body.Close()
if resp.StatusCode != hashrateCommon.SuccessCode {
log.Error("Send post request failed:", resp.Status)
return false, nil, nil, nil
}
readAllResult, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应内容错误:", err)
return false, nil, nil, err
}
result1 := &models.ResponseStr{}
err = json.Unmarshal(readAllResult, result1)
if err != nil {
log.Warning("json unmarshal responseStr error:", err)
}
if result1.Data != "" {
return true, nil, nil, nil
}
result2 := &models.ResponseArr{}
err = json.Unmarshal(readAllResult, result2)
if err != nil {
log.Warning("json unmarshal responseStr error:", err)
}
if len(result2.Data) > 0 {
return true, result2.Data, nil, nil
}
result := &models.Response{}
err = json.Unmarshal(readAllResult, result)
if err != nil {
log.Error("json Unmarshal error:", err)
return false, nil, nil, err
}
return true, nil, result.Data, nil
}
package test
import (
"fmt"
"hashrateNode/asyncLog"
"net/http"
"net/http/httptest"
"path/filepath"
"runtime"
"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)
})
})
}
func TestIpAddressCondition(t *testing.T) {
condition := asyncLog.IsCreateVmCondition("13.38.146.66")
fmt.Println("condition:", condition)
}
package utils
import (
"context"
"crypto/ecdsa"
"encoding/json"
"fmt"
"github.com/astaxie/beego"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/oschwald/geoip2-golang"
"hashrateNode/log"
"math"
"math/big"
"net"
"time"
)
// EarthRadius 地球半径(单位:千米)
const EarthRadius = 6371
// Coordinates 经纬度坐标结构体
type Coordinates struct {
Latitude float64 // 纬度
Longitude float64 // 经度
}
// EthGetTransactionCount 获取账户nonce
func EthGetTransactionCount(client *ethclient.Client, param string) (uint64, error) {
ctx := context.Background()
addr := common.HexToAddress(param)
nonce, err := client.NonceAt(ctx, addr, nil)
return nonce, err
}
func GetTranOpts() (*bind.TransactOpts, error) {
prv := beego.AppConfig.String("sendTranPrv")
key, err := StringToPrivateKey(prv)
if err != nil {
return nil, err
}
chainID, _ := beego.AppConfig.Int64("chainID")
auth, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(chainID))
if err != nil {
return nil, err
}
return auth, nil
}
// StringToPrivateKey 解析私钥
func StringToPrivateKey(privateKeyStr string) (*ecdsa.PrivateKey, error) {
privateKeyByte, err := hexutil.Decode(privateKeyStr)
if err != nil {
return nil, err
}
privateKey, err := crypto.ToECDSA(privateKeyByte)
if err != nil {
return nil, err
}
return privateKey, nil
}
func Marshal(param interface{}) []byte {
byteInfo, _ := json.Marshal(param)
return byteInfo
}
func GetFormatTime(timestamp int64) string {
return time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")
}
// 将角度转换为弧度
func degreesToRadians(degrees float64) float64 {
return degrees * (math.Pi / 180.0)
}
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 db.Close()
// 解析 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
}
// 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
}
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