diff options
| -rw-r--r-- | vm/vmm/vmm.go | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/vm/vmm/vmm.go b/vm/vmm/vmm.go index acaf9b3b2..8d2ce5121 100644 --- a/vm/vmm/vmm.go +++ b/vm/vmm/vmm.go @@ -9,7 +9,7 @@ import ( "io" "os" "path/filepath" - "strconv" + "regexp" "strings" "time" @@ -48,11 +48,13 @@ type instance struct { sshhost string sshport int merger *vmimpl.OutputMerger - vmID int + vmName string stop chan bool diagnose chan string } +var ipRegex = regexp.MustCompile(`bound to (([0-9]+\.){3}3)`) + func ctor(env *vmimpl.Env) (vmimpl.Pool, error) { cfg := &Config{ Count: 1, @@ -106,6 +108,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { return nil, err } + name := fmt.Sprintf("syzkaller-%v-%v", pool.env.Name, index) inst := &instance{ cfg: pool.cfg, index: index, @@ -116,6 +119,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { sshkey: pool.env.SSHKey, sshuser: pool.env.SSHUser, sshport: 22, + vmName: name, stop: make(chan bool), diagnose: make(chan string), } @@ -135,25 +139,17 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { } func (inst *instance) Boot() error { - name := fmt.Sprintf("syzkaller-%v", inst.index) mem := fmt.Sprintf("%vM", inst.cfg.Mem) startArgs := []string{ - "start", name, + "start", inst.vmName, "-t", inst.cfg.Template, "-b", inst.cfg.Kernel, "-d", inst.image, "-m", mem, } - startOut, err := inst.vmctl(startArgs...) - if err != nil { - return err - } - - inst.vmID, err = parseID(startOut) - if err != nil { + if _, err := inst.vmctl(startArgs...); err != nil { return err } - inst.sshhost = fmt.Sprintf("100.64.%v.3", inst.vmID) var tee io.Writer if inst.debug { @@ -167,7 +163,9 @@ func (inst *instance) Boot() error { var bootOutput []byte bootOutputStop := make(chan bool) + ipch := make(chan string, 1) go func() { + gotip := false for { select { case out := <-inst.merger.Output: @@ -176,9 +174,25 @@ func (inst *instance) Boot() error { bootOutputStop <- true return } + if gotip { + continue + } + if ip := parseIP(bootOutput); ip != "" { + ipch <- ip + gotip = true + } } }() + select { + case ip := <-ipch: + inst.sshhost = ip + case <-time.After(1 * time.Minute): + bootOutputStop <- true + <-bootOutputStop + return vmimpl.BootError{Title: "no IP found", Output: bootOutput} + } + if err := vmimpl.WaitForSSH(inst.debug, 2*time.Minute, inst.sshhost, inst.sshkey, inst.sshuser, inst.os, inst.sshport); err != nil { bootOutputStop <- true @@ -190,11 +204,15 @@ func (inst *instance) Boot() error { } func (inst *instance) Close() { - inst.vmctl("stop", inst.vmIdent(), "-f") + inst.vmctl("stop", inst.vmName, "-f") } func (inst *instance) Forward(port int) (string, error) { - addr := fmt.Sprintf("100.64.%v.2:%v", inst.vmID, port) + octets := strings.Split(inst.sshhost, ".") + if len(octets) < 3 { + return "", fmt.Errorf("too few octets in hostname %v", inst.sshhost) + } + addr := fmt.Sprintf("%v.%v.%v.2:%v", octets[0], octets[1], octets[2], port) return addr, nil } @@ -289,7 +307,7 @@ func (inst *instance) console() error { return err } - cmd := osutil.Command("vmctl", "console", inst.vmIdent()) + cmd := osutil.Command("vmctl", "console", inst.vmName) cmd.Stdin = inr cmd.Stdout = outw cmd.Stderr = outw @@ -351,26 +369,10 @@ func (inst *instance) vmctl(args ...string) (string, error) { return string(out), nil } -func (inst *instance) vmIdent() string { - return strconv.Itoa(inst.vmID) -} - -// Extract VM ID from vmctl start output. -func parseID(str string) (int, error) { - const prefix = "vmctl: started vm " - if !strings.HasPrefix(str, prefix) { - return 0, fmt.Errorf("could not extract ID from: %v", str) - } - fields := strings.Fields(str) - if len(fields) < 4 { - return 0, fmt.Errorf("could not extract ID from: %v", str) - } - i, err := strconv.Atoi(fields[3]) - if err != nil { - return 0, err - } - if i <= 0 { - return 0, fmt.Errorf("invalid ID: %v", i) +func parseIP(output []byte) string { + matches := ipRegex.FindSubmatch(output) + if len(matches) < 2 { + return "" } - return i, nil + return string(matches[1]) } |
