X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/168fedbe65526ff3eabf155039d6e55a8f5eadf6..892521c6c0189d2e6a8fffff77140183098db259:/lib/boot/supervisor.go diff --git a/lib/boot/supervisor.go b/lib/boot/supervisor.go index 59e1ae352e..4a4ab4d98b 100644 --- a/lib/boot/supervisor.go +++ b/lib/boot/supervisor.go @@ -34,7 +34,6 @@ import ( type Supervisor struct { SourcePath string // e.g., /home/username/src/arvados SourceVersion string // e.g., acbd1324... - LibPath string // e.g., /var/lib/arvados ClusterType string // e.g., production ListenHost string // e.g., localhost ControllerAddr string // e.g., 127.0.0.1:8000 @@ -73,7 +72,7 @@ func (super *Supervisor) Start(ctx context.Context, cfg *arvados.Config) { err := super.run(cfg) if err != nil { - fmt.Fprintln(super.Stderr, err) + super.logger.WithError(err).Warn("supervisor shut down") } close(super.done) }() @@ -97,17 +96,17 @@ func (super *Supervisor) run(cfg *arvados.Config) error { return err } defer os.RemoveAll(super.tempdir) - if err := os.Mkdir(filepath.Join(super.tempdir, "bin"), 0777); err != nil { + if err := os.Mkdir(filepath.Join(super.tempdir, "bin"), 0755); err != nil { return err } // Fill in any missing config keys, and write the resulting // config in the temp dir for child services to use. - err = super.autofillConfig(cfg, super.logger) + err = super.autofillConfig(cfg) if err != nil { return err } - conffile, err := os.OpenFile(filepath.Join(super.tempdir, "config.yml"), os.O_CREATE|os.O_WRONLY, 0777) + conffile, err := os.OpenFile(filepath.Join(super.tempdir, "config.yml"), os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } @@ -123,12 +122,11 @@ func (super *Supervisor) run(cfg *arvados.Config) error { super.configfile = conffile.Name() super.environ = os.Environ() - super.cleanEnv() + super.cleanEnv([]string{"ARVADOS_"}) super.setEnv("ARVADOS_CONFIG", super.configfile) super.setEnv("RAILS_ENV", super.ClusterType) super.setEnv("TMPDIR", super.tempdir) super.prependEnv("PATH", filepath.Join(super.tempdir, "bin")+":") - super.prependEnv("PATH", filepath.Join(super.LibPath, "bin")+":") super.cluster, err = cfg.GetCluster("") if err != nil { @@ -164,16 +162,7 @@ func (super *Supervisor) run(cfg *arvados.Config) error { } else { return errors.New("specifying a version to run is not yet supported") } - for _, dir := range []string{super.LibPath, filepath.Join(super.LibPath, "bin")} { - if _, err = os.Stat(filepath.Join(dir, ".")); os.IsNotExist(err) { - err = os.Mkdir(dir, 0755) - if err != nil { - return err - } - } else if err != nil { - return err - } - } + _, err = super.installGoProgram(super.ctx, "cmd/arvados-server") if err != nil { return err @@ -307,17 +296,11 @@ func (super *Supervisor) prependEnv(key, prepend string) { super.environ = append(super.environ, key+"="+prepend) } -var cleanEnvPrefixes = []string{ - "GEM_HOME=", - "GEM_PATH=", - "ARVADOS_", -} - -func (super *Supervisor) cleanEnv() { +func (super *Supervisor) cleanEnv(prefixes []string) { var cleaned []string for _, s := range super.environ { drop := false - for _, p := range cleanEnvPrefixes { + for _, p := range prefixes { if strings.HasPrefix(s, p) { drop = true break @@ -365,17 +348,29 @@ func (super *Supervisor) installGoProgram(ctx context.Context, srcpath string) ( return binfile, err } +func (super *Supervisor) usingRVM() bool { + return os.Getenv("rvm_path") != "" +} + func (super *Supervisor) setupRubyEnv() error { - cmd := exec.Command("gem", "env", "gempath") - cmd.Env = super.environ - buf, err := cmd.Output() // /var/lib/arvados/.gem/ruby/2.5.0/bin:... - if err != nil || len(buf) == 0 { - return fmt.Errorf("gem env gempath: %v", err) - } - gempath := string(bytes.Split(buf, []byte{':'})[0]) - super.prependEnv("PATH", gempath+"/bin:") - super.setEnv("GEM_HOME", gempath) - super.setEnv("GEM_PATH", gempath) + if !super.usingRVM() { + // (If rvm is in use, assume the caller has everything + // set up as desired) + super.cleanEnv([]string{ + "GEM_HOME=", + "GEM_PATH=", + }) + cmd := exec.Command("gem", "env", "gempath") + cmd.Env = super.environ + buf, err := cmd.Output() // /var/lib/arvados/.gem/ruby/2.5.0/bin:... + if err != nil || len(buf) == 0 { + return fmt.Errorf("gem env gempath: %v", err) + } + gempath := string(bytes.Split(buf, []byte{':'})[0]) + super.prependEnv("PATH", gempath+"/bin:") + super.setEnv("GEM_HOME", gempath) + super.setEnv("GEM_PATH", gempath) + } // Passenger install doesn't work unless $HOME is ~user u, err := user.Current() if err != nil { @@ -412,9 +407,9 @@ func (super *Supervisor) RunProgram(ctx context.Context, dir string, output io.W super.logger.WithField("command", cmdline).WithField("dir", dir).Info("executing") logprefix := strings.TrimPrefix(prog, super.tempdir+"/bin/") - if prog == "bundle" && len(args) > 2 && args[0] == "exec" { + if logprefix == "bundle" && len(args) > 2 && args[0] == "exec" { logprefix = args[1] - } else if prog == "arvados-server" && len(args) > 1 { + } else if logprefix == "arvados-server" && len(args) > 1 { logprefix = args[0] } if !strings.HasPrefix(dir, "/") { @@ -495,15 +490,15 @@ func (super *Supervisor) RunProgram(ctx context.Context, dir string, output io.W return nil } -func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLogger) error { +func (super *Supervisor) autofillConfig(cfg *arvados.Config) error { cluster, err := cfg.GetCluster("") if err != nil { return err } usedPort := map[string]bool{} - nextPort := func() string { + nextPort := func(host string) string { for { - port, err := availablePort(super.ListenHost + ":0") + port, err := availablePort(host) if err != nil { panic(err) } @@ -523,11 +518,7 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog h = super.ListenHost } if p == "0" { - p, err = availablePort(":0") - if err != nil { - return err - } - usedPort[p] = true + p = nextPort(h) } cluster.Services.Controller.ExternalURL = arvados.URL{Scheme: "https", Host: net.JoinHostPort(h, p)} } @@ -554,11 +545,11 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog svc == &cluster.Services.WebDAVDownload || svc == &cluster.Services.Websocket || svc == &cluster.Services.Workbench1) { - svc.ExternalURL = arvados.URL{Scheme: "https", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort())} + svc.ExternalURL = arvados.URL{Scheme: "https", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost))} } if len(svc.InternalURLs) == 0 { svc.InternalURLs = map[arvados.URL]arvados.ServiceInstance{ - arvados.URL{Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort())}: arvados.ServiceInstance{}, + arvados.URL{Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost))}: arvados.ServiceInstance{}, } } } @@ -586,7 +577,7 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog } 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())}] = arvados.ServiceInstance{} + cluster.Services.Keepstore.InternalURLs[arvados.URL{Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost))}] = arvados.ServiceInstance{} // Create a directory-backed volume for each keepstore // process. @@ -597,7 +588,7 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog if _, err = os.Stat(datadir + "/."); err == nil { } else if !os.IsNotExist(err) { return err - } else if err = os.Mkdir(datadir, 0777); err != nil { + } else if err = os.Mkdir(datadir, 0755); err != nil { return err } cluster.Volumes[fmt.Sprintf(cluster.ClusterID+"-nyw5e-%015d", volnum)] = arvados.Volume{ @@ -613,7 +604,7 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog cluster.PostgreSQL.Connection = arvados.PostgreSQLConnection{ "client_encoding": "utf8", "host": "localhost", - "port": nextPort(), + "port": nextPort(super.ListenHost), "dbname": "arvados_test", "user": "arvados", "password": "insecure_arvados_test", @@ -624,6 +615,19 @@ func (super *Supervisor) autofillConfig(cfg *arvados.Config, log logrus.FieldLog return nil } +func addrIsLocal(addr string) (bool, error) { + return true, nil + listener, err := net.Listen("tcp", addr) + if err == nil { + listener.Close() + return true, nil + } else if strings.Contains(err.Error(), "cannot assign requested address") { + return false, nil + } else { + return false, err + } +} + func randomHexString(chars int) string { b := make([]byte, chars/2) _, err := rand.Read(b) @@ -634,6 +638,9 @@ func randomHexString(chars int) string { } func internalPort(svc arvados.Service) (string, error) { + if len(svc.InternalURLs) > 1 { + return "", errors.New("internalPort() doesn't work with multiple InternalURLs") + } for u := range svc.InternalURLs { if _, p, err := net.SplitHostPort(u.Host); err != nil { return "", err @@ -660,8 +667,8 @@ func externalPort(svc arvados.Service) (string, error) { } } -func availablePort(addr string) (string, error) { - ln, err := net.Listen("tcp", addr) +func availablePort(host string) (string, error) { + ln, err := net.Listen("tcp", net.JoinHostPort(host, "0")) if err != nil { return "", err }