blob: d699c4bc14fb4f1cfbf657da5036c7719e81b132 [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package servodserver
import (
"bytes"
"go.chromium.org/chromiumos/test/servod/cmd/model"
"fmt"
"io"
"strings"
"go.chromium.org/luci/common/errors"
)
// RunCli runs servod service as execution by CLI.
func (s *ServodService) RunCli(cs model.CliSubcommand, a model.CliArgs, stdin io.Reader, routeToStd bool) (bytes.Buffer, bytes.Buffer, error) {
s.logger.Println("Start running the servod service CLI.")
var bOut bytes.Buffer
var bErr bytes.Buffer
var err error
command := ""
switch cs {
case model.CliStartServod:
command, err = s.getStartServodCommand(a)
case model.CliStopServod:
command = s.getStopServodCommand(a)
case model.CliExecCmd:
command = s.getExecCmdCommand(a)
case model.CliCallServod:
command = s.getCallServodCommand(a)
}
if command != "" {
s.logger.Printf("Execute command: %s", command)
bOut, bErr, err = s.commandexecutor.Run(a.ServoHostPath, command, stdin, routeToStd)
if err != nil {
return bOut, bErr, err
}
s.logger.Println("Finished running the servod service CLI successfully!")
}
return bOut, bErr, err
}
// getStartServodCommand returns either a "docker run" command when
// ServodDockerImagePath is specified or a "start servod" command
// when ServodDockerImagePath is empty.
func (s *ServodService) getStartServodCommand(a model.CliArgs) (string, error) {
if a.Board == "" {
return "", errors.Reason("Board not specified").Err()
}
if a.Model == "" {
return "", errors.Reason("Model not specified").Err()
}
if a.SerialName == "" {
return "", errors.Reason("SerialName not specified").Err()
}
command := ""
if a.ServodDockerImagePath != "" {
if a.ServodDockerContainerName == "" {
return "", errors.Reason("ServodDockerContainerName not specified").Err()
}
command = fmt.Sprintf("docker run -d --network host --name %s %s --cap-add=NET_ADMIN --volume=/dev:/dev --privileged %s /start_servod.sh",
a.ServodDockerContainerName, getStartServodEnv(a, "--env "), a.ServodDockerImagePath)
} else {
command = fmt.Sprintf("start servod %s", getStartServodEnv(a, ""))
}
return command, nil
}
// getStartServodEnv returns environment variables as a string.
// envPrefix is applied to each environment variable (e.g. Docker --env parameter).
func getStartServodEnv(a model.CliArgs, envPrefix string) string {
env := fmt.Sprintf("%sPORT=%d", envPrefix, a.ServodPort)
env = fmt.Sprintf("%s %sBOARD=%s", env, envPrefix, a.Board)
env = fmt.Sprintf("%s %sMODEL=%s", env, envPrefix, a.Model)
env = fmt.Sprintf("%s %sSERIAL=%s", env, envPrefix, a.SerialName)
if a.AllowDualV4 != "" {
env = fmt.Sprintf("%s %sDUAL_V4=%s", env, envPrefix, a.AllowDualV4)
}
if a.Config != "" {
env = fmt.Sprintf("%s %sCONFIG=%s", env, envPrefix, a.Config)
}
if a.Debug != "" {
env = fmt.Sprintf("%s %sDEBUG=%s", env, envPrefix, a.Debug)
}
if a.RecoveryMode != "" {
env = fmt.Sprintf("%s %sREC_MODE=%s", env, envPrefix, a.RecoveryMode)
}
return env
}
// getStopServodCommand returns either a "docker stop" command when
// ServodDockerContainerName is specified or a "stop servod" command
// when ServodDockerContainerName is empty.
func (s *ServodService) getStopServodCommand(a model.CliArgs) string {
command := ""
if a.ServodDockerContainerName != "" {
command = fmt.Sprintf("docker exec -d %s /stop_servod.sh && docker stop %s",
a.ServodDockerContainerName, a.ServodDockerContainerName)
} else {
command = fmt.Sprintf("stop servod PORT=%d", a.ServodPort)
}
return command
}
// getExecCmdCommand returns either a "docker exec" command when
// ServodDockerContainerName is specified or the command provided
// when ServodDockerContainerName is empty.
func (s *ServodService) getExecCmdCommand(a model.CliArgs) string {
if a.ServodDockerContainerName != "" {
return fmt.Sprintf("docker exec -d %s '%s'",
a.ServodDockerContainerName, a.Command)
} else {
return a.Command
}
}
// getCallServodCommand returns either a "docker exec" command when
// ServodDockerContainerName is specified or a "dut-control" command
// when ServodDockerContainerName is empty.
func (s *ServodService) getCallServodCommand(a model.CliArgs) string {
command := ""
// Generate a "dut-control" command based on the method and args provided.
switch strings.ToLower(a.Method) {
case "doc":
command = fmt.Sprintf("dut-control -p %d -i %s", a.ServodPort, a.Args)
case "get", "set":
command = fmt.Sprintf("dut-control -p %d %s", a.ServodPort, a.Args)
}
if a.ServodDockerContainerName != "" {
return fmt.Sprintf("docker exec -d %s '%s'",
a.ServodDockerContainerName, command)
} else {
return command
}
}