1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage build 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "os" 20*333d2b36SAndroid Build Coastguard Worker "path/filepath" 21*333d2b36SAndroid Build Coastguard Worker "runtime" 22*333d2b36SAndroid Build Coastguard Worker "strings" 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Worker "android/soong/remoteexec" 25*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/metrics" 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Workerconst ( 29*333d2b36SAndroid Build Coastguard Worker rbeLeastNProcs = 2500 30*333d2b36SAndroid Build Coastguard Worker rbeLeastNFiles = 16000 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker // prebuilt RBE binaries 33*333d2b36SAndroid Build Coastguard Worker bootstrapCmd = "bootstrap" 34*333d2b36SAndroid Build Coastguard Worker 35*333d2b36SAndroid Build Coastguard Worker // RBE metrics proto buffer file 36*333d2b36SAndroid Build Coastguard Worker rbeMetricsPBFilename = "rbe_metrics.pb" 37*333d2b36SAndroid Build Coastguard Worker 38*333d2b36SAndroid Build Coastguard Worker defaultOutDir = "out" 39*333d2b36SAndroid Build Coastguard Worker) 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Workerfunc rbeCommand(ctx Context, config Config, rbeCmd string) string { 42*333d2b36SAndroid Build Coastguard Worker var cmdPath string 43*333d2b36SAndroid Build Coastguard Worker if rbeDir := config.rbeDir(); rbeDir != "" { 44*333d2b36SAndroid Build Coastguard Worker cmdPath = filepath.Join(rbeDir, rbeCmd) 45*333d2b36SAndroid Build Coastguard Worker } else { 46*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("rbe command path not found") 47*333d2b36SAndroid Build Coastguard Worker } 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Worker if _, err := os.Stat(cmdPath); err != nil && os.IsNotExist(err) { 50*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("rbe command %q not found", rbeCmd) 51*333d2b36SAndroid Build Coastguard Worker } 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker return cmdPath 54*333d2b36SAndroid Build Coastguard Worker} 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Workerfunc getRBEVars(ctx Context, config Config) map[string]string { 57*333d2b36SAndroid Build Coastguard Worker vars := map[string]string{ 58*333d2b36SAndroid Build Coastguard Worker "RBE_log_dir": config.rbeProxyLogsDir(), 59*333d2b36SAndroid Build Coastguard Worker "RBE_re_proxy": config.rbeReproxy(), 60*333d2b36SAndroid Build Coastguard Worker "RBE_exec_root": config.rbeExecRoot(), 61*333d2b36SAndroid Build Coastguard Worker "RBE_output_dir": config.rbeProxyLogsDir(), 62*333d2b36SAndroid Build Coastguard Worker "RBE_proxy_log_dir": config.rbeProxyLogsDir(), 63*333d2b36SAndroid Build Coastguard Worker "RBE_cache_dir": config.rbeCacheDir(), 64*333d2b36SAndroid Build Coastguard Worker "RBE_download_tmp_dir": config.rbeDownloadTmpDir(), 65*333d2b36SAndroid Build Coastguard Worker "RBE_platform": "container-image=" + remoteexec.DefaultImage, 66*333d2b36SAndroid Build Coastguard Worker } 67*333d2b36SAndroid Build Coastguard Worker if config.StartRBE() { 68*333d2b36SAndroid Build Coastguard Worker name, err := config.rbeSockAddr(absPath(ctx, config.rbeTmpDir())) 69*333d2b36SAndroid Build Coastguard Worker if err != nil { 70*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Error retrieving socket address: %v", err) 71*333d2b36SAndroid Build Coastguard Worker return nil 72*333d2b36SAndroid Build Coastguard Worker } 73*333d2b36SAndroid Build Coastguard Worker vars["RBE_server_address"] = fmt.Sprintf("unix://%v", name) 74*333d2b36SAndroid Build Coastguard Worker } 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Worker rf := 1.0 77*333d2b36SAndroid Build Coastguard Worker if config.Parallel() < runtime.NumCPU() { 78*333d2b36SAndroid Build Coastguard Worker rf = float64(config.Parallel()) / float64(runtime.NumCPU()) 79*333d2b36SAndroid Build Coastguard Worker } 80*333d2b36SAndroid Build Coastguard Worker vars["RBE_local_resource_fraction"] = fmt.Sprintf("%.2f", rf) 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Worker k, v := config.rbeAuth() 83*333d2b36SAndroid Build Coastguard Worker vars[k] = v 84*333d2b36SAndroid Build Coastguard Worker return vars 85*333d2b36SAndroid Build Coastguard Worker} 86*333d2b36SAndroid Build Coastguard Worker 87*333d2b36SAndroid Build Coastguard Workerfunc cleanupRBELogsDir(ctx Context, config Config) { 88*333d2b36SAndroid Build Coastguard Worker if !config.shouldCleanupRBELogsDir() { 89*333d2b36SAndroid Build Coastguard Worker return 90*333d2b36SAndroid Build Coastguard Worker } 91*333d2b36SAndroid Build Coastguard Worker 92*333d2b36SAndroid Build Coastguard Worker rbeTmpDir := config.rbeProxyLogsDir() 93*333d2b36SAndroid Build Coastguard Worker if err := os.RemoveAll(rbeTmpDir); err != nil { 94*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "\033[33mUnable to remove RBE log directory: ", err, "\033[0m") 95*333d2b36SAndroid Build Coastguard Worker } 96*333d2b36SAndroid Build Coastguard Worker} 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Workerfunc checkRBERequirements(ctx Context, config Config) { 99*333d2b36SAndroid Build Coastguard Worker if !config.GoogleProdCredsExist() && prodCredsAuthType(config) { 100*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Unable to start RBE reproxy\nFAILED: Missing LOAS credentials.") 101*333d2b36SAndroid Build Coastguard Worker } 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Worker if u := ulimitOrFatal(ctx, config, "-u"); u < rbeLeastNProcs { 104*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, rbeLeastNProcs) 105*333d2b36SAndroid Build Coastguard Worker } 106*333d2b36SAndroid Build Coastguard Worker if n := ulimitOrFatal(ctx, config, "-n"); n < rbeLeastNFiles { 107*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, rbeLeastNFiles) 108*333d2b36SAndroid Build Coastguard Worker } 109*333d2b36SAndroid Build Coastguard Worker if _, err := os.Stat(config.rbeProxyLogsDir()); os.IsNotExist(err) { 110*333d2b36SAndroid Build Coastguard Worker if err := os.MkdirAll(config.rbeProxyLogsDir(), 0744); err != nil { 111*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Unable to create logs dir (%v) for RBE: %v", config.rbeProxyLogsDir, err) 112*333d2b36SAndroid Build Coastguard Worker } 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker} 115*333d2b36SAndroid Build Coastguard Worker 116*333d2b36SAndroid Build Coastguard Workerfunc startRBE(ctx Context, config Config) { 117*333d2b36SAndroid Build Coastguard Worker ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap") 118*333d2b36SAndroid Build Coastguard Worker defer ctx.EndTrace() 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker ctx.Status.Status("Starting rbe...") 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd)) 123*333d2b36SAndroid Build Coastguard Worker 124*333d2b36SAndroid Build Coastguard Worker if output, err := cmd.CombinedOutput(); err != nil { 125*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Unable to start RBE reproxy\nFAILED: RBE bootstrap failed with: %v\n%s\n", err, output) 126*333d2b36SAndroid Build Coastguard Worker } 127*333d2b36SAndroid Build Coastguard Worker} 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Workerfunc stopRBE(ctx Context, config Config) { 130*333d2b36SAndroid Build Coastguard Worker cmd := Command(ctx, config, "stopRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd), "-shutdown") 131*333d2b36SAndroid Build Coastguard Worker output, err := cmd.CombinedOutput() 132*333d2b36SAndroid Build Coastguard Worker if err != nil { 133*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("rbe bootstrap with shutdown failed with: %v\n%s\n", err, output) 134*333d2b36SAndroid Build Coastguard Worker } 135*333d2b36SAndroid Build Coastguard Worker 136*333d2b36SAndroid Build Coastguard Worker if !config.Environment().IsEnvTrue("ANDROID_QUIET_BUILD") && len(output) > 0 { 137*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 138*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, fmt.Sprintf("%s", output)) 139*333d2b36SAndroid Build Coastguard Worker } 140*333d2b36SAndroid Build Coastguard Worker} 141*333d2b36SAndroid Build Coastguard Worker 142*333d2b36SAndroid Build Coastguard Workerfunc prodCredsAuthType(config Config) bool { 143*333d2b36SAndroid Build Coastguard Worker authVar, val := config.rbeAuth() 144*333d2b36SAndroid Build Coastguard Worker if strings.Contains(authVar, "use_google_prod_creds") && val != "" && val != "false" { 145*333d2b36SAndroid Build Coastguard Worker return true 146*333d2b36SAndroid Build Coastguard Worker } 147*333d2b36SAndroid Build Coastguard Worker return false 148*333d2b36SAndroid Build Coastguard Worker} 149*333d2b36SAndroid Build Coastguard Worker 150*333d2b36SAndroid Build Coastguard Worker// Check whether proper auth exists for RBE builds run within a 151*333d2b36SAndroid Build Coastguard Worker// Google dev environment. 152*333d2b36SAndroid Build Coastguard Workerfunc CheckProdCreds(ctx Context, config Config) { 153*333d2b36SAndroid Build Coastguard Worker if !config.IsGooglerEnvironment() { 154*333d2b36SAndroid Build Coastguard Worker return 155*333d2b36SAndroid Build Coastguard Worker } 156*333d2b36SAndroid Build Coastguard Worker if !config.StubbyExists() && prodCredsAuthType(config) { 157*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 158*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, fmt.Sprintf("\033[33mWARNING: %q binary not found in $PATH, follow go/build-fast-without-stubby instead for authenticating with RBE.\033[0m", "stubby")) 159*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 160*333d2b36SAndroid Build Coastguard Worker return 161*333d2b36SAndroid Build Coastguard Worker } 162*333d2b36SAndroid Build Coastguard Worker} 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Worker// DumpRBEMetrics creates a metrics protobuf file containing RBE related metrics. 165*333d2b36SAndroid Build Coastguard Worker// The protobuf file is created if RBE is enabled and the proxy service has 166*333d2b36SAndroid Build Coastguard Worker// started. The proxy service is shutdown in order to dump the RBE metrics to the 167*333d2b36SAndroid Build Coastguard Worker// protobuf file. 168*333d2b36SAndroid Build Coastguard Workerfunc DumpRBEMetrics(ctx Context, config Config, filename string) { 169*333d2b36SAndroid Build Coastguard Worker ctx.BeginTrace(metrics.RunShutdownTool, "dump_rbe_metrics") 170*333d2b36SAndroid Build Coastguard Worker defer ctx.EndTrace() 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Worker // Remove the previous metrics file in case there is a failure or RBE has been 173*333d2b36SAndroid Build Coastguard Worker // disable for this run. 174*333d2b36SAndroid Build Coastguard Worker os.Remove(filename) 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Worker // If RBE is not enabled then there are no metrics to generate. 177*333d2b36SAndroid Build Coastguard Worker // If RBE does not require to start, the RBE proxy maybe started 178*333d2b36SAndroid Build Coastguard Worker // manually for debugging purpose and can generate the metrics 179*333d2b36SAndroid Build Coastguard Worker // afterwards. 180*333d2b36SAndroid Build Coastguard Worker if !config.StartRBE() { 181*333d2b36SAndroid Build Coastguard Worker return 182*333d2b36SAndroid Build Coastguard Worker } 183*333d2b36SAndroid Build Coastguard Worker 184*333d2b36SAndroid Build Coastguard Worker outputDir := config.rbeProxyLogsDir() 185*333d2b36SAndroid Build Coastguard Worker if outputDir == "" { 186*333d2b36SAndroid Build Coastguard Worker ctx.Fatal("RBE output dir variable not defined. Aborting metrics dumping.") 187*333d2b36SAndroid Build Coastguard Worker } 188*333d2b36SAndroid Build Coastguard Worker metricsFile := filepath.Join(outputDir, rbeMetricsPBFilename) 189*333d2b36SAndroid Build Coastguard Worker 190*333d2b36SAndroid Build Coastguard Worker // Stop the proxy first in order to generate the RBE metrics protobuf file. 191*333d2b36SAndroid Build Coastguard Worker stopRBE(ctx, config) 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Worker if metricsFile == filename { 194*333d2b36SAndroid Build Coastguard Worker return 195*333d2b36SAndroid Build Coastguard Worker } 196*333d2b36SAndroid Build Coastguard Worker if _, err := copyFile(metricsFile, filename); err != nil { 197*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err) 198*333d2b36SAndroid Build Coastguard Worker } 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker// PrintOutDirWarning prints a warning to indicate to the user that 202*333d2b36SAndroid Build Coastguard Worker// setting output directory to a path other than "out" in an RBE enabled 203*333d2b36SAndroid Build Coastguard Worker// build can cause slow builds. 204*333d2b36SAndroid Build Coastguard Workerfunc PrintOutDirWarning(ctx Context, config Config) { 205*333d2b36SAndroid Build Coastguard Worker if config.UseRBE() && config.OutDir() != defaultOutDir { 206*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 207*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "\033[33mWARNING:\033[0m") 208*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, fmt.Sprintf("Setting OUT_DIR to a path other than %v may result in slow RBE builds.", defaultOutDir)) 209*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "See http://go/android_rbe_out_dir for a workaround.") 210*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 211*333d2b36SAndroid Build Coastguard Worker } 212*333d2b36SAndroid Build Coastguard Worker} 213