Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: appengine/swarming/tools/start_bot.py

Issue 2911193003: Expose named caches as dimensions. (Closed)
Patch Set: Fixed smoke test Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/swarming/swarming_bot/api/os_utilities.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2015 The LUCI Authors. All rights reserved. 2 # Copyright 2015 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 """Starts a local bot to connect to a local server.""" 6 """Starts a local bot to connect to a local server."""
7 7
8 import glob 8 import glob
9 import logging 9 import logging
10 import os 10 import os
11 import signal 11 import signal
12 import socket 12 import socket
13 import sys 13 import sys
14 import tempfile 14 import tempfile
15 import urllib 15 import urllib
16 16
17 17
18 THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 18 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
19 CLIENT_DIR = os.path.join(THIS_DIR, '..', '..', '..', 'client') 19 CLIENT_DIR = os.path.join(THIS_DIR, '..', '..', '..', 'client')
20 sys.path.insert(0, CLIENT_DIR) 20 sys.path.insert(0, CLIENT_DIR)
21 from third_party.depot_tools import fix_encoding 21 from third_party.depot_tools import fix_encoding
22 from utils import file_path 22 from utils import file_path
23 from utils import subprocess42 23 from utils import subprocess42
24 sys.path.pop(0) 24 sys.path.pop(0)
25 25
26 26
27 def _safe_rm(path):
28 if os.path.exists(path):
29 try:
30 file_path.rmtree(path)
31 except OSError as e:
32 logging.error('Failed to delete %s: %s', path, e)
33
34
27 class LocalBot(object): 35 class LocalBot(object):
28 """A local running Swarming bot. 36 """A local running Swarming bot.
29 37
30 It creates its own temporary directory to download the zip and run tasks 38 It creates its own temporary directory to download the zip and run tasks
31 locally. 39 locally.
32 """ 40 """
33 def __init__(self, swarming_server_url, redirect=True): 41 def __init__(self, swarming_server_url, redirect=True):
34 self._tmpdir = tempfile.mkdtemp(prefix='swarming_bot') 42 # It is deleted in self.stop(False).
43 self._botdir = tempfile.mkdtemp(prefix='swarming_bot')
35 self._swarming_server_url = swarming_server_url 44 self._swarming_server_url = swarming_server_url
36 self._proc = None 45 self._proc = None
37 self._logs = {} 46 self._logs = {}
38 self._redirect = redirect 47 self._redirect = redirect
39 48
40 def wipe_cache(self): 49 def wipe_cache(self, restart):
41 """Blows away this bot's cache.""" 50 """Blows away this bot's cache and restart it.
42 for i in ('c', 'isolated_cache'): 51
43 cache_dir = os.path.join(self._tmpdir, i) 52 There's just too much risk of the bot failing over so it's not worth not
44 if os.path.exists(cache_dir): 53 restarting it.
45 try: 54 """
46 file_path.rmtree(cache_dir) 55 if restart:
47 except OSError: 56 logging.info('wipe_cache(): Restarting the bot')
48 logging.info('Failed to deleted %s', cache_dir) 57 self.stop(True)
58 # Deletion needs to happen while the bot is not running to ensure no side
59 # effect.
60 # These values are from ./swarming_bot/bot_code/bot_main.py.
61 _safe_rm(os.path.join(self._botdir, 'c'))
62 _safe_rm(os.path.join(self._botdir, 'isolated_cache'))
63 self.start()
64 else:
65 logging.info('wipe_cache(): wiping cache without telling the bot')
66 _safe_rm(os.path.join(self._botdir, 'c'))
67 _safe_rm(os.path.join(self._botdir, 'isolated_cache'))
49 68
50 @property 69 @property
51 def bot_id(self): 70 def bot_id(self):
52 # TODO(maruel): Big assumption. 71 # TODO(maruel): Big assumption.
53 return socket.getfqdn().split('.')[0] 72 return socket.getfqdn().split('.')[0]
54 73
55 @property 74 @property
56 def log(self): 75 def log(self):
57 """Returns the log output. Only set after calling stop().""" 76 """Returns the log output. Only set after calling stop()."""
58 return '\n'.join(self._logs.itervalues()) if self._logs else None 77 return '\n'.join(self._logs.itervalues()) if self._logs else None
59 78
60 def start(self): 79 def start(self):
61 """Starts the local Swarming bot.""" 80 """Starts the local Swarming bot."""
62 assert not self._proc 81 assert not self._proc
63 bot_zip = os.path.join(self._tmpdir, 'swarming_bot.zip') 82 bot_zip = os.path.join(self._botdir, 'swarming_bot.zip')
64 urllib.urlretrieve(self._swarming_server_url + '/bot_code', bot_zip) 83 urllib.urlretrieve(self._swarming_server_url + '/bot_code', bot_zip)
65 cmd = [sys.executable, bot_zip, 'start_slave'] 84 cmd = [sys.executable, bot_zip, 'start_slave']
66 if self._redirect: 85 if self._redirect:
67 logs = os.path.join(self._tmpdir, 'logs') 86 logs = os.path.join(self._botdir, 'logs')
68 if not os.path.isdir(logs): 87 if not os.path.isdir(logs):
69 os.mkdir(logs) 88 os.mkdir(logs)
70 with open(os.path.join(logs, 'bot_stdout.log'), 'wb') as f: 89 with open(os.path.join(logs, 'bot_stdout.log'), 'wb') as f:
71 self._proc = subprocess42.Popen( 90 self._proc = subprocess42.Popen(
72 cmd, cwd=self._tmpdir, stdout=f, stderr=f, detached=True) 91 cmd, cwd=self._botdir, stdout=f, stderr=f, detached=True)
73 else: 92 else:
74 self._proc = subprocess42.Popen(cmd, cwd=self._tmpdir, detached=True) 93 self._proc = subprocess42.Popen(cmd, cwd=self._botdir, detached=True)
75 94
76 def stop(self, leak): 95 def stop(self, leak):
77 """Stops the local Swarming bot. Returns the process exit code.""" 96 """Stops the local Swarming bot. Returns the process exit code."""
78 if not self._proc: 97 if not self._proc:
79 return None 98 return None
80 if self._proc.poll() is None: 99 if self._proc.poll() is None:
81 try: 100 try:
82 self._proc.send_signal(signal.SIGTERM) 101 self._proc.send_signal(signal.SIGTERM)
83 # TODO(maruel): SIGKILL after N seconds. 102 # TODO(maruel): SIGKILL after N seconds.
84 self._proc.wait() 103 self._proc.wait()
85 except OSError: 104 except OSError:
86 pass 105 pass
87 exit_code = self._proc.returncode 106 exit_code = self._proc.returncode
88 if self._tmpdir: 107 if self._botdir:
89 for i in sorted(glob.glob(os.path.join(self._tmpdir, 'logs', '*.log'))): 108 for i in sorted(glob.glob(os.path.join(self._botdir, 'logs', '*.log'))):
90 self._read_log(i) 109 self._read_log(i)
91 if not leak: 110 if not leak:
92 try: 111 try:
93 file_path.rmtree(self._tmpdir) 112 file_path.rmtree(self._botdir)
94 except OSError: 113 except OSError:
95 print >> sys.stderr, 'Leaking %s' % self._tmpdir 114 print >> sys.stderr, 'Leaking %s' % self._botdir
96 self._tmpdir = None
97 self._proc = None 115 self._proc = None
98 return exit_code 116 return exit_code
99 117
100 def poll(self): 118 def poll(self):
101 """Polls the process to know if it exited.""" 119 """Polls the process to know if it exited."""
102 self._proc.poll() 120 if self._proc:
121 self._proc.poll()
103 122
104 def wait(self, timeout=None): 123 def wait(self, timeout=None):
105 """Waits for the process to normally exit.""" 124 """Waits for the process to normally exit."""
106 return self._proc.wait(timeout) 125 if self._proc:
126 return self._proc.wait(timeout)
107 127
108 def kill(self): 128 def kill(self):
109 """Kills the child forcibly.""" 129 """Kills the child forcibly."""
110 if self._proc: 130 if self._proc:
111 self._proc.kill() 131 self._proc.kill()
112 132
113 def dump_log(self): 133 def dump_log(self):
114 """Prints dev_appserver log to stderr, works only if app is stopped.""" 134 """Prints dev_appserver log to stderr, works only if app is stopped."""
115 print >> sys.stderr, '-' * 60 135 print >> sys.stderr, '-' * 60
116 print >> sys.stderr, 'swarming_bot log' 136 print >> sys.stderr, 'swarming_bot log'
(...skipping 27 matching lines...) Expand all
144 bot.dump_log() 164 bot.dump_log()
145 except KeyboardInterrupt: 165 except KeyboardInterrupt:
146 print >> sys.stderr, '<Ctrl-C> received; stopping bot' 166 print >> sys.stderr, '<Ctrl-C> received; stopping bot'
147 finally: 167 finally:
148 exit_code = bot.stop(False) 168 exit_code = bot.stop(False)
149 return exit_code 169 return exit_code
150 170
151 171
152 if __name__ == '__main__': 172 if __name__ == '__main__':
153 sys.exit(main()) 173 sys.exit(main())
OLDNEW
« no previous file with comments | « appengine/swarming/swarming_bot/api/os_utilities.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698