func appDelAction(c *cli.Context) { appname := c.String("d") super, err := context.CheckSuperPerm(context.Config.User) if err != nil { fmt.Println(err) return } if !super { fmt.Println("You have no permission to this operation") return } if appname == "" { appname = context.GetAppName() } fmt.Printf("Type %s to continue: ", "yes") var cmd string fmt.Scanf("%s\n", &cmd) if cmd != "yes" { return } _, version, err := context.GetApp(appname) if err != nil { fmt.Println(err) return } err = context.DelApp(appname, version) if err != nil { fmt.Println(err) return } else { fmt.Printf("Delete %s success\n", appname) } }
func appDelAction(c *cli.Context) { appname := context.GetAppName() fmt.Printf("Type %s to continue: ", "yes") var cmd string fmt.Scanf("%s\n", &cmd) if cmd != "yes" { return } _, version, err := context.GetApp(appname) if err != nil { fmt.Println(err) return } err = context.DelApp(appname, version) if err != nil { fmt.Println(err) return } else { fmt.Printf("Delete %s success\n", appname) } }
func appModAction(c *cli.Context) { appname := context.GetAppName() s := c.String("s") m := c.String("m") f := c.String("f") i := c.Int("i") r := c.String("r") R := c.String("R") k := c.Int("k") t := c.Int("t") appConfig := meta.AppConfig{} config, version, err := context.GetApp(appname) if err != nil { fmt.Println(err) return } err = json.Unmarshal(config, &appConfig) if err != nil { fmt.Println(err) return } //update config if needed if s != "" { if s == "true" { appConfig.AutoEnableSlaveRead = true } else if s == "false" { appConfig.AutoEnableSlaveRead = false } } if m != "" { if m == "true" { appConfig.AutoEnableMasterWrite = true } else if m == "false" { appConfig.AutoEnableMasterWrite = false } } if f != "" { if f == "true" { appConfig.AutoFailover = true } else if f == "false" { appConfig.AutoFailover = false } } if i != -1 { appConfig.AutoFailoverInterval = time.Duration(i) } if r != "" { appConfig.MasterRegion = r } if R != "" { appConfig.Regions = strings.Split(R, ",") } if k != -1 { appConfig.MigrateKeysEachTime = k } if t != -1 { appConfig.MigrateTimeout = t } out, err := json.Marshal(appConfig) if err != nil { fmt.Println(err) return } err = context.ModApp(appname, out, version) if err != nil { fmt.Println(err) return } fmt.Printf("Mod %s success\n%s\n", appname, string(out)) }
func upgradeSlaves(c *cli.Context) { pid := context.GetAppName() addr := context.GetLeaderAddr() url := "http://" + addr + api.FetchReplicaSetsPath resp, err := utils.HttpGet(url, nil, 5*time.Second) if err != nil { fmt.Println(err) return } var rss command.FetchReplicaSetsResult err = utils.InterfaceToStruct(resp.Body, &rss) if err != nil { fmt.Println(err) return } sort.Sort(topo.ByMasterId(rss.ReplicaSets)) sort.Sort(topo.ByNodeState(rss.ReplicaSets)) iidx, err := getIdx(IdxServerAddr, pid, "slaves") if err != nil { fmt.Println(err) return } fmt.Printf("Get last idx record: %d\n", iidx) for idx, rs := range rss.ReplicaSets { if rs.Master.IsArbiter() { continue } if idx <= iidx { fmt.Printf("Skipping replica(id:%s) (%d/%d) slaves\n", rs.Master.Id, idx, len(rss.ReplicaSets)) continue } fmt.Printf("Upgrading replica(id:%s) (%d/%d) slaves\n", rs.Master.Id, idx, len(rss.ReplicaSets)) for _, s := range rs.Slaves { //disable read _, err := configRead(s, false) if err != nil { fmt.Println(err) } fmt.Printf("Disable read %s\n", s.Addr()) err = configAofAndRdb(s, false) if err != nil { fmt.Println(err) } fmt.Printf("Disable aof feature %s\n", s.Addr()) //send shutdown command err = shutdownServer(s) if err != nil { fmt.Printf("server %s restart\n", s.Addr()) } //sleep for 5 seconds time.Sleep(5 * time.Second) } //check slaves replica status and loading status inner := func(nodes []*topo.Node) bool { for _, n := range nodes { ok, err := checkSlaveRepliStatusOk(n) if err != nil { return false } if !ok { return false } } return true } cnt := 0 for { ok := inner(rs.Slaves) if ok { break } cnt++ fmt.Printf("Checking slaves replication status %d times\n", cnt) time.Sleep(5 * time.Second) } //enable slaves aof and read flag for _, s := range rs.Slaves { err := configAofAndRdb(s, true) if err != nil { fmt.Println(err) } _, err = configRead(s, true) if err != nil { fmt.Println(err) } fmt.Printf("Enable slaves %s aof and read flag\n", s.Addr()) } //status ok, record the idx to a redis err := saveIdx(IdxServerAddr, pid, "slaves", idx) if err != nil { fmt.Printf("saveIdx to %d failed\n", idx) } } }
func upgradeMaster(c *cli.Context) { pid := context.GetAppName() addr := context.GetLeaderAddr() url_fr := "http://" + addr + api.FetchReplicaSetsPath url_fl := "http://" + addr + api.NodeSetAsMasterPath extraHeader := &utils.ExtraHeader{ User: context.Config.User, Role: context.Config.Role, Token: context.Config.Token, } resp, err := utils.HttpGet(url_fr, nil, 5*time.Second) if err != nil { fmt.Println(err) return } var rss command.FetchReplicaSetsResult err = utils.InterfaceToStruct(resp.Body, &rss) if err != nil { fmt.Println(err) return } sort.Sort(topo.ByMasterId(rss.ReplicaSets)) sort.Sort(topo.ByNodeState(rss.ReplicaSets)) iidx, err := getIdx(IdxServerAddr, pid, "master") if err != nil { fmt.Println(err) return } fmt.Printf("Get last idx record: %d\n", iidx) var old_master *topo.Node var new_master *topo.Node //used to check status var new_slaves []*topo.Node old_master = nil new_master = nil for idx, rs := range rss.ReplicaSets { if rs.Master.IsArbiter() { continue } if idx <= iidx { fmt.Printf("Skipping replica(id:%s) (%d/%d) master\n", rs.Master.Id, idx, len(rss.ReplicaSets)) continue } //select a slave in the same IDC old_master = rs.Master old_master_r := getRegion(old_master) if old_master_r == "" { return } new_slaves = append(new_slaves, old_master) fmt.Printf("Upgrading replica(id:%s) (%d/%d) master\n", rs.Master.Id, idx, len(rss.ReplicaSets)) skip := false for _, s := range rs.Slaves { re := getRegion(s) if re == "" { return } if re == old_master_r && !skip { new_master = s skip = true } else { new_slaves = append(new_slaves, s) } } if new_master == nil { fmt.Printf("Select new master failed for master(%s) replica\n", old_master.Id) return } //send failover to the new master req := api.FailoverTakeoverParams{ NodeId: new_master.Id, } resp, err := utils.HttpPostExtra(url_fl, req, 10*time.Second, extraHeader) if err != nil { fmt.Println(err) return } if resp.Errno != 0 { fmt.Println(resp.Errmsg) return } //send failover request done,check the new_master role to a real master for { ismaster, err := checkMasterRole(new_master, true) if err != nil { fmt.Println(err) time.Sleep(10 * time.Second) continue } if ismaster == true { //to be a new master break } else { //wait for next check time.Sleep(10 * time.Second) } } //disable read flag of the all new slaves,including old master for _, s := range new_slaves { resp, err = configRead(s, false) if err != nil { fmt.Println(err) return } if resp.Errno != 0 { fmt.Println(resp.Errmsg) return } } //disable aof and rdb to speed up start err = configAofAndRdb(old_master, false) if err != nil { fmt.Println(err) return } //shutdown server err = shutdownServer(old_master) if err != nil { fmt.Printf("server %s restart\n", old_master.Addr()) } //check the status of old master cnt := 1 for { fmt.Printf("Check slave status %d times\n", cnt) cnt++ inner := func(nodes []*topo.Node) bool { rok := true for _, n := range nodes { ok, err := checkSlaveRepliStatusOk(n) if ok { //replica status ok,enable read flag,ignore result configRead(n, true) continue } if !ok || err != nil { rok = false } } return rok } ok := inner(new_slaves) if !ok { //not ok, wait for next trun check time.Sleep(10 * time.Second) } else { break } } //enable aof and rdb err = configAofAndRdb(old_master, true) if err != nil { fmt.Println(err) return } //save the idx of the process err = saveIdx(IdxServerAddr, pid, "master", idx) if err != nil { fmt.Println(err) return } } }