| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Provides service implementations and management |
| package services |
| |
| import ( |
| "fmt" |
| "os/exec" |
| |
| "go.chromium.org/chromiumos/config/go/test/api" |
| "go.chromium.org/chromiumos/test/local-cft/internal/utils" |
| ) |
| |
| type crosDutServiceCommands struct { |
| } |
| |
| func CROS_DUT_SERVICE_COMMANDS() crosDutServiceCommands { |
| return crosDutServiceCommands{} |
| } |
| |
| // Service implementation for cros-dut |
| type CrosDutService struct { |
| Service |
| ServiceBase |
| |
| client api.DutServiceClient |
| } |
| |
| func (c *CrosDutService) Start() error { |
| c.EnsurePort() |
| |
| c.LocalLogger.Printf("Starting %s on port %d", c.Name, c.Port) |
| |
| starter := &SetupCrosDut{ |
| cd: c, |
| } |
| return c.executor.Start(starter) |
| } |
| |
| func (c *CrosDutService) Execute(commandName ServiceCommand_, args ...interface{}) error { |
| switch commandName { |
| default: |
| return fmt.Errorf("Command %s not found", commandName) |
| } |
| } |
| |
| func (c *CrosDutService) Stop() error { |
| stopper := &StopCrosDut{ |
| cd: c, |
| } |
| return c.executor.Stop(stopper) |
| } |
| |
| // Setup |
| |
| type SetupCrosDut struct { |
| ServiceSetup |
| cd *CrosDutService |
| } |
| |
| func (starter *SetupCrosDut) Setup() error { |
| if err := utils.EnsureContainerAvailable(starter.cd.Name); err != nil { |
| err = fmt.Errorf("Failed to ensure container %s was available, %s", starter.cd.Name, err) |
| starter.cd.LocalLogger.Println(err) |
| return err |
| } |
| |
| containerImage := fmt.Sprintf( |
| "us-docker.pkg.dev/cros-registry/test-services/%s:%s", |
| starter.cd.Name, |
| starter.cd.manager.images[starter.cd.Name].Tags[0], |
| ) |
| |
| if _, ok := starter.cd.manager.LocalServices[starter.cd.Name]; ok { |
| err := utils.UpdateContainerService(starter.cd.LocalLogger, starter.cd.manager.Chroot, containerImage, starter.cd.Name) |
| if err != nil { |
| starter.cd.LocalLogger.Println(err) |
| return err |
| } |
| containerImage = containerImage + "_localchange" |
| } |
| |
| request := &api.StartContainerRequest{ |
| Name: starter.cd.Name, |
| ContainerImage: containerImage, |
| AdditionalOptions: &api.StartContainerRequest_Options{ |
| Expose: []string{fmt.Sprint(starter.cd.Port)}, |
| Volume: []string{fmt.Sprintf("%s/cros-dut:/tmp/cros-dut", starter.cd.BaseDir)}, |
| Network: "host", |
| }, |
| StartCommand: []string{ |
| "cros-dut", |
| "-dut_address", |
| fmt.Sprintf("localhost:%d", starter.cd.manager.ports[SERVICES().SSHTunnel]), |
| "-cache_address", |
| fmt.Sprintf("%s:%d", "localhost", starter.cd.manager.ports[SERVICES().SSHReverseTunnel]), |
| "-port", |
| fmt.Sprint(starter.cd.Port), |
| }, |
| } |
| |
| starter.cd.manager.Execute( |
| SERVICES().CrosToolRunner, |
| CTR_SERVICE_COMMANDS().StartContainer, |
| request, |
| ) |
| |
| go BuildServiceListener( |
| &starter.cd.ServiceBase, |
| false, |
| exec.Command("docker", "logs", "-f", starter.cd.Name), |
| )() |
| |
| if err := <-starter.cd.ReadyChan; err != nil { |
| starter.cd.LocalLogger.Println(err) |
| return err |
| } |
| |
| if err := BuildConnection(&starter.cd.ServiceBase); err != nil { |
| return err |
| } |
| starter.cd.client = api.NewDutServiceClient(starter.cd.conn) |
| |
| return nil |
| } |
| |
| // Stopper |
| |
| type StopCrosDut struct { |
| ServiceStopper |
| cd *CrosDutService |
| } |
| |
| func (stopper *StopCrosDut) Stop() error { |
| if stopper.cd.conn != nil { |
| stopper.cd.conn.Close() |
| } |
| |
| if stopper.cd.Started { |
| stopper.cd.CloseChan <- struct{}{} |
| <-stopper.cd.CloseFinishedChan |
| } |
| |
| WriteLogs(&stopper.cd.ServiceBase) |
| |
| return nil |
| } |
| |
| // Commands |