aboutsummaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorJoey Jiao <quic_jiangenj@quicinc.com>2024-06-17 09:45:16 +0800
committerAleksandr Nogikh <nogikh@google.com>2025-02-10 11:56:14 +0000
commit529cb927961356394978d77470022859e718c44a (patch)
treebc2d2e2f6d8040f9908d6bd22701f359dbbb3516 /vm
parentef44b750e8fab8d6d5cb84920680581b13e0d470 (diff)
vm: support console_cmd to run cmd to collect console log
- Sometimes we need customized cmd to get serial log, ex FTDI4232H chip gets serial log through usb directly, thus we need to call cmd like `pyterm.py ftdi://ftdi:4232:FT7JLD0U/1`. - There are seveval places in console implementation to call osutil.Command, move the command code into one function.
Diffstat (limited to 'vm')
-rw-r--r--vm/adb/adb.go49
-rw-r--r--vm/vmimpl/console.go52
2 files changed, 52 insertions, 49 deletions
diff --git a/vm/adb/adb.go b/vm/adb/adb.go
index e914acded..8889f7397 100644
--- a/vm/adb/adb.go
+++ b/vm/adb/adb.go
@@ -33,8 +33,9 @@ func init() {
}
type Device struct {
- Serial string `json:"serial"` // device serial to connect
- Console string `json:"console"` // console device name (e.g. "/dev/pts/0")
+ Serial string `json:"serial"` // device serial to connect
+ Console string `json:"console"` // console device name (e.g. "/dev/pts/0")
+ ConsoleCmd []string `json:"console_cmd"` // command to obtain device console log
}
type Config struct {
@@ -60,13 +61,14 @@ type Pool struct {
}
type instance struct {
- cfg *Config
- adbBin string
- device string
- console string
- closed chan bool
- debug bool
- timeouts targets.Timeouts
+ cfg *Config
+ adbBin string
+ device string
+ console string
+ consoleCmd []string
+ closed chan bool
+ debug bool
+ timeouts targets.Timeouts
}
var (
@@ -132,13 +134,14 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
return nil, err
}
inst := &instance{
- cfg: pool.cfg,
- adbBin: pool.cfg.Adb,
- device: device.Serial,
- console: device.Console,
- closed: make(chan bool),
- debug: pool.env.Debug,
- timeouts: pool.env.Timeouts,
+ cfg: pool.cfg,
+ adbBin: pool.cfg.Adb,
+ device: device.Serial,
+ console: device.Console,
+ consoleCmd: device.ConsoleCmd,
+ closed: make(chan bool),
+ debug: pool.env.Debug,
+ timeouts: pool.env.Timeouts,
}
closeInst := inst
defer func() {
@@ -149,10 +152,14 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
if err := inst.repair(); err != nil {
return nil, err
}
- if inst.console == "" {
- inst.console = findConsole(inst.adbBin, inst.device)
+ if len(inst.consoleCmd) > 0 {
+ log.Logf(0, "associating adb device %v with console cmd `%v`", inst.device, inst.consoleCmd)
+ } else {
+ if inst.console == "" {
+ inst.console = findConsole(inst.adbBin, inst.device)
+ }
+ log.Logf(0, "associating adb device %v with console %v", inst.device, inst.console)
}
- log.Logf(0, "associating adb device %v with console %v", inst.device, inst.console)
if pool.cfg.BatteryCheck {
if err := inst.checkBatteryLevel(); err != nil {
return nil, err
@@ -517,7 +524,9 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin
var tty io.ReadCloser
var err error
- if ok, ip := isRemoteCuttlefish(inst.device); ok {
+ if len(inst.consoleCmd) > 0 {
+ tty, err = vmimpl.OpenConsoleByCmd(inst.consoleCmd[0], inst.consoleCmd[1:])
+ } else if ok, ip := isRemoteCuttlefish(inst.device); ok {
tty, err = vmimpl.OpenRemoteKernelLog(ip, inst.console)
} else if inst.console == "adb" {
tty, err = vmimpl.OpenAdbConsole(inst.adbBin, inst.device)
diff --git a/vm/vmimpl/console.go b/vm/vmimpl/console.go
index 200c44f73..7ae680f26 100644
--- a/vm/vmimpl/console.go
+++ b/vm/vmimpl/console.go
@@ -77,46 +77,45 @@ func (t *tty) Close() error {
// OpenRemoteKernelLog accesses to the host where Android VM runs on, not Android VM itself.
// The host stores all kernel outputs of Android VM so in case of crashes nothing will be lost.
func OpenRemoteKernelLog(ip, console string) (rc io.ReadCloser, err error) {
- rpipe, wpipe, err := osutil.LongPipe()
- if err != nil {
- return nil, err
- }
conAddr := "vsoc-01@" + ip
- cmd := osutil.Command("ssh", conAddr, "tail", "-f", console)
- cmd.Stdout = wpipe
- cmd.Stderr = wpipe
- if _, err := cmd.StdinPipe(); err != nil {
- rpipe.Close()
- wpipe.Close()
- return nil, err
- }
- if err := cmd.Start(); err != nil {
- rpipe.Close()
- wpipe.Close()
- return nil, fmt.Errorf("failed to connect to console server: %w", err)
- }
- wpipe.Close()
- con := &remoteCon{
- cmd: cmd,
- rpipe: rpipe,
+ args := []string{
+ conAddr,
+ "tail",
+ "-f",
+ console,
}
- return con, nil
+ return OpenConsoleByCmd("ssh", args)
}
// Open dmesg remotely.
func OpenRemoteConsole(bin string, args ...string) (rc io.ReadCloser, err error) {
+ args = append(args, "dmesg -w")
+ return OpenConsoleByCmd(bin, args)
+}
+
+// OpenAdbConsole provides fallback console output using 'adb shell dmesg -w'.
+func OpenAdbConsole(bin, dev string) (rc io.ReadCloser, err error) {
+ return OpenRemoteConsole(bin, "-s", dev, "shell")
+}
+
+// Open console log by cmd.
+func OpenConsoleByCmd(bin string, args []string) (rc io.ReadCloser, err error) {
rpipe, wpipe, err := osutil.LongPipe()
if err != nil {
return nil, err
}
- args = append(args, "dmesg -w")
cmd := osutil.Command(bin, args...)
cmd.Stdout = wpipe
cmd.Stderr = wpipe
+ if _, err := cmd.StdinPipe(); err != nil {
+ rpipe.Close()
+ wpipe.Close()
+ return nil, err
+ }
if err := cmd.Start(); err != nil {
rpipe.Close()
wpipe.Close()
- return nil, fmt.Errorf("failed to start adb: %w", err)
+ return nil, fmt.Errorf("failed to open console: %w", err)
}
wpipe.Close()
con := &remoteCon{
@@ -126,11 +125,6 @@ func OpenRemoteConsole(bin string, args ...string) (rc io.ReadCloser, err error)
return con, err
}
-// OpenAdbConsole provides fallback console output using 'adb shell dmesg -w'.
-func OpenAdbConsole(bin, dev string) (rc io.ReadCloser, err error) {
- return OpenRemoteConsole(bin, "-s", dev, "shell")
-}
-
type remoteCon struct {
closeMu sync.Mutex
readMu sync.Mutex