diff options
| author | Kris Alder <kalder@google.com> | 2022-04-08 14:06:21 -0700 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2022-04-12 19:32:41 +0200 |
| commit | 87d46b64e1389c842869fae9199221565d6f65d2 (patch) | |
| tree | 8030113f01a1db5af4ec3181dd003358f0a7436e /vm/cuttlefish | |
| parent | dacb3f1c44e9c527b8bb595e3b37a43ca7733cc0 (diff) | |
vm/cuttlefish: implement forward function
We need to tunnel ports from the Manager instance all the way through to the virtual device. We do
this by tunneling from the Manager to the worker GCE instance using 'socat' on the worker instance
and 'adb reverse' to forward the port on the device.
We need the 'socat' process to keep running for the tunnel to stay open. We can check for an error
on launch, but to check if the process is still running we send it a zero signal after waiting an
appropriate amount of time.
The 'adb reverse' command, by comparison returns immediately after the connection is established and
keeps the tunnel open. We loop until we find a valid/available port, similar to what is done in
vm/adb/adb.go. In practice, this nearly always finds a valid port on the first attempt.
Diffstat (limited to 'vm/cuttlefish')
| -rw-r--r-- | vm/cuttlefish/cuttlefish.go | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/vm/cuttlefish/cuttlefish.go b/vm/cuttlefish/cuttlefish.go index dbba45037..57ab0e3f9 100644 --- a/vm/cuttlefish/cuttlefish.go +++ b/vm/cuttlefish/cuttlefish.go @@ -69,27 +69,33 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { // Start a Cuttlefish device on the GCE instance // TODO: pass it the specific kernel artifact using -kernel_path and -initramfs_path flags - if err := inst.runOnHost(10*time.Minute, "./bin/launch_cvd -daemon"); err != nil { + if err := inst.runOnHost(10*time.Minute, "./bin/launch_cvd -daemon", false); err != nil { return nil, fmt.Errorf("failed to start cuttlefish: %s", err) } - if err := inst.runOnHost(10*time.Minute, "adb wait-for-device"); err != nil { + if err := inst.runOnHost(10*time.Minute, "adb wait-for-device", false); err != nil { return nil, fmt.Errorf("failed while waiting for device: %s", err) } - if err := inst.runOnHost(5*time.Minute, "adb root"); err != nil { + if err := inst.runOnHost(5*time.Minute, "adb root", false); err != nil { return nil, fmt.Errorf("failed to get root access to device: %s", err) } return inst, nil } -func (inst *instance) runOnHost(timeout time.Duration, cmd string) error { - outc, errc, err := inst.gceInst.Run(timeout, nil, cmd) +func (inst *instance) runOnHost(timeout time.Duration, cmd string, background bool) error { + taskTimeout := timeout + if background { + taskTimeout = 24 * time.Hour + } + + outc, errc, err := inst.gceInst.Run(taskTimeout, nil, cmd) if err != nil { return fmt.Errorf("failed to run command: %s", err) } + timer := time.NewTimer(timeout) for { select { case <-vmimpl.Shutdown: @@ -103,6 +109,12 @@ func (inst *instance) runOnHost(timeout time.Duration, cmd string) error { if ok && inst.debug { log.Logf(1, "%s", out) } + case <-timer.C: + // When running processes in the background, we assume that everything is fine if the timer + // expires and it hasn't given any errors. + if background { + return nil + } } } } @@ -116,7 +128,7 @@ func (inst *instance) Copy(hostSrc string) (string, error) { deviceDst := filepath.Join(deviceRoot, filepath.Base(hostSrc)) pushCmd := fmt.Sprintf("adb push %s %s", gceDst, deviceDst) - if err := inst.runOnHost(5*time.Minute, pushCmd); err != nil { + if err := inst.runOnHost(5*time.Minute, pushCmd, false); err != nil { return "", fmt.Errorf("error pushing to device: %s", err) } @@ -124,7 +136,25 @@ func (inst *instance) Copy(hostSrc string) (string, error) { } func (inst *instance) Forward(port int) (string, error) { - return "", fmt.Errorf("not implemented") + hostForward, err := inst.gceInst.Forward(port) + if err != nil { + return "", fmt.Errorf("failed to get IP/port from GCE instance: %s", err) + } + cmd := fmt.Sprintf("socat TCP-LISTEN:%d,fork TCP:%s", port, hostForward) + if err := inst.runOnHost(60*time.Second, cmd, true); err != nil { + return "", fmt.Errorf("unable to forward port on host: %s", err) + } + + for i := 0; i < 100; i++ { + devicePort := vmimpl.RandomPort() + cmd := fmt.Sprintf("adb reverse tcp:%d tcp:%d", devicePort, port) + err = inst.runOnHost(10*time.Second, cmd, false) + if err == nil { + return fmt.Sprintf("127.0.0.1:%d", devicePort), nil + } + } + + return "", fmt.Errorf("unable to forward port on device: %s", err) } func (inst *instance) Close() { |
