Exemple #1
0
func VerifyRegistration(url string) {
	headers := []string{"Authorization TutumAgentToken " + Conf.Token,
		"Content-Type application/json",
		"User-Agent dockercloud-agent/" + VERSION}
	body, err := SendRequest("GET", utils.JoinURL(url, Conf.UUID), nil, headers)
	if err != nil {
		SendError(err, "SendRequest error", nil)
		Logger.Printf("Get registration info error, %s", err)
	} else {
		var form RegGetForm
		if err = json.Unmarshal(body, &form); err != nil {
			SendError(err, "Json unmarshal error", nil)
			Logger.Println("Cannot unmarshal the response", err)
		} else {
			if form.State == "Deployed" {
				Logger.Printf("Node registration to %s succeeded", Conf.Host)
				return
			}
		}
	}

	time.Sleep(5 * time.Minute)

	body, err = SendRequest("GET", utils.JoinURL(url, Conf.UUID), nil, headers)
	if err != nil {
		SendError(err, "Failed to get registration info after 5 minutes", nil)
		Logger.Printf("Get registration info error, %s", err)
	} else {
		var form RegGetForm
		if err = json.Unmarshal(body, &form); err != nil {
			SendError(err, "Json unmarshal error", nil)
			Logger.Println("Cannot unmarshal the response", err)
		} else {
			if form.State == "Deployed" {
				Logger.Printf("Node registration to %s succeeded", Conf.Host)
			} else {
				Logger.Printf("Node registration to %s timed out", Conf.Host)
				Logger.Println("Node state:", form.State)
			}
		}
	}
}
func isNodeReachable(url, uuid string) bool {
	var reachableForm ReachableForm

	detailedUrl := utils.JoinURL(url, uuid+"/ping/")
	headers := []string{"Authorization TutumAgentToken " + Conf.Token,
		"Content-Type application/json",
		"User-Agent dockercloud-agent/" + VERSION}

	//waiting for docker port opens
	Logger.Print("Waiting for docker unix socket to be ready")
	for {
		unixsock := DockerDefaultHost
		if strings.HasPrefix(unixsock, "unix://") {
			unixsock = DockerDefaultHost[7:]
		}

		_, err := net.DialTimeout("unix", unixsock, DialTimeOut*time.Second)
		if err == nil {
			break
		} else {
			time.Sleep(2 * time.Second)
		}
	}
	Logger.Print("Docker unix socket opened")

	//check the port from remote server
	for i := 1; ; i *= 2 {
		if i > MaxWaitingTime {
			i = 1
		}
		body, err := SendRequest("POST", detailedUrl, nil, headers)
		if err == nil {
			if err := json.Unmarshal(body, &reachableForm); err != nil {
				SendError(err, "Json unmarshal error", nil)
				Logger.Println("Failed to unmarshal the response", err)
			} else {
				return reachableForm.Reachable
			}
		}
		SendError(err, "Node reachable check HTTP error", nil)
		Logger.Printf("Node reachable check failed, %s. Retry in %d seconds", err, i)
		time.Sleep(time.Duration(i) * time.Second)
	}
}
func patchTunnel(url, tunnel string) {
	Logger.Println("Sending tunnel address to Docker Cloud")
	form := TunnelPatchForm{}
	form.Version = VERSION
	form.Tunnel = tunnel
	data, err := json.Marshal(form)
	if err != nil {
		SendError(err, "Json marshal error", nil)
		Logger.Printf("Cannot marshal the TunnelPatch form:%s\f", err)
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.Token,
		"Content-Type", "application/json"}
	_, err = SendRequest("PATCH", utils.JoinURL(url, Conf.UUID), data, headers)
	if err != nil {
		SendError(err, "Failed to patch tunnel address to Docker Cloud", nil)
		Logger.Println("Failed to patch tunnel address to Docker Cloud,", err)
	}
	Logger.Println("New tunnel has been set up")
}
func updateNgrokHost(url string) {
	if NgrokHost != "" {
		return
	}

	headers := []string{"Authorization TutumAgentToken " + Conf.Token,
		"Content-Type application/json"}
	body, err := SendRequest("GET", utils.JoinURL(url, Conf.UUID), nil, headers)
	if err != nil {
		SendError(err, "SendRequest error", nil)
		Logger.Printf("Get registration info error, %s", err)
	} else {
		var form RegGetForm
		if err = json.Unmarshal(body, &form); err != nil {
			SendError(err, "Json unmarshal error", nil)
			Logger.Println("Cannot unmarshal the response", err)
		} else {
			if form.NgrokHost != "" {
				NgrokHost = form.NgrokHost
				Logger.Println("Ngrok server:", NgrokHost)
			}
		}
	}
}
func main() {
	dockerBinPath := path.Join(DockerDir, DockerBinaryName)
	dockerNewBinPath := path.Join(DockerDir, DockerNewBinaryName)
	dockerNewBinSigPath := path.Join(DockerDir, DockerNewBinarySigName)
	configFilePath := path.Join(AgentHome, ConfigFileName)
	keyFilePath := path.Join(AgentHome, KeyFileName)
	certFilePath := path.Join(AgentHome, CertFileName)
	caFilePath := path.Join(AgentHome, CAFileName)
	ngrokPath := path.Join(DockerDir, NgrokBinaryName)
	ngrokLogPath := path.Join(LogDir, NgrokLogName)
	ngrokConfPath := path.Join(AgentHome, NgrokConfName)

	_ = os.MkdirAll(AgentHome, 0755)
	_ = os.MkdirAll(DockerDir, 0755)
	_ = os.MkdirAll(LogDir, 0755)

	ParseFlag()

	if *FlagVersion {
		fmt.Println(VERSION)
		return
	}
	SetLogger(path.Join(LogDir, AgentLogFileName))
	Logger.Print("Running dockercloud-agent: version ", VERSION)
	CreatePidFile(AgentPidFile)

	PrepareFiles(configFilePath, dockerBinPath, keyFilePath, certFilePath)
	SetConfigFile(configFilePath)

	regUrl := utils.JoinURL(Conf.Host, RegEndpoint)
	if Conf.UUID == "" {
		os.RemoveAll(keyFilePath)
		os.RemoveAll(certFilePath)
		os.RemoveAll(caFilePath)

		if !*FlagStandalone {
			Logger.Printf("Registering in Docker Cloud via POST: %s", regUrl)
			RegPost(regUrl, caFilePath, configFilePath)
		}
	}

	if *FlagStandalone {
		commonName := Conf.CertCommonName
		if commonName == "" {
			commonName = "*"
		}
		CreateCerts(keyFilePath, certFilePath, commonName)
	} else {
		CreateCerts(keyFilePath, certFilePath, Conf.CertCommonName)
	}

	if utils.FileExist(dockerBinPath) {
		DockerClientVersion = GetDockerClientVersion(dockerBinPath)
	}

	if !*FlagStandalone {
		Logger.Printf("Registering in Docker Cloud via PATCH: %s",
			regUrl+Conf.UUID)
		err := RegPatch(regUrl, caFilePath, certFilePath, configFilePath)
		if err != nil {
			Logger.Printf("PATCH error %s :either UUID (%s) or Token is invalid", err.Error(), Conf.UUID)
			Conf.UUID = ""
			SaveConf(configFilePath, Conf)

			os.RemoveAll(keyFilePath)
			os.RemoveAll(certFilePath)
			os.RemoveAll(caFilePath)

			Logger.Printf("Registering in Docker Cloud via POST: %s", regUrl)
			RegPost(regUrl, caFilePath, configFilePath)

			CreateCerts(keyFilePath, certFilePath, Conf.CertCommonName)
			DownloadDocker(DockerBinaryURL, dockerBinPath)

			Logger.Printf("Registering in Docker Cloud via PATCH: %s",
				regUrl+Conf.UUID)
			if err = RegPatch(regUrl, caFilePath, certFilePath, configFilePath); err != nil {
				SendError(err, "Registion HTTP error", nil)
			}
		}
	}

	if err := SaveConf(configFilePath, Conf); err != nil {
		SendError(err, "Failed to save config to the conf file", nil)
		Logger.Fatalln(err)
	}

	DownloadDocker(DockerBinaryURL, dockerBinPath)
	CreateDockerSymlink(dockerBinPath, DockerSymbolicLink)
	HandleSig()
	syscall.Setpriority(syscall.PRIO_PROCESS, os.Getpid(), RenicePriority)

	Logger.Println("Initializing docker daemon")
	StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath)

	if !*FlagStandalone {
		if *FlagSkipNatTunnel {
			Logger.Println("Skip NAT tunnel")
		} else {
			Logger.Println("Loading NAT tunnel module")
			go NatTunnel(regUrl, ngrokPath, ngrokLogPath, ngrokConfPath, Conf.UUID)
		}
	}

	if !*FlagStandalone {
		Logger.Println("Verifying the registration with Docker Cloud")
		go VerifyRegistration(regUrl)
	}

	Logger.Println("Docker server started. Entering maintenance loop")
	for {
		time.Sleep(HeartBeatInterval * time.Second)
		UpdateDocker(dockerBinPath, dockerNewBinPath, dockerNewBinSigPath, keyFilePath, certFilePath, caFilePath)

		// try to restart docker daemon if it dies somehow
		if DockerProcess == nil {
			time.Sleep(HeartBeatInterval * time.Second)
			if DockerProcess == nil && ScheduleToTerminateDocker == false {
				Logger.Println("Respawning docker daemon")
				StartDocker(dockerBinPath, keyFilePath, certFilePath, caFilePath)
			}
		}
	}
}
Exemple #6
0
func sendRegRequest(url, method, token, uuid string, data []byte) ([]byte, error) {
	headers := []string{"Authorization TutumAgentToken " + token,
		"Content-Type application/json",
		"User-Agent dockercloud-agent/" + VERSION}
	return SendRequest(method, utils.JoinURL(url, uuid), data, headers)
}