Пример #1
0
func new_reg_resp_from_hashed(hr hashed_registry_response) (*registry_response, error) {
	h := md5.New()
	h.Write([]byte(hr.ResponseStr))
	hash_expect := hex.EncodeToString(h.Sum(nil))
	if hr.Hash != hash_expect {
		return nil, logging.SErrorf("hash doesn't match: (got)%s != (expected)%s", hr.Hash, hash_expect)
	}
	var resp registry_response
	err := json.Unmarshal([]byte(hr.ResponseStr), &resp)
	if err != nil {
		return nil, logging.SErrorf("failed to unmarshal RegistryResponse: %v", err)
	}
	return &resp, nil
}
Пример #2
0
func new_hashed_reg_response_from_json(dump []byte) (*hashed_registry_response, error) {
	var hr hashed_registry_response
	err := json.Unmarshal(dump, &hr)
	if err != nil {
		logging.Errorf("dump: %s", string(dump))
		return nil, logging.SErrorf("failed to unmarshal HashedRegistryResponse: %v", err)
	}
	return &hr, nil
}
Пример #3
0
func WatchRuntimeConfFromEtcd(etcd_machines []string, etcd_path string, stop chan error) <-chan RespConfig {
	logging.Info("WatchRuntimeConfFromEtcd Started")
	var (
		out            = make(chan RespConfig, 1)
		sleep_duration = time.Second
		// sleep_duration = time.Second * 5
	)

	if stop == nil {
		panic("stop chan is nil")
	}

	go func() {
		var (
			the_first_time = true
			watching       = false
			chGetConf      <-chan time.Time
			chWaching      <-chan time.Time
		)

		client := etcd.NewClient(etcd_machines)

		cached_conf, _ := LoadRuntimeConfFromPath(CONF_CACHE_PATH)

		watch_stop := make(chan bool, 0)

	loop:
		for {
			if watching == false && chGetConf == nil {
				if the_first_time == true {
					chGetConf = time.After(0)
				} else {
					chGetConf = time.After(sleep_duration)
				}
			}

			if watching == true && chWaching == nil {
				chWaching = time.After(sleep_duration)
			}

			select {
			case <-stop:
				logging.Info("stop watching etcd.")
				watch_stop <- true
				logging.Info("watching etcd stopped.")
				break loop
			case <-chGetConf:
				the_first_time = false
				chGetConf = nil

				tmp_conf, err := getRuntimeConfFromEtcd(client, etcd_path)
				if err != nil {
					if cached_conf != nil {
						// if failed to get config from etcd but we have a cached copy. then use
						// this cached version first.
						out <- RespConfig{cached_conf, nil}
						cached_conf = nil // cached copy only need to emit once.
					} else {
						out <- RespConfig{nil, logging.SErrorf("failed to getRuntimeConfFromEtcd: %v", err)}
					}
				} else {
					out <- RespConfig{tmp_conf, nil}
					watching = true
				}
			case <-chWaching:
				chWaching = nil
				logging.Infof("watching etcd remote config: %s, %s", etcd_machines, etcd_path)
				resp, err := client.Watch(etcd_path, 0, false, nil, watch_stop)
				if err != nil {
					logging.Errorf("watching etcd error: %v", err)
					break
				}

				r := bytes.NewReader([]byte(resp.Node.Value))
				tmp_conf, err := ReadRuntimeConfig(r)
				if err != nil {
					logging.Errorf("watching etcd. changes detected but faild to parse config: %v", err)
					break
				}

				logging.Infof("a new config is comming")
				out <- RespConfig{tmp_conf, nil}
			}
		}
	}()
	return out
}
Пример #4
0
func do_registry(reg_url string) (*registry_response, error) {
	logging.Debug("do_registry started")
	req, err := new_reg_request()
	if err != nil {
		return nil, logging.SError(err)
	}
	hReq, err := new_hashed_reg_request(req)
	if err != nil {
		return nil, logging.SError(err)
	}

	hResp, err := goreq.Request{
		Method:      "POST",
		Uri:         reg_url,
		Body:        hReq,
		Accept:      "application/json",
		ContentType: "application/json",
		UserAgent:   "hickwall",
		Timeout:     10 * time.Second,
	}.Do()

	if serr, ok := err.(*goreq.Error); ok {
		if serr.Timeout() {
			return nil, logging.SError(err)
		}
		return nil, logging.SErrorf("registry failed: %d", hResp.StatusCode)
	}
	defer hResp.Body.Close()

	if hResp.StatusCode != 200 {
		return nil, logging.SErrorf("status code != 200: %d", hResp.StatusCode)
	}

	body, err := ioutil.ReadAll(hResp.Body)
	if err != nil {
		return nil, logging.SErrorf("failed to read body %v", err)
	}

	resp, err := new_reg_response_from_json(body)
	if err != nil {
		return nil, logging.SError(err)
	}

	if resp.ErrorCode != 0 {
		if resp.ErrorCode == 1001 {
			logging.Warn("this agent already registried.")
		} else {
			return nil, logging.SErrorf("registry server give this error: %d, msg: %s", resp.ErrorCode, resp.ErrorMsg)
		}

	}

	if len(resp.EtcdMachines) <= 0 {
		return nil, logging.SError("EtcdMachines is empty")
	}

	for _, m := range resp.EtcdMachines {
		machine, err := url.Parse(m)
		if err != nil {
			return nil, logging.SErrorf("invalid etcd machine url: %s", err)
		}
		if machine.Scheme != "http" {
			return nil, logging.SErrorf("etcd machine url only support http : %s", m)
		}
	}

	if resp.EtcdConfigPath == "" {
		return nil, logging.SError("config path is empty")
	}

	if resp.RequestHash != hReq.Hash {
		return nil, logging.SErrorf("request hash and response hash mismatch: %s != (response)%s", hReq.Hash, resp.RequestHash)
	}
	resp.Request = req

	logging.Debug("do_registry finished")
	resp.Save()
	return resp, nil
}