| OLD | NEW | 
|---|
| 1 # Copyright 2014 The LUCI Authors. All rights reserved. | 1 # Copyright 2014 The LUCI Authors. All rights reserved. | 
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 | 
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 """Swarming bot management, e.g. list of known bots and their state. | 5 """Swarming bot management, e.g. list of known bots and their state. | 
| 6 | 6 | 
| 7           +---------+ | 7           +---------+ | 
| 8           |BotRoot  | | 8           |BotRoot  | | 
| 9           |id=bot_id| | 9           |id=bot_id| | 
| 10           +---------+ | 10           +---------+ | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 21   happening for the bot. | 21   happening for the bot. | 
| 22 - BotInfo is a 'dump-only' entity used for UI, it permits quickly show the | 22 - BotInfo is a 'dump-only' entity used for UI, it permits quickly show the | 
| 23   state of every bots in an single query. It is basically a cache of the last | 23   state of every bots in an single query. It is basically a cache of the last | 
| 24   BotEvent and additionally updated on poll. It doesn't need to be updated in a | 24   BotEvent and additionally updated on poll. It doesn't need to be updated in a | 
| 25   transaction. | 25   transaction. | 
| 26 - BotSettings contains bot-specific settings. It must be updated in a | 26 - BotSettings contains bot-specific settings. It must be updated in a | 
| 27   transaction and contains admin-provided settings, contrary to the other | 27   transaction and contains admin-provided settings, contrary to the other | 
| 28   entities which are generated from data provided by the bot itself. | 28   entities which are generated from data provided by the bot itself. | 
| 29 """ | 29 """ | 
| 30 | 30 | 
|  | 31 import datetime | 
| 31 import hashlib | 32 import hashlib | 
| 32 | 33 | 
| 33 from google.appengine.ext import ndb | 34 from google.appengine.ext import ndb | 
| 34 | 35 | 
| 35 from components import datastore_utils | 36 from components import datastore_utils | 
| 36 from components import utils | 37 from components import utils | 
| 37 from server import config | 38 from server import config | 
| 38 from server import task_pack | 39 from server import task_pack | 
| 39 | 40 | 
| 40 | 41 | 
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 260   if order: | 261   if order: | 
| 261     query = query.order(BotEvent.key) | 262     query = query.order(BotEvent.key) | 
| 262   return query | 263   return query | 
| 263 | 264 | 
| 264 | 265 | 
| 265 def get_settings_key(bot_id): | 266 def get_settings_key(bot_id): | 
| 266   """Returns the BotSettings ndb.Key for a known bot.""" | 267   """Returns the BotSettings ndb.Key for a known bot.""" | 
| 267   return ndb.Key(BotSettings, 'settings', parent=get_root_key(bot_id)) | 268   return ndb.Key(BotSettings, 'settings', parent=get_root_key(bot_id)) | 
| 268 | 269 | 
| 269 | 270 | 
|  | 271 def filter_dimensions(q, dimensions): | 
|  | 272   """Filters a ndb.Query for BotInfo based on dimensions in the request.""" | 
|  | 273   for d in dimensions: | 
|  | 274     parts = d.split(':', 1) | 
|  | 275     if len(parts) != 2 or any(i.strip() != i or not i for i in parts): | 
|  | 276       raise ValueError('Invalid dimensions') | 
|  | 277     q = q.filter(BotInfo.dimensions_flat == d) | 
|  | 278   return q | 
|  | 279 | 
|  | 280 | 
|  | 281 def filter_availability(q, quarantined, is_dead, now): | 
|  | 282   """Filters a ndb.Query for BotInfo based on quarantined/is_dead.""" | 
|  | 283   if quarantined is not None: | 
|  | 284     q = q.filter(BotInfo.quarantined == quarantined) | 
|  | 285 | 
|  | 286   dt = datetime.timedelta(seconds=config.settings().bot_death_timeout_secs) | 
|  | 287   timeout = now - dt | 
|  | 288   if is_dead: | 
|  | 289     q = q.filter(BotInfo.last_seen_ts < timeout) | 
|  | 290   elif is_dead is not None: | 
|  | 291     q = q.filter(BotInfo.last_seen_ts > timeout) | 
|  | 292   return q | 
|  | 293 | 
|  | 294 | 
| 270 def bot_event( | 295 def bot_event( | 
| 271     event_type, bot_id, external_ip, authenticated_as, dimensions, state, | 296     event_type, bot_id, external_ip, authenticated_as, dimensions, state, | 
| 272     version, quarantined, task_id, task_name, **kwargs): | 297     version, quarantined, task_id, task_name, **kwargs): | 
| 273   """Records when a bot has queried for work. | 298   """Records when a bot has queried for work. | 
| 274 | 299 | 
| 275   Arguments: | 300   Arguments: | 
| 276   - event: event type. | 301   - event: event type. | 
| 277   - bot_id: bot id. | 302   - bot_id: bot id. | 
| 278   - external_ip: IP address as seen by the HTTP handler. | 303   - external_ip: IP address as seen by the HTTP handler. | 
| 279   - authenticated_as: bot identity as seen by the HTTP handler. | 304   - authenticated_as: bot identity as seen by the HTTP handler. | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 368   Returns: | 393   Returns: | 
| 369     Tuple (True to restart, text message explaining the reason). | 394     Tuple (True to restart, text message explaining the reason). | 
| 370   """ | 395   """ | 
| 371   # Periodically reboot bots to workaround OS level leaks (especially on Win). | 396   # Periodically reboot bots to workaround OS level leaks (especially on Win). | 
| 372   running_time = state.get('running_time', 0) | 397   running_time = state.get('running_time', 0) | 
| 373   assert isinstance(running_time, (int, float)) | 398   assert isinstance(running_time, (int, float)) | 
| 374   period = get_bot_reboot_period(bot_id, state) | 399   period = get_bot_reboot_period(bot_id, state) | 
| 375   if period and running_time > period: | 400   if period and running_time > period: | 
| 376     return True, 'Periodic reboot: running longer than %ds' % period | 401     return True, 'Periodic reboot: running longer than %ds' % period | 
| 377   return False, '' | 402   return False, '' | 
| OLD | NEW | 
|---|