コード例 #1
0
ファイル: sm.go プロジェクト: yiduoyunQ/sm
// no need lock
func NewSwitchManager(context *cli.Context) error {
	config, err := NewConfig(context)
	if err != nil {
		return err
	}
	sm = &switchManager{
		config:  config,
		rwMutex: new(sync.RWMutex),
		steps:   []string{},
		closed:  true,
	}

	if sm.config.Domain == "" {
		return errors.New("need Domain specify")
	}
	if sm.config.Name == "" {
		return errors.New("need Name specify")
	}
	if sm.config.Port == "" {
		return errors.New("need Port specify")
	}
	if sm.config.ProxyPort == "" {
		return errors.New("need ProxyPort specify")
	}

	prefix = sm.config.Domain + "/" + sm.config.Name + "/"

	cs, err := consul.NewConsul(context)
	if err != nil {
		sm.steps = append(sm.steps, fmt.Sprintf("Step1. New Consul fail:%s\n", err.Error()))
		return err
	}
	sm.steps = append(sm.steps, "Step1. New Consul success\n")
	sm.consul = cs
	swm, err := swarm.NewSwarm(context, cs)
	if err != nil {
		sm.steps = append(sm.steps, fmt.Sprintf("Step2. New Swarm fail:%s\n", err.Error()))
		return err
	}
	sm.steps = append(sm.steps, "Step2. New Swarm success\n")
	sm.swarm = swm

	// init from consul
	isInitalized, err := sm.consul.GetVal(prefix + consts.InitKey)
	if err == nil && isInitalized == "true" {
		log.Info("init from consul")
		err = initProxy()
		if err != nil {
			log.WithFields(log.Fields{
				"err:": err.Error(),
			}).Error("pull proxy from consul fail, return")
			sm.steps = append(sm.steps, fmt.Sprintf("Step3. Init from consul fail:%s\n", err.Error()))
			return err
		}
		err = initTopo()
		if err != nil {
			log.WithFields(log.Fields{
				"err:": err.Error(),
			}).Error("pull topology from consul fail, continue")
			sm.steps = append(sm.steps, fmt.Sprintf("Step3. Init from consul fail:%s\n", err.Error()))
			return err
		}
		err = initSwarm()
		if err != nil {
			log.WithFields(log.Fields{
				"err:": err.Error(),
			}).Error("pull swarm from consul fail, continue")
			sm.steps = append(sm.steps, fmt.Sprintf("Step3. Init from consul fail:%s\n", err.Error()))
			return err
		}
		sm.steps = append(sm.steps, "Step3. Init from consul success\n")
	} else {
		sm.steps = append(sm.steps, "Step3. No init from consul\n")
	}

	sm.closed = false
	sm.state = 0

	// recover action no need lock
	actionVal, err := sm.consul.GetVal(prefix + consts.ActionKey)
	if actionVal != "" {
		log.Info("recover action:%s\n", actionVal)
		split := strings.Split(actionVal, ",")
		actionVal := split[0]
		name := split[1]
		if actionVal == consts.ActionIsolateProxyVal {
			if sm.proxys[name].Status != consts.ProxyClose {
				err = CloseProxy(name)
				if err != nil {
					sm.steps = append(sm.steps, fmt.Sprintf("Step4. Init recover action %s fail:%s\n", actionVal, err.Error()))
					return err
				}
				bproxys, _ := json.Marshal(sm.proxys)
				err = sm.consul.PutVal(prefix+consts.ProxyKey, bproxys)
				if err != nil {
					log.WithFields(log.Fields{
						"key": prefix + consts.ProxyKey,
						"val": string(bproxys),
						"err": err.Error(),
					}).Error("push proxy to consul fail, continue")
				}
				err = presistent.ProxyPresist(string(bproxys))
				if err != nil {
					log.WithFields(log.Fields{
						"val": string(bproxys),
						"err": err.Error(),
					}).Error("proxy presist fail, continue")
				}
			}
			err := sm.consul.PutVal(prefix+consts.ActionKey, []byte(""))
			if err != nil {
				log.WithFields(log.Fields{
					"key": prefix + consts.ActionKey,
					"val": "",
					"err": err.Error(),
				}).Error("push action key to consul fail, continue")
			}
			sm.steps = append(sm.steps, "Step4. Init recover action %s success\n")
		} else if actionVal == consts.ActionIsolateDbVal {
			if sm.topology.DataNodeGroup["default"][name].Status != consts.Abnormal {
				err, _ = ha.IsolateDB(name, sm.rwMutex, sm.topology, sm.swarm)
				if err != nil {
					sm.steps = append(sm.steps, fmt.Sprintf("Step4. Init recover action %s fail:%s\n", actionVal, err.Error()))
					return err
				}
				btopology, _ := json.Marshal(sm.topology)
				err = sm.consul.PutVal(prefix+consts.TopologyKey, btopology)
				if err != nil {
					log.WithFields(log.Fields{
						"key": prefix + consts.TopologyKey,
						"val": string(btopology),
						"err": err.Error(),
					}).Error("push topology to consul fail, continue")
				}
				err = presistent.TopologyPresist(string(btopology))
				if err != nil {
					log.WithFields(log.Fields{
						"val": string(btopology),
						"err": err.Error(),
					}).Error("topology presist fail, continue")
				}
			}
			err := sm.consul.PutVal(prefix+consts.ActionKey, []byte(""))
			if err != nil {
				log.WithFields(log.Fields{
					"key": prefix + consts.ActionKey,
					"val": "",
					"err": err.Error(),
				}).Error("push action key to consul fail, continue")
			}
			sm.steps = append(sm.steps, "Step4. Init recover action %s success\n")
		} else if actionVal == consts.ActionRecoverDbVal {
			if sm.topology.DataNodeGroup["default"][name].Status != consts.Normal {
				err, _ = ha.RecoverDb(name, sm.rwMutex, sm.topology, sm.swarm)
				if err != nil {
					sm.steps = append(sm.steps, fmt.Sprintf("Step4. Init recover action %s fail:%s\n", actionVal, err.Error()))
					return err
				}
				btopology, _ := json.Marshal(sm.topology)
				err = sm.consul.PutVal(prefix+consts.TopologyKey, btopology)
				if err != nil {
					log.WithFields(log.Fields{
						"key": prefix + consts.TopologyKey,
						"val": string(btopology),
						"err": err.Error(),
					}).Error("push topology to consul fail, continue")
				}
				err = presistent.TopologyPresist(string(btopology))
				if err != nil {
					log.WithFields(log.Fields{
						"val": string(btopology),
						"err": err.Error(),
					}).Error("topology presist fail, continue")
				}
			}
			err := sm.consul.PutVal(prefix+consts.ActionKey, []byte(""))
			if err != nil {
				log.WithFields(log.Fields{
					"key": prefix + consts.ActionKey,
					"val": "",
					"err": err.Error(),
				}).Error("push action key to consul fail, continue")
			}
			sm.steps = append(sm.steps, "Step4. Init recover action %s success\n")
		}
	} else {
		sm.steps = append(sm.steps, "Step4. No init recover action\n")
	}

	log.Info("sm init success")

	return nil
}
コード例 #2
0
ファイル: handler.go プロジェクト: yiduoyunQ/sm
func recover(w http.ResponseWriter, req *http.Request) {
	var steps []string
	vars := mux.Vars(req)
	n := vars["name"]
	log.WithFields(log.Fields{
		"RemoteAddr": req.RemoteAddr,
		"URL":        req.URL,
		"Name":       n,
	}).Info("handle `/recover/{name}` start")
	var err error
	defer func() {
		log.WithFields(log.Fields{
			"RemoteAddr": req.RemoteAddr,
			"URL":        req.URL,
			"Name":       n,
		}).Info("handle `/recover/{name}` end")

		if err != nil {
			w.Write([]byte(err.Error()))
		}

		if len(sm.steps) != 0 {
			s := ""
			for _, v := range steps {
				s = s + v
			}
			w.Write([]byte(s))
		}

		atomic.CompareAndSwapInt64(&sm.state, 2, 0)
	}()

	if !getLock(2) {
		w.WriteHeader(http.StatusNotModified)
		err = errors.New("http recover get lock fail")
		return
	}

	var t string
	sm.rwMutex.RLock()
	_, ok := sm.proxys[n]
	if ok {
		if sm.proxys[n].Status != consts.ProxyClose {
			w.WriteHeader(http.StatusBadRequest)
		} else {
			t = consts.Type_Proxy
		}

	} else {
		_, ok = sm.topology.DataNodeGroup["default"][n]
		if ok {
			status := sm.topology.DataNodeGroup["default"][n].Status
			if status == consts.Abnormal {
				t = consts.Type_Db
			} else {
				w.WriteHeader(http.StatusBadRequest)
			}
		}
	}
	sm.rwMutex.RUnlock()

	if t == consts.Type_Proxy {
		sm.rwMutex.Lock()
		if ok := sm.swarm.UpproxyStart(n); !ok {
			sm.rwMutex.Unlock()
			return
		}
		sm.proxys[n] = &structs.ProxyInfo{}
		bproxy, _ := json.Marshal(sm.proxys)
		sm.rwMutex.Unlock()
		err = sm.consul.PutVal(prefix+consts.ProxyKey, bproxy)
		if err != nil {
			log.WithFields(log.Fields{
				"key": prefix + consts.ProxyKey,
				"val": string(bproxy),
				"err": err.Error(),
			}).Error("push proxy to consul fail, continue")
		}
		err = presistent.ProxyPresist(string(bproxy))
		if err != nil {
			log.WithFields(log.Fields{
				"val": string(bproxy),
				"err": err.Error(),
			}).Error("proxy presist fail, continue")
		}

		w.WriteHeader(http.StatusOK)
	} else if t == consts.Type_Db {
		err = sm.consul.PutVal(prefix+consts.ActionKey, []byte(consts.ActionRecoverDbVal+","+n))
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		err, steps = ha.RecoverDb(n, sm.rwMutex, sm.topology, sm.swarm)
		sm.steps = steps
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
		} else {
			w.WriteHeader(http.StatusOK)
		}
		sm.rwMutex.RLock()
		btopology, _ := json.Marshal(sm.topology)
		sm.rwMutex.RUnlock()
		err = sm.consul.PutVal(prefix+consts.TopologyKey, btopology)
		if err != nil {
			log.WithFields(log.Fields{
				"key": prefix + consts.TopologyKey,
				"val": string(btopology),
				"err": err.Error(),
			}).Error("push topology to consul fail, continue")
		}
		err = presistent.TopologyPresist(string(btopology))
		if err != nil {
			log.WithFields(log.Fields{
				"val": string(btopology),
				"err": err.Error(),
			}).Error("topology presist fail, continue")
		}
		err = sm.consul.PutVal(prefix+consts.ActionKey, []byte(""))
		if err != nil {
			log.WithFields(log.Fields{
				"key": prefix + consts.ActionKey,
				"val": "",
				"err": err.Error(),
			}).Error("push action key to consul fail, continue")
		}
	} else {
		w.WriteHeader(http.StatusBadRequest)
		err = errors.New(http.StatusText(http.StatusBadRequest))
	}

}