X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/20d7bfd30b4c890246c7ad72d6c96f93417f12ee..86beb5fc2d508cef8e38ad0b4db8e14d68556dbb:/lib/install/init.go?ds=sidebyside diff --git a/lib/install/init.go b/lib/install/init.go index 792262b59a..11a62f18e9 100644 --- a/lib/install/init.go +++ b/lib/install/init.go @@ -13,6 +13,7 @@ import ( "flag" "fmt" "io" + "net/url" "os" "os/exec" "os/user" @@ -23,7 +24,9 @@ import ( "git.arvados.org/arvados.git/lib/cmd" "git.arvados.org/arvados.git/lib/config" + "git.arvados.org/arvados.git/lib/controller/rpc" "git.arvados.org/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/auth" "git.arvados.org/arvados.git/sdk/go/ctxlog" "github.com/lib/pq" ) @@ -108,6 +111,23 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read return 1 } + // Do the "create extension" thing early. This way, if there's + // no local postgresql server (a likely failure mode), we can + // bail out without any side effects, and the user can start + // over easily. + fmt.Fprintln(stderr, "installing pg_trgm postgresql extension...") + cmd := exec.CommandContext(ctx, "sudo", "-u", "postgres", "psql", "--quiet", + "-c", `CREATE EXTENSION IF NOT EXISTS pg_trgm`) + cmd.Dir = "/" + cmd.Stdout = stdout + cmd.Stderr = stderr + err = cmd.Run() + if err != nil { + err = fmt.Errorf("error preparing postgresql server: %w", err) + return 1 + } + fmt.Fprintln(stderr, "...done") + wwwuser, err := user.Lookup("www-data") if err != nil { err = fmt.Errorf("user.Lookup(%q): %w", "www-data", err) @@ -119,13 +139,15 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read } initcmd.PostgreSQLPassword = initcmd.RandomHex(32) + fmt.Fprintln(stderr, "creating data storage directory /var/lib/arvados/keep ...") err = os.Mkdir("/var/lib/arvados/keep", 0600) if err != nil && !os.IsExist(err) { err = fmt.Errorf("mkdir /var/lib/arvados/keep: %w", err) return 1 } - fmt.Fprintln(stderr, "created /var/lib/arvados/keep") + fmt.Fprintln(stderr, "...done") + fmt.Fprintln(stderr, "creating config file", conffile, "...") err = os.Mkdir(confdir, 0750) if err != nil && !os.IsExist(err) { err = fmt.Errorf("mkdir %s: %w", confdir, err) @@ -136,9 +158,9 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read err = fmt.Errorf("chown 0:%d %s: %w", wwwgid, confdir, err) return 1 } - f, err := os.OpenFile(conffile, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644) + f, err := os.OpenFile(conffile+".tmp", os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644) if err != nil { - err = fmt.Errorf("open %s: %w", conffile, err) + err = fmt.Errorf("open %s: %w", conffile+".tmp", err) return 1 } tmpl, err := template.New("config").Parse(`Clusters: @@ -257,18 +279,24 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read } err = tmpl.Execute(f, initcmd) if err != nil { - err = fmt.Errorf("%s: tmpl.Execute: %w", conffile, err) + err = fmt.Errorf("%s: tmpl.Execute: %w", conffile+".tmp", err) return 1 } err = f.Close() if err != nil { - err = fmt.Errorf("%s: close: %w", conffile, err) + err = fmt.Errorf("%s: close: %w", conffile+".tmp", err) return 1 } - fmt.Fprintln(stderr, "created", conffile) + err = os.Rename(conffile+".tmp", conffile) + if err != nil { + err = fmt.Errorf("rename %s -> %s: %w", conffile+".tmp", conffile, err) + return 1 + } + fmt.Fprintln(stderr, "...done") ldr := config.NewLoader(nil, logger) ldr.SkipLegacy = true + ldr.Path = conffile // load the file we just wrote, even if $ARVADOS_CONFIG is set cfg, err := ldr.Load() if err != nil { err = fmt.Errorf("%s: %w", conffile, err) @@ -279,12 +307,15 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read return 1 } + fmt.Fprintln(stderr, "creating postresql user and database...") err = initcmd.createDB(ctx, cluster.PostgreSQL.Connection, stderr) if err != nil { return 1 } + fmt.Fprintln(stderr, "...done") - cmd := exec.CommandContext(ctx, "sudo", "-u", "www-data", "-E", "HOME=/var/www", "PATH=/var/lib/arvados/bin:"+os.Getenv("PATH"), "/var/lib/arvados/bin/bundle", "exec", "rake", "db:setup") + fmt.Fprintln(stderr, "initializing database...") + cmd = exec.CommandContext(ctx, "sudo", "-u", "www-data", "-E", "HOME=/var/www", "PATH=/var/lib/arvados/bin:"+os.Getenv("PATH"), "/var/lib/arvados/bin/bundle", "exec", "rake", "db:setup") cmd.Dir = "/var/lib/arvados/railsapi" cmd.Stdout = stderr cmd.Stderr = stderr @@ -293,11 +324,11 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read err = fmt.Errorf("rake db:setup failed: %w", err) return 1 } - fmt.Fprintln(stderr, "initialized database") + fmt.Fprintln(stderr, "...done") if initcmd.Start { - fmt.Fprintln(stderr, "starting systemd service") - cmd := exec.CommandContext(ctx, "systemctl", "start", "--no-block", "arvados") + fmt.Fprintln(stderr, "starting systemd service...") + cmd := exec.CommandContext(ctx, "systemctl", "start", "arvados") cmd.Dir = "/" cmd.Stdout = stderr cmd.Stderr = stderr @@ -306,8 +337,22 @@ func (initcmd *initCommand) RunCommand(prog string, args []string, stdin io.Read err = fmt.Errorf("%v: %w", cmd.Args, err) return 1 } + fmt.Fprintln(stderr, "...done") + + fmt.Fprintln(stderr, "checking controller API endpoint...") + u := url.URL(cluster.Services.Controller.ExternalURL) + conn := rpc.NewConn(cluster.ClusterID, &u, cluster.TLS.Insecure, rpc.PassthroughTokenProvider) + ctx := auth.NewContext(context.Background(), auth.NewCredentials(cluster.SystemRootToken)) + _, err = conn.UserGetCurrent(ctx, arvados.GetOptions{}) + if err != nil { + err = fmt.Errorf("API request failed: %w", err) + return 1 + } + fmt.Fprintln(stderr, "...looks good") } + fmt.Fprintln(stderr, "Setup complete. You should now be able to log in to workbench2 at", cluster.Services.Workbench2.ExternalURL.String()) + return 0 } @@ -336,19 +381,16 @@ func (initcmd *initCommand) RandomHex(chars int) string { } func (initcmd *initCommand) createDB(ctx context.Context, dbconn arvados.PostgreSQLConnection, stderr io.Writer) error { - for _, sql := range []string{ - `CREATE USER ` + pq.QuoteIdentifier(dbconn["user"]) + ` WITH SUPERUSER ENCRYPTED PASSWORD ` + pq.QuoteLiteral(dbconn["password"]), - `CREATE DATABASE ` + pq.QuoteIdentifier(dbconn["dbname"]) + ` WITH TEMPLATE template0 ENCODING 'utf8'`, - `CREATE EXTENSION IF NOT EXISTS pg_trgm`, - } { - cmd := exec.CommandContext(ctx, "sudo", "-u", "postgres", "psql", "-c", sql) - cmd.Dir = "/" - cmd.Stdout = stderr - cmd.Stderr = stderr - err := cmd.Run() - if err != nil { - return fmt.Errorf("error setting up arvados user/database: %w", err) - } + cmd := exec.CommandContext(ctx, "sudo", "-u", "postgres", "psql", "--quiet", + "-c", `CREATE USER `+pq.QuoteIdentifier(dbconn["user"])+` WITH SUPERUSER ENCRYPTED PASSWORD `+pq.QuoteLiteral(dbconn["password"]), + "-c", `CREATE DATABASE `+pq.QuoteIdentifier(dbconn["dbname"])+` WITH TEMPLATE template0 ENCODING 'utf8'`, + ) + cmd.Dir = "/" + cmd.Stdout = stderr + cmd.Stderr = stderr + err := cmd.Run() + if err != nil { + return fmt.Errorf("error setting up arvados user/database: %w", err) } return nil }