1#!/usr/bin/env python 2# 3# Copyright 2021 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the', help='License'); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an', help='AS IS' BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17 18import itertools 19import logging 20import os 21from pathlib import Path 22import platform 23import shutil 24import socket 25from environment import get_default_environment 26from utils import AOSP_ROOT, run 27 28 29# A class that is responsible for configuring the server when running the build. 30class ServerConfig(object): 31 REDIS_SCCACHE_IP = "34.145.83.254" 32 REDIS_PORT = 443 33 34 def __in_gce(self): 35 """Queries the magic url to determine if we are in GCE""" 36 try: 37 # TODO(jansene): Remove once windows buildbots are using PY3 38 import urllib.request 39 40 with urllib.request.urlopen("http://metadata.google.internal") as r: 41 return r.getheader("Metadata-Flavor") == "Google" 42 except: 43 logging.info("Unable to query magic url, we are not in gce.") 44 return False 45 46 def __can_use_redis(self): 47 """Tries to connect to the redis cache.""" 48 try: 49 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 50 s.settimeout(2.5) 51 s.connect((ServerConfig.REDIS_SCCACHE_IP, ServerConfig.REDIS_PORT)) 52 return True 53 except: 54 logging.exception("Unable to connect to redis, we are not in corp.") 55 return False 56 57 def __init__(self, presubmit, args): 58 self.args = args 59 self.presubmit = presubmit 60 self.env = get_default_environment(AOSP_ROOT) 61 self.target = platform.system().lower() 62 search_dir = Path( 63 AOSP_ROOT, 64 "prebuilts", 65 "android-emulator-build", 66 "common", 67 "sccache", 68 f"{self.target}-x86_64", 69 ).absolute() 70 self.sccache = shutil.which("sccache", path=search_dir) 71 72 def get_env(self): 73 return self.env 74 75 def __enter__(self): 76 """Configure cache, report statistics and setup vscode""" 77 # Let's make sure we have ninja on the path. 78 79 if self.__in_gce(): 80 # Use a bucket in gce. Make sure the default service account has R/W 81 # access to gs://emu-dev-sccache 82 self.env["SCCACHE_GCS_BUCKET"] = "emu-dev-sccache" 83 self.env["SCCACHE_GCS_OAUTH_URL"] = ( 84 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" 85 ) 86 self.env["SCCACHE_GCS_RW_MODE"] = "READ_WRITE" 87 elif self.__can_use_redis(): 88 # Lets try our redis cache. 89 self.env["SCCACHE_REDIS"] = "redis//{}:{}/1".format( 90 ServerConfig.REDIS_SCCACHE_IP, ServerConfig.REDIS_PORT 91 ) 92 93 # Configure logging, (debug logging is very verbose, and only needed if 94 # you wish to figure out why you have a lot of cache-misses) 95 self.env["SCCACHE_LOG"] = "info" 96 self.env["SCCACHE_ERROR_LOG"] = os.path.join( 97 self.args.dist_dir, "sccache.log" 98 ) 99 100 # We will terminate sccache upon completion 101 self.env["SCCACHE_IDLE_TIMEOUT"] = "0" 102 if self.sccache: 103 # This will print stats, and launch the server if needed 104 run([self.sccache, "--stop-server"], self.env, "scc", AOSP_ROOT, False) 105 run([self.sccache, "--start-server"], self.env, "scc", AOSP_ROOT, False) 106 107 return self 108 109 def __exit__(self, exc_type, exc_value, tb): 110 """Report cache statistics and stop the server.""" 111 if self.sccache: 112 run([self.sccache, "--stop-server"], self.env, "scc") 113