X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/b161916d6b97e8b7205670ecc972a590749dd93c..b53513423ab948804425424278ac554870864997:/lib/boot/supervisor.go diff --git a/lib/boot/supervisor.go b/lib/boot/supervisor.go index 526411c41f..7daceccb93 100644 --- a/lib/boot/supervisor.go +++ b/lib/boot/supervisor.go @@ -42,7 +42,9 @@ type Supervisor struct { ClusterType string // e.g., production ListenHost string // e.g., localhost ControllerAddr string // e.g., 127.0.0.1:8000 + Workbench2Source string // e.g., /home/username/src/arvados-workbench2 NoWorkbench1 bool + NoWorkbench2 bool OwnTemporaryDatabase bool Stderr io.Writer @@ -58,8 +60,8 @@ type Supervisor struct { waitShutdown sync.WaitGroup bindir string - tempdir string - wwwtempdir string + tempdir string // in production mode, this is accessible only to root + wwwtempdir string // in production mode, this is accessible only to www-data configfile string environ []string // for child processes } @@ -258,6 +260,11 @@ func (super *Supervisor) run(cfg *arvados.Config) error { runPassenger{src: "apps/workbench", varlibdir: "workbench1", svc: super.cluster.Services.Workbench1, depends: []supervisedTask{installPassenger{src: "apps/workbench"}}}, ) } + if !super.NoWorkbench2 { + tasks = append(tasks, + runWorkbench2{svc: super.cluster.Services.Workbench2}, + ) + } if super.ClusterType != "test" { tasks = append(tasks, runServiceCommand{name: "dispatch-cloud", svc: super.cluster.Services.DispatchCloud}, @@ -482,6 +489,7 @@ type runOptions struct { output io.Writer // attach stdout env []string // add/replace environment variables user string // run as specified user + stdin io.Reader } // RunProgram runs prog with args, using dir as working directory. If ctx is @@ -525,6 +533,7 @@ func (super *Supervisor) RunProgram(ctx context.Context, dir string, opts runOpt } cmd := exec.Command(super.lookPath(prog), args...) + cmd.Stdin = opts.stdin stdout, err := cmd.StdoutPipe() if err != nil { return err @@ -628,32 +637,40 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { return err } usedPort := map[string]bool{} - nextPort := func(host string) string { + nextPort := func(host string) (string, error) { for { port, err := availablePort(host) if err != nil { - panic(err) + port, err = availablePort(super.ListenHost) + } + if err != nil { + return "", err } if usedPort[port] { continue } usedPort[port] = true - return port + return port, nil } } if cluster.Services.Controller.ExternalURL.Host == "" { h, p, err := net.SplitHostPort(super.ControllerAddr) if err != nil { - return err + return fmt.Errorf("SplitHostPort(ControllerAddr): %w", err) } if h == "" { h = super.ListenHost } if p == "0" { - p = nextPort(h) + p, err = nextPort(h) + if err != nil { + return err + } } cluster.Services.Controller.ExternalURL = arvados.URL{Scheme: "https", Host: net.JoinHostPort(h, p), Path: "/"} } + u := url.URL(cluster.Services.Controller.ExternalURL) + defaultExtHost := u.Hostname() for _, svc := range []*arvados.Service{ &cluster.Services.Controller, &cluster.Services.DispatchCloud, @@ -666,24 +683,32 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { &cluster.Services.WebDAVDownload, &cluster.Services.Websocket, &cluster.Services.Workbench1, + &cluster.Services.Workbench2, } { if svc == &cluster.Services.DispatchCloud && super.ClusterType == "test" { continue } if svc.ExternalURL.Host == "" { + port, err := nextPort(defaultExtHost) + if err != nil { + return err + } + host := net.JoinHostPort(defaultExtHost, port) if svc == &cluster.Services.Controller || svc == &cluster.Services.GitHTTP || svc == &cluster.Services.Health || svc == &cluster.Services.Keepproxy || svc == &cluster.Services.WebDAV || svc == &cluster.Services.WebDAVDownload || - svc == &cluster.Services.Workbench1 { - svc.ExternalURL = arvados.URL{Scheme: "https", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"} + svc == &cluster.Services.Workbench1 || + svc == &cluster.Services.Workbench2 { + svc.ExternalURL = arvados.URL{Scheme: "https", Host: host, Path: "/"} } else if svc == &cluster.Services.Websocket { - svc.ExternalURL = arvados.URL{Scheme: "wss", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/websocket"} + svc.ExternalURL = arvados.URL{Scheme: "wss", Host: host, Path: "/websocket"} } } - if super.NoWorkbench1 && svc == &cluster.Services.Workbench1 { + if super.NoWorkbench1 && svc == &cluster.Services.Workbench1 || + super.NoWorkbench2 && svc == &cluster.Services.Workbench2 { // When workbench1 is disabled, it gets an // ExternalURL (so we have a valid listening // port to write in our Nginx config) but no @@ -692,8 +717,13 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { continue } if len(svc.InternalURLs) == 0 { + port, err := nextPort(super.ListenHost) + if err != nil { + return err + } + host := net.JoinHostPort(super.ListenHost, port) svc.InternalURLs = map[arvados.URL]arvados.ServiceInstance{ - {Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"}: {}, + {Scheme: "http", Host: host, Path: "/"}: {}, } } } @@ -721,7 +751,12 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { } if super.ClusterType == "test" { // Add a second keepstore process. - cluster.Services.Keepstore.InternalURLs[arvados.URL{Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"}] = arvados.ServiceInstance{} + port, err := nextPort(super.ListenHost) + if err != nil { + return err + } + host := net.JoinHostPort(super.ListenHost, port) + cluster.Services.Keepstore.InternalURLs[arvados.URL{Scheme: "http", Host: host, Path: "/"}] = arvados.ServiceInstance{} // Create a directory-backed volume for each keepstore // process. @@ -755,10 +790,14 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { } } if super.OwnTemporaryDatabase { + port, err := nextPort("localhost") + if err != nil { + return err + } cluster.PostgreSQL.Connection = arvados.PostgreSQLConnection{ "client_encoding": "utf8", - "host": super.ListenHost, - "port": nextPort(super.ListenHost), + "host": "localhost", + "port": port, "dbname": "arvados_test", "user": "arvados", "password": "insecure_arvados_test",