Esempio n. 1
0
func (i *Instance) dialSSH(stderr io.Writer) error {
	if i.ssh != nil {
		return nil
	}

	i.sshMtx.RUnlock()
	i.sshMtx.Lock()
	defer i.sshMtx.RLock()
	defer i.sshMtx.Unlock()

	if i.ssh != nil {
		return nil
	}

	var sc *ssh.Client
	err := sshAttempts.Run(func() (err error) {
		if stderr != nil {
			fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", i.IP)
		}
		sc, err = ssh.Dial("tcp", i.IP+":22", &ssh.ClientConfig{
			User: "******",
			Auth: []ssh.AuthMethod{ssh.Password("ubuntu")},
		})
		return
	})
	if sc != nil {
		i.ssh = sc
	}
	return err
}
Esempio n. 2
0
func (c *BaseCluster) instanceRunCmd(cmd string, sshConfig *ssh.ClientConfig, ipAddress string) error {
	sshConn, err := ssh.Dial("tcp", ipAddress+":22", sshConfig)
	if err != nil {
		return err
	}
	defer sshConn.Close()
	return c.instanceRunCmdWithClient(cmd, sshConn, sshConfig.User, ipAddress)
}
Esempio n. 3
0
func (c *SSHCluster) testAndAddAuthentication(target *TargetServer, sshConfig *ssh.ClientConfig) bool {
	conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", target.IP, target.Port), sshConfig)
	if err != nil {
		return false
	}
	target.SSHConfig = sshConfig
	target.SSHClient = conn
	return true
}
Esempio n. 4
0
func (c *BaseCluster) uploadDebugInfo(t *TargetServer) {
	cmd := "sudo flynn-host collect-debug-info"
	if t.SSHClient == nil {
		var err error
		t.SSHClient, err = ssh.Dial("tcp", net.JoinHostPort(t.IP, t.Port), t.SSHConfig)
		if err != nil {
			c.SendLog(fmt.Sprintf("Error connecting to %s:%s: %s", t.IP, t.Port, err))
			return
		}
	}
	if err := c.instanceRunCmdWithClient(cmd, t.SSHClient, t.User, t.IP); err != nil {
		c.SendLog(fmt.Sprintf("Error running %s: %s", cmd, err))
	}
}
Esempio n. 5
0
func (c *BaseCluster) attemptSSHConnectionForTarget(t *TargetServer) error {
	attempts := 0
	maxAttempts := 30
	for {
		var err error
		t.SSHClient, err = ssh.Dial("tcp", net.JoinHostPort(t.IP, t.Port), t.SSHConfig)
		if err != nil {
			if attempts < maxAttempts {
				attempts++
				c.SendLog(err.Error())
				time.Sleep(time.Second)
				continue
			}
			return err
		}
		break
	}
	return nil
}
Esempio n. 6
0
func (c *DigitalOceanCluster) instanceWaitForSSH(sshConfig *ssh.ClientConfig, ipAddress string) error {
	c.base.SendLog(fmt.Sprintf("Waiting for ssh on %s", ipAddress))
	timeout := time.After(5 * time.Minute)
	for {
		sshConn, err := ssh.Dial("tcp", ipAddress+":22", sshConfig)
		if err != nil {
			if _, ok := err.(*net.OpError); ok {
				select {
				case <-time.After(5 * time.Second):
					continue
				case <-timeout:
					return err
				}
			}
			return err
		}
		sshConn.Close()
		return nil
	}
}
Esempio n. 7
0
func (c *BaseCluster) instanceRunCmd(cmd string, sshConfig *ssh.ClientConfig, ipAddress string) error {
	c.SendLog(fmt.Sprintf("Running `%s` on %s", cmd, ipAddress))

	sshConn, err := ssh.Dial("tcp", ipAddress+":22", sshConfig)
	if err != nil {
		return err
	}
	defer sshConn.Close()

	sess, err := sshConn.NewSession()
	if err != nil {
		return err
	}
	stdout, err := sess.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := sess.StderrPipe()
	if err != nil {
		return err
	}
	if err = sess.Start(cmd); err != nil {
		return err
	}

	go func() {
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			c.SendLog(scanner.Text())
		}
	}()
	go func() {
		scanner := bufio.NewScanner(stderr)
		for scanner.Scan() {
			c.SendLog(scanner.Text())
		}
	}()

	return sess.Wait()
}
Esempio n. 8
0
func (c *BaseCluster) bootstrap() error {
	c.SendLog("Running bootstrap")

	if c.SSHKey == nil {
		return errors.New("No SSHKey found")
	}

	// bootstrap only needs to run on one instance
	ipAddress := c.InstanceIPs[0]

	sshConfig, err := c.sshConfig()
	if err != nil {
		return nil
	}

	attempts := 0
	maxAttempts := 3
	var sshConn *ssh.Client
	for {
		sshConn, err = ssh.Dial("tcp", ipAddress+":22", sshConfig)
		if err != nil {
			if attempts < maxAttempts {
				attempts += 1
				time.Sleep(time.Second)
				continue
			}
			return err
		}
		break
	}
	defer sshConn.Close()

	sess, err := sshConn.NewSession()
	if err != nil {
		return err
	}
	stdout, err := sess.StdoutPipe()
	if err != nil {
		return err
	}
	sess.Stderr = os.Stderr
	if err := sess.Start(fmt.Sprintf("CLUSTER_DOMAIN=%s flynn-host bootstrap --json", c.Domain.Name)); err != nil {
		c.uploadDebugInfo(sshConfig, ipAddress)
		return err
	}

	var keyData struct {
		Key string `json:"data"`
	}
	var loginTokenData struct {
		Token string `json:"data"`
	}
	var controllerCertData struct {
		Pin    string `json:"pin"`
		CACert string `json:"ca_cert"`
	}
	output := json.NewDecoder(stdout)
	for {
		var stepRaw json.RawMessage
		if err := output.Decode(&stepRaw); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		var step stepInfo
		if err := json.Unmarshal(stepRaw, &step); err != nil {
			return err
		}
		if step.State == "error" {
			c.uploadDebugInfo(sshConfig, ipAddress)
			return fmt.Errorf("bootstrap: %s %s error: %s", step.ID, step.Action, step.Error)
		}
		c.SendLog(fmt.Sprintf("%s: %s", step.ID, step.State))
		if step.State != "done" {
			continue
		}
		switch step.ID {
		case "controller-key":
			if err := json.Unmarshal(*step.Data, &keyData); err != nil {
				return err
			}
		case "controller-cert":
			if err := json.Unmarshal(*step.Data, &controllerCertData); err != nil {
				return err
			}
		case "dashboard-login-token":
			if err := json.Unmarshal(*step.Data, &loginTokenData); err != nil {
				return err
			}
		case "log-complete":
			break
		}
	}
	if keyData.Key == "" || controllerCertData.Pin == "" {
		return err
	}

	c.ControllerKey = keyData.Key
	c.ControllerPin = controllerCertData.Pin
	c.CACert = controllerCertData.CACert
	c.DashboardLoginToken = loginTokenData.Token

	if err := c.saveField("ControllerKey", c.ControllerKey); err != nil {
		return err
	}
	if err := c.saveField("ControllerPin", c.ControllerPin); err != nil {
		return err
	}
	if err := c.saveField("CACert", c.CACert); err != nil {
		return err
	}
	if err := c.saveField("DashboardLoginToken", c.DashboardLoginToken); err != nil {
		return err
	}

	if err := sess.Wait(); err != nil {
		return err
	}
	return nil
}
Esempio n. 9
0
func (c *BaseCluster) bootstrapTarget(t *TargetServer) error {
	c.SendLog("Running bootstrap")

	if t.SSHClient == nil {
		attempts := 0
		maxAttempts := 30
		for {
			var err error
			t.SSHClient, err = ssh.Dial("tcp", net.JoinHostPort(t.IP, t.Port), t.SSHConfig)
			if err != nil {
				if attempts < maxAttempts {
					attempts++
					c.SendLog(err.Error())
					time.Sleep(time.Second)
					continue
				}
				return err
			}
			break
		}
	}

	sess, err := t.SSHClient.NewSession()
	if err != nil {
		return err
	}
	stdout, err := sess.StdoutPipe()
	if err != nil {
		return err
	}
	sess.Stderr = os.Stderr
	if err := sess.Start(fmt.Sprintf("CLUSTER_DOMAIN=%s flynn-host bootstrap --timeout 240 --min-hosts=%d --discovery=%s --json", c.Domain.Name, c.NumInstances, c.DiscoveryToken)); err != nil {
		c.uploadDebugInfo(t)
		return err
	}

	var keyData struct {
		Key string `json:"data"`
	}
	var loginTokenData struct {
		Token string `json:"data"`
	}
	var controllerCertData struct {
		Pin    string `json:"pin"`
		CACert string `json:"ca_cert"`
	}
	output := json.NewDecoder(stdout)
	for {
		var stepRaw json.RawMessage
		if err := output.Decode(&stepRaw); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		var step stepInfo
		if err := json.Unmarshal(stepRaw, &step); err != nil {
			return err
		}
		if step.State == "error" {
			c.uploadDebugInfo(t)
			return fmt.Errorf("bootstrap: %s %s error: %s", step.ID, step.Action, step.Error)
		}
		c.SendLog(fmt.Sprintf("%s: %s", step.ID, step.State))
		if step.State != "done" {
			continue
		}
		switch step.ID {
		case "controller-key":
			if err := json.Unmarshal(*step.Data, &keyData); err != nil {
				return err
			}
		case "controller-cert":
			if err := json.Unmarshal(*step.Data, &controllerCertData); err != nil {
				return err
			}
		case "dashboard-login-token":
			if err := json.Unmarshal(*step.Data, &loginTokenData); err != nil {
				return err
			}
		case "log-complete":
			break
		}
	}
	if keyData.Key == "" || controllerCertData.Pin == "" {
		return err
	}

	c.ControllerKey = keyData.Key
	c.ControllerPin = controllerCertData.Pin
	c.CACert = controllerCertData.CACert
	c.DashboardLoginToken = loginTokenData.Token

	if err := c.saveField("ControllerKey", c.ControllerKey); err != nil {
		return err
	}
	if err := c.saveField("ControllerPin", c.ControllerPin); err != nil {
		return err
	}
	if err := c.saveField("CACert", c.CACert); err != nil {
		return err
	}
	if err := c.saveField("DashboardLoginToken", c.DashboardLoginToken); err != nil {
		return err
	}

	if err := sess.Wait(); err != nil {
		return err
	}
	return nil
}
Esempio n. 10
0
func (i *Instance) DialSSH() (*ssh.Client, error) {
	return ssh.Dial("tcp", i.IP+":22", &ssh.ClientConfig{
		User: "******",
		Auth: []ssh.AuthMethod{ssh.Password("ubuntu")},
	})
}