Commit 533c92b4 authored by szh's avatar szh

添加备份相关接口

parent 51cba7e4
......@@ -44,7 +44,7 @@ func main() {
//树莓派内置程序操作
go app.PaiJob(time.NewTicker(time.Second * 50))
//go app.ClearLog(time.NewTicker(time.Hour*1))
go app.RollbackJob()
go app.RaspberryChan()
//上传统计树莓派信息
go app.UploadInfo(time.NewTicker(time.Minute * 10))
......
package app
var RollChan chan bool
var JobChan chan MsgType
type MsgType struct {
Name string
}
func Setup() {
RollChan = make(chan bool,1)
JobChan = make(chan MsgType,10)
}
......@@ -24,6 +24,7 @@ import (
"chain33-pai/pkg/chain33"
types2 "github.com/33cn/plugin/plugin/dapp/ticket/types"
"strconv"
"sync"
)
var tlog = log.New("pkg","app")
......@@ -60,7 +61,12 @@ type BTYDownloadInfo struct {
Version string
}
var BityuanFlag bool //true表示有任务在占用,禁止其他重复操作 重置钱包 重置节点 升级节点 不能并发执行
type BityuanOp struct {
Flag bool
Lock sync.Mutex
}
var BityuanFlag BityuanOp //true表示有任务在占用,禁止其他重复操作
var Bityuan ProcessInfo
var UpdateInfo updateInfo
var NodeError error
......@@ -145,7 +151,8 @@ func BityuanJob(ticker *time.Ticker){
for {
select {
case <-ticker.C:
if !BityuanFlag {//有更新,重置等节点重启操作时 禁止运行,防止冲突
BityuanFlag.Lock.Lock()
if !BityuanFlag.Flag {//有更新,重置等节点重启操作时 禁止运行,防止冲突
//节点未启动 会调用auto启动
NodeError = getWalletInfo()
//解锁钱包
......@@ -173,6 +180,7 @@ func BityuanJob(ticker *time.Ticker){
//升级6.4.0bityuan
//updateBityuan640()
}
BityuanFlag.Lock.Unlock()
}
}
}
......@@ -412,7 +420,7 @@ func SafeCloseNode() (bool,error) {
//return true,nil
path := GetAbsPath(setting.BityuanSetting.Name)
if path == "" {
return true,nil
return false,nil
}
close := exec.Command(path+"/"+setting.BityuanSetting.Name+"-cli","close")
stderr := bytes.NewBuffer(nil)
......@@ -782,32 +790,33 @@ func uploadVersion() error {
//update bityuan 6.3.x to 6.4.0
func updateBityuan640() error {
BityuanFlag = true
BityuanFlag.Lock.Lock()
defer BityuanFlag.Lock.Unlock()
BityuanFlag.Flag = true
//2020/4/2 20:0:0
plantime := int64(1585828800)
nowtime := time.Now().Unix()
if nowtime < plantime {
tlog.Error("waiting plantime to update","nowtime",nowtime)
BityuanFlag = false
BityuanFlag.Flag = false
return errors.New("waiting plantime to update")
}
update := GetNodeUpdateStatus()
if update {
tlog.Info("updateBityuan640 is updating","update",update)
BityuanFlag = false
BityuanFlag.Flag = false
return nil
}
var pai chain33.PaiClient
v ,err:= pai.Version()
if err != nil {
tlog.Error("get version ","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
if strings.Contains(v.App,"6.4.2") {
tlog.Info("bityuan do not need update","version",v.App)
BityuanFlag = false
BityuanFlag.Flag = false
return nil
}
......@@ -820,13 +829,13 @@ func updateBityuan640() error {
err = DownLoadFile(url,name,int32(1))
if err != nil {
tlog.Error("updateBityuan640","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
dirs := strings.Split(absPath,"wallet-bty")
if len(dirs) != 2 {
tlog.Error("updateBityuan640","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
//解压缩文件
......@@ -835,19 +844,19 @@ func updateBityuan640() error {
err = tar.Start()
if err != nil {
tlog.Error("tar","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
err = tar.Wait()
if err != nil {
tlog.Error("tar","err",stderr.String())
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
t,err := SafeCloseNode()
if err != nil || !t {
tlog.Error("updateBityuan640 close node","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
//其他模块可能没有即时关闭,在高速刷盘的情形下
......@@ -857,23 +866,23 @@ func updateBityuan640() error {
err = remove.Start()
if err != nil {
tlog.Error("rm","err",stderr.String())
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
err = remove.Wait()
if err != nil {
tlog.Error("rm","err",stderr.String())
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
err=StartProcess(setting.Chain33Pai.Auto)
if err!=nil{
tlog.Error("updateBityuan640","auto.sh error ",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
tlog.Info("updateBityuan640 success please waiting hours","version","6.3.2->6.4.2")
BityuanFlag = false
BityuanFlag.Flag = false
return nil
}
func GetNodeUpdateStatus() bool {
......
......@@ -7,21 +7,49 @@ import (
"os/exec"
"fmt"
"chain33-pai/service/pai_service"
"errors"
"os"
)
func RollbackJob() {
func RaspberryChan() {
for {
if value,ok := <- RollChan; ok {
if !value {
if value,ok := <- JobChan; ok {
tlog.Info("raspberrychan","msg",value)
if value.Name == "" {
continue
}
switch value.Name {
case "ROLLBACK":
err := rollback()
if err == nil {
tlog.Info("rollback success","err",nil)
} else {
tlog.Error("rollback fail ","err",err)
}
case "BACKUP":
err := backup()
if err == nil {
tlog.Info("backup success","err",nil)
} else {
tlog.Error("backup fail ","err",err)
}
case "RECOVER":
err := recoverNode()
if err == nil {
tlog.Info("recover success","err",nil)
} else {
tlog.Error("recover fail ","err",err)
}
case "DELETEBACKUP":
err := deleteBackup()
if err == nil {
tlog.Info("deleteBackup success","err",nil)
} else {
tlog.Error("deleteBackup fail ","err",err)
}
}
}
time.Sleep(time.Second * 1)
}
......@@ -29,22 +57,24 @@ func RollbackJob() {
func rollback() error {
BityuanFlag = true
BityuanFlag.Lock.Lock()
defer BityuanFlag.Lock.Unlock()
BityuanFlag.Flag = true
_,err := SafeCloseNode()
if err != nil {
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
var pai pai_service.Pai
err = pai.SetPai()
if err != nil {
tlog.Error("SetPai","err",err)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
if pai.LocalLastHeight == 0 {
tlog.Error("LocalLastHeight","height",pai.LocalLastHeight)
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
rollheight := pai.LocalLastHeight - 1000
......@@ -57,17 +87,94 @@ func rollback() error {
path := GetAbsPath(setting.BityuanSetting.Name)
if path == "" {
tlog.Error("GetAbsPath","err","path not exists")
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
cmd := exec.Command(path+"/"+setting.BityuanSetting.Name, "-rollback",fmt.Sprintf("%d",rollheight))
cmd.Stdout = &buf
err = cmd.Run()
if err != nil {
BityuanFlag = false
BityuanFlag.Flag = false
return err
}
tlog.Info("rollback end","height",pai.LocalLastHeight,"rollbackheight",rollheight)
BityuanFlag = false
BityuanFlag.Flag = false
return nil
}
func backup() error {
BityuanFlag.Lock.Lock()
defer BityuanFlag.Lock.Unlock()
if BityuanFlag.Flag {
return errors.New("env err")
}
BityuanFlag.Flag = true
ok,err := SafeCloseNode()
if err != nil {
BityuanFlag.Flag = false
return err
}
if !ok {
BityuanFlag.Flag = false
return errors.New("env err")
}
time.Sleep(time.Second * 2)
return SafeBackup()
}
func SafeBackup() error {
backup := exec.Command("cp","-r","datadir","datadir_backup")
return backup.Run()
}
func recoverNode() error {
BityuanFlag.Lock.Lock()
defer BityuanFlag.Lock.Unlock()
remove := exec.Command("rm","-rf","datadir")
err := remove.Run()
if err != nil {
tlog.Error("rm -rf datadir","err",err)
return err
}
path := GetAbsPath(setting.BityuanSetting.Name)
if path == "" {
tlog.Error("path empty","err","node not exists")
return errors.New("node not exists")
}
backupPath := path + "/datadir_backup"
if _,err := os.Stat(backupPath);err != nil {
if os.IsNotExist(err) {
tlog.Error("backup file not exists","err",backupPath)
return errors.New("backup file not exists")
}
}
recover := exec.Command("cp","-r","datadir_backup","datadir")
err = recover.Run()
if err != nil {
tlog.Error("cp -r datadir_backup datadir","err",err)
return err
}
return nil
}
func deleteBackup() error {
path := GetAbsPath(setting.BityuanSetting.Name)
if path == "" {
tlog.Error("path empty","err","node not exists")
return errors.New("node not exists")
}
backupPath := path + "/datadir_backup"
if _,err := os.Stat(backupPath);err != nil {
if os.IsNotExist(err) {
tlog.Error("backup file not exists","err",backupPath)
return errors.New("backup file not exists")
}
}
remove := exec.Command("rm","-rf","datadir_backup")
err := remove.Run()
if err != nil {
tlog.Error("rm -rf datadir_backup","err",err)
return err
}
return nil
}
\ No newline at end of file
......@@ -20,25 +20,28 @@ import (
"github.com/33cn/chain33/types"
"strings"
"time"
"strconv"
)
var flag bool//判断是否正在更新
func ResetWallet(c *gin.Context) {
appG := app.Gin{C: c}
if app.BityuanFlag {
app.BityuanFlag.Lock.Lock()
defer app.BityuanFlag.Lock.Unlock()
if app.BityuanFlag.Flag {
appG.Response(http.StatusOK, e.TRY_LATER,"other job is busy,please try later")
return
}
app.BityuanFlag = true
app.BityuanFlag.Flag = true
if app.NodeError!=nil{
tlog.Error(app.NodeError.Error())
appG.Response(http.StatusOK, e.NODE_ERROR,"node internal error,could not start node")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
t,err := app.SafeCloseNode()
if err != nil || !t {
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.NODE_ERROR,err)
return
}
......@@ -46,7 +49,7 @@ func ResetWallet(c *gin.Context) {
if err!=nil{
appG.Response(http.StatusOK, e.NODE_ERROR, "fail to remove wallet")
tlog.Error("ResetWallet","remove error",err)
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
......@@ -54,11 +57,11 @@ func ResetWallet(c *gin.Context) {
if err!=nil{
appG.Response(http.StatusOK, e.NODE_ERROR,"fail to restart node")
tlog.Error("ResetWallet","auto.sh error ",err)
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
appG.Response(http.StatusOK, e.SUCCESS,"reset complete")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
}
//钱包更新,只替换执行文件和配置文件
......@@ -66,7 +69,9 @@ func ResetWallet(c *gin.Context) {
//oss下载包打包要保持执行权限
func UpdateNodeNew(c *gin.Context){
appG := app.Gin{C: c}
if app.BityuanFlag{
app.BityuanFlag.Lock.Lock()
defer app.BityuanFlag.Lock.Unlock()
if app.BityuanFlag.Flag {
appG.Response(http.StatusOK,e.SUCCESS_RUNNING,"node is updating")
return
}
......@@ -81,7 +86,7 @@ func UpdateNodeNew(c *gin.Context){
return
}
pwd = pwd + "/"
app.BityuanFlag = true
app.BityuanFlag.Flag = true
//app.UpdateInfo.Flag = false
setting.FreshVersion()
var pai pai_service.Pai
......@@ -89,20 +94,20 @@ func UpdateNodeNew(c *gin.Context){
latestVersion,err := pai.GetPaiLatestVersion(int32(1))
if err != nil {
appG.Response(http.StatusOK, e.NODE_ERROR,"get online version err")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
//app.UpdateInfo.Flag = true
return
}
if latestVersion==setting.BityuanSetting.Version{
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.SUCCESS,"current version is latest")
return
}
if latestVersion==""{
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.NETWORK_ERROR,"network error,please checkout your network then try again")
return
}
......@@ -115,14 +120,14 @@ func UpdateNodeNew(c *gin.Context){
if err != nil {
appG.Response(http.StatusOK, e.DOWNLOAD_ERROR, err)
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
dirs := strings.Split(absPath,"wallet-bty")
if len(dirs) != 2 {
appG.Response(http.StatusOK, e.ERROR, err)
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
//解压缩文件
......@@ -133,7 +138,7 @@ func UpdateNodeNew(c *gin.Context){
tlog.Error("tar","err",err)
appG.Response(http.StatusOK, e.TAR_XVF_ERROR, err)
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
err = tar.Wait()
......@@ -141,14 +146,14 @@ func UpdateNodeNew(c *gin.Context){
tlog.Error("tar","err",stderr.String())
appG.Response(http.StatusOK, e.TAR_XVF_ERROR, stderr.String())
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
t,err := app.SafeCloseNode()
if err != nil || !t {
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.NODE_ERROR,err)
return
}
......@@ -159,14 +164,14 @@ func UpdateNodeNew(c *gin.Context){
if err != nil {
appG.Response(http.StatusOK, e.RM_ERROR, err)
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
err = remove.Wait()
if err != nil {
appG.Response(http.StatusOK, e.RM_ERROR, stderr.String())
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
err=app.StartProcess(setting.Chain33Pai.Auto)
......@@ -174,10 +179,10 @@ func UpdateNodeNew(c *gin.Context){
appG.Response(http.StatusOK, e.NODE_ERROR,"fail to restart node")
tlog.Error("UpdateNodeNew","auto.sh error ",err)
//app.UpdateInfo.Flag = true
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
app.BityuanFlag = false
app.BityuanFlag.Flag = false
//app.UpdateInfo.Flag = true
appG.Response(http.StatusOK,e.SUCCESS,"update job ok")
}
......@@ -185,20 +190,22 @@ func UpdateNodeNew(c *gin.Context){
//重置节点只需要删除datadir 然后重启节点
func ResetNode(c* gin.Context){
appG := app.Gin{C: c}
if app.BityuanFlag {
app.BityuanFlag.Lock.Lock()
defer app.BityuanFlag.Lock.Unlock()
if app.BityuanFlag.Flag {
appG.Response(http.StatusOK, e.TRY_LATER,"other job is busy,please try later")
return
}
app.BityuanFlag = true
app.BityuanFlag.Flag = true
_,err := app.SafeCloseNode()
if err != nil {
appG.Response(http.StatusOK,e.NODE_ERROR,"node err")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
err = os.RemoveAll(fmt.Sprintf("%s/datadir",path.Dir(app.Bityuan.Path)))
if err != nil {
app.BityuanFlag = false
app.BityuanFlag.Flag = false
tlog.Error("ResetNode","remove datadir err",err)
appG.Response(http.StatusOK, e.RM_ERROR,"remove datadir err")
return
......@@ -207,11 +214,11 @@ func ResetNode(c* gin.Context){
if err != nil {
tlog.Error("ResetNode","start node err",err)
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK, e.NODE_ERROR,"start auto sh err")
return
}
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.SUCCESS,"reset job ok")
}
......@@ -255,24 +262,24 @@ func NodeInfo(c *gin.Context){
func RestartNode(c* gin.Context){
appG:=app.Gin{C:c}
app.BityuanFlag = true
app.BityuanFlag.Flag = true
_,err := app.SafeCloseNode()
if err != nil {
appG.Response(http.StatusOK,e.NODE_ERROR,"node err")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
app.BityuanFlag = false
app.BityuanFlag.Flag = false
appG.Response(http.StatusOK,e.SUCCESS,"node close safe")
}
func CloseNode(c* gin.Context){
appG:=app.Gin{C:c}
app.BityuanFlag = true
app.BityuanFlag.Flag = true
_,err := app.SafeCloseNode()
if err != nil {
appG.Response(http.StatusOK,e.NODE_ERROR,"node err")
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
//防止其他模块未关闭
......@@ -518,11 +525,13 @@ func UpdateNodeStatus(c *gin.Context){
func PoweroffPai(c *gin.Context) {
appG:=app.Gin{C:c}
app.BityuanFlag = true
app.BityuanFlag.Lock.Lock()
defer app.BityuanFlag.Lock.Unlock()
app.BityuanFlag.Flag = true
_,err := app.SafeCloseNode()
if err != nil {
appG.Response(http.StatusOK,e.NODE_ERROR,err)
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
var buf bytes.Buffer
......@@ -531,7 +540,7 @@ func PoweroffPai(c *gin.Context) {
err = cmd.Run()
if err != nil {
appG.Response(http.StatusOK,e.NODE_ERROR,err)
app.BityuanFlag = false
app.BityuanFlag.Flag = false
return
}
appG.Response(http.StatusOK,e.SUCCESS,"pai restarted")
......@@ -554,6 +563,79 @@ func Test(c *gin.Context) {
func Rollback(c *gin.Context) {
appG:=app.Gin{C:c}
app.RollChan <- true
app.JobChan <- app.MsgType{Name:"ROLLBACK"}
appG.Response(http.StatusOK,e.SUCCESS,"bityuan rollback")
}
func NodeBackup(c *gin.Context) {
appG:=app.Gin{C:c}
var pai pai_service.Pai
err := pai.GetDiskUseage()
if err != nil {
tlog.Error("GetDiskUseage","err",err)
appG.Response(http.StatusOK,e.ENV_ERROR,"get diskuseage err")
return
}
if len(pai.Disks) == 0 {
tlog.Error("disk ","err","disk not find")
appG.Response(http.StatusOK,e.ENV_ERROR,"disk not find")
return
}
tlog.Info("disk info","ssd",pai.Disks[0])
p := pai.Disks[0].Use
ps := strings.Split(p,"%")
pint,_ := strconv.Atoi(ps[0])
if pint * 2 > 80 {
tlog.Error("disk space ","err","space not enough to backup")
appG.Response(http.StatusOK,e.ENV_ERROR,"disk space not enough")
return
}
app.JobChan <- app.MsgType{Name:"BACKUP"}
appG.Response(http.StatusOK,e.SUCCESS,"bityuan ready to backup")
}
func NodeRecover(c *gin.Context) {
appG:=app.Gin{C:c}
var pai pai_service.Pai
err := pai.GetDiskUseage()
if err != nil {
tlog.Error("GetDiskUseage","err",err)
appG.Response(http.StatusOK,e.ENV_ERROR,"get diskuseage err")
return
}
if len(pai.Disks) == 0 {
tlog.Error("disk ","err","disk not find")
appG.Response(http.StatusOK,e.ENV_ERROR,"disk not find")
return
}
tlog.Info("disk info","ssd",pai.Disks[0])
p := pai.Disks[0].Use
ps := strings.Split(p,"%")
pint,_ := strconv.Atoi(ps[0])
if pint * 2 > 80 {
app.JobChan <- app.MsgType{Name:"DELETEBACKUP"}
}
app.JobChan <- app.MsgType{Name:"RECOVER"}
appG.Response(http.StatusOK,e.SUCCESS,"bityuan ready to recover")
}
func DelBackup(c *gin.Context) {
appG:=app.Gin{C:c}
var pai pai_service.Pai
err := pai.GetDiskUseage()
if err != nil {
tlog.Error("GetDiskUseage","err",err)
appG.Response(http.StatusOK,e.ENV_ERROR,"get diskuseage err")
return
}
if len(pai.Disks) == 0 {
tlog.Error("disk ","err","disk not find")
appG.Response(http.StatusOK,e.ENV_ERROR,"disk not find")
return
}
tlog.Info("disk info","ssd",pai.Disks[0])
app.JobChan <- app.MsgType{Name:"DELETEBACKUP"}
appG.Response(http.StatusOK,e.ENV_ERROR,"del backup")
}
\ No newline at end of file
......@@ -57,7 +57,14 @@ func InitRouter() *gin.Engine {
apiv1.POST("/poweroff",v1.PoweroffPai)
//test
apiv1.POST("/test",v1.Test)
//回滚1000区块
apiv1.POST("/rollback",v1.Rollback)
//一键备份 40g
apiv1.POST("/nodebackup",v1.NodeBackup)
//一键恢复 针对不同步 并且 回滚多次还不同步的情况下拿最近的备份恢复
apiv1.POST("/noderecover",v1.NodeRecover)
//删除备份
apiv1.POST("/delbackup",v1.DelBackup)
return r
}
......
......@@ -13,6 +13,7 @@ import (
"io/ioutil"
"encoding/json"
"chain33-pai/pkg/setting"
"chain33-pai/pkg/app"
)
var (
......@@ -33,6 +34,7 @@ type Pai struct {
BtyVersion *types.VersionInfo `json:"bty_version"`
Err string `json:"err"`
Arch string `json:"arch"`
Disks []*app.Disk
}
type ReqUpdatePai struct {
......@@ -45,6 +47,7 @@ func (p *Pai) SetPai() error {
p.GetDevstatus()
p.GetBtyVersion()
p.SetPaiEnv()
p.GetDiskUseage()
return nil
}
......@@ -197,3 +200,14 @@ func (p *Pai) GetPaiLatestVersion(t int32) (string,error) {
}
return r.Data,nil
}
func (p *Pai) GetDiskUseage() error {
err := app.MonitorServer()
if err != nil {
return err
}
if len(app.ServerStatus.Disks) > 0 {
p.Disks = app.ServerStatus.Disks
}
return nil
}
\ No newline at end of file
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