isolate_daemon.py (4380B)
1 # Copyright 2023 The Chromium Authors 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 """Sets up the isolate daemon environment to run test on the bots.""" 5 6 import os 7 import tempfile 8 9 from typing import Optional 10 11 from contextlib import AbstractContextManager 12 13 from common import get_ffx_isolate_dir,has_ffx_isolate_dir, \ 14 set_ffx_isolate_dir, is_daemon_running, \ 15 start_ffx_daemon, stop_ffx_daemon 16 from ffx_integration import ScopedFfxConfig 17 from modification_waiter import ModificationWaiter 18 19 20 class IsolateDaemon(AbstractContextManager): 21 """Sets up the environment of an isolate ffx daemon.""" 22 23 class IsolateDir(AbstractContextManager): 24 """Sets up the ffx isolate dir to a temporary folder if it's not set.""" 25 def __init__(self): 26 if has_ffx_isolate_dir(): 27 self._temp_dir = None 28 else: 29 self._temp_dir = tempfile.TemporaryDirectory() 30 31 def __enter__(self): 32 if self._temp_dir: 33 set_ffx_isolate_dir(self._temp_dir.__enter__()) 34 return self 35 36 def __exit__(self, exc_type, exc_value, traceback): 37 if self._temp_dir: 38 try: 39 self._temp_dir.__exit__(exc_type, exc_value, traceback) 40 except OSError: 41 # Ignore the errors when cleaning up the temporary folder. 42 pass 43 return False 44 45 class RepoProcessDir(AbstractContextManager): 46 """Sets up a temporary folder for the repository server process dir. 47 The default location, $XDG_STATE_HOME turns out to be in the 48 a binding to a directory on the host machine. The isolate directory is 49 a docker Volume. The performance of the isolate dir is much better than 50 the performance of using the volume based directory, especially on 51 arm64 hosts. 52 """ 53 def __init__(self): 54 # don't try to access the isolate dir at this point, it may not be 55 # set up yet. 56 self._process_dir_config = None 57 58 def __enter__(self): 59 self._process_dir_config = ScopedFfxConfig( 60 'repository.process_dir', 61 f'{get_ffx_isolate_dir()}/repo_proc') 62 self._process_dir_config.__enter__() 63 return self 64 65 def __exit__(self, exc_type, exc_value, traceback): 66 return self._process_dir_config.__exit__(exc_type, exc_value, 67 traceback) 68 69 def __init__(self, logs_dir: Optional[str]): 70 assert not has_ffx_isolate_dir() or not is_daemon_running() 71 self._inits = [ 72 self.IsolateDir(), 73 # The RepoProcess dir must be 'entered' after the IsolateDir, so the 74 # iso directory is set up first. 75 self.RepoProcessDir(), 76 ModificationWaiter(logs_dir), 77 # Keep the alphabetical order. 78 ScopedFfxConfig('ffx.isolated', 'true'), 79 ScopedFfxConfig('daemon.autostart', 'false'), 80 # fxb/126212: The timeout rate determines the timeout for each file 81 # transfer based on the size of the file / this rate (in MB). 82 # Decreasing the rate to 1 (from 5) increases the timeout in 83 # swarming, where large files can take longer to transfer. 84 ScopedFfxConfig('fastboot.flash.timeout_rate', '1'), 85 ScopedFfxConfig('fastboot.reboot.reconnect_timeout', '120'), 86 ScopedFfxConfig('fastboot.usb.disabled', 'true'), 87 ScopedFfxConfig('log.level', 'debug') 88 ] 89 if logs_dir: 90 self._inits.append(ScopedFfxConfig('log.dir', logs_dir)) 91 92 # Updating configurations to meet the requirement of isolate. 93 def __enter__(self): 94 # This environment variable needs to be set before stopping ffx daemon 95 # to avoid sending unnecessary analytics. 96 os.environ['FUCHSIA_ANALYTICS_DISABLED'] = '1' 97 stop_ffx_daemon() 98 for init in self._inits: 99 init.__enter__() 100 start_ffx_daemon() 101 return self 102 103 def __exit__(self, exc_type, exc_value, traceback): 104 for init in self._inits: 105 init.__exit__(exc_type, exc_value, traceback) 106 stop_ffx_daemon()