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) } } } }
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) }