1// Copyright 2017 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4package vmimpl
5
6import (
7	"fmt"
8	"time"
9
10	"github.com/google/syzkaller/pkg/log"
11	"github.com/google/syzkaller/pkg/osutil"
12)
13
14// Sleep for d.
15// If shutdown is in progress, return false prematurely.
16func SleepInterruptible(d time.Duration) bool {
17	select {
18	case <-time.After(d):
19		return true
20	case <-Shutdown:
21		return false
22	}
23}
24
25func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS string, port int) error {
26	pwd := "pwd"
27	if OS == "windows" {
28		pwd = "dir"
29	}
30	startTime := time.Now()
31	SleepInterruptible(5 * time.Second)
32	for {
33		if !SleepInterruptible(5 * time.Second) {
34			return fmt.Errorf("shutdown in progress")
35		}
36		args := append(SSHArgs(debug, sshKey, port), sshUser+"@"+addr, pwd)
37		if debug {
38			log.Logf(0, "running ssh: %#v", args)
39		}
40		_, err := osutil.RunCmd(time.Minute, "", "ssh", args...)
41		if err == nil {
42			return nil
43		}
44		if time.Since(startTime) > timeout {
45			return fmt.Errorf("can't ssh into the instance: %v", err)
46		}
47	}
48}
49
50func SSHArgs(debug bool, sshKey string, port int) []string {
51	return sshArgs(debug, sshKey, "-p", port)
52}
53
54func SCPArgs(debug bool, sshKey string, port int) []string {
55	return sshArgs(debug, sshKey, "-P", port)
56}
57
58func sshArgs(debug bool, sshKey, portArg string, port int) []string {
59	args := []string{
60		portArg, fmt.Sprint(port),
61		"-i", sshKey,
62		"-F", "/dev/null",
63		"-o", "UserKnownHostsFile=/dev/null",
64		"-o", "BatchMode=yes",
65		"-o", "IdentitiesOnly=yes",
66		"-o", "StrictHostKeyChecking=no",
67		"-o", "ConnectTimeout=10",
68	}
69	if sshKey != "" {
70		args = append(args, "-i", sshKey)
71	}
72	if debug {
73		args = append(args, "-v")
74	}
75	return args
76}
77