| Index: appengine/swarming/server/config.py
|
| diff --git a/appengine/swarming/server/config.py b/appengine/swarming/server/config.py
|
| index 3f76daa32a967114e37d8c6272146365b9d44e41..c36f75d5d00176347b5a69fadb2fe3b0cfa89fce 100644
|
| --- a/appengine/swarming/server/config.py
|
| +++ b/appengine/swarming/server/config.py
|
| @@ -4,32 +4,108 @@
|
|
|
| """Instance specific settings."""
|
|
|
| -from google.appengine.ext import ndb
|
| +import logging
|
| +import posixpath
|
|
|
| -from components.datastore_utils import config
|
| +from components import config
|
| +from components import gitiles
|
| +from components import net
|
| +from components import utils
|
| +from components.config import validation
|
|
|
| +from proto import config_pb2
|
|
|
| -class GlobalConfig(config.GlobalConfig):
|
| - """Application wide settings."""
|
| - # id to inject into pages if applicable.
|
| - google_analytics = ndb.StringProperty(indexed=False, default='')
|
| +SETTINGS_CFG_FILENAME = 'settings.cfg'
|
|
|
| - # The number of seconds an old task can be deduped from.
|
| - reusable_task_age_secs = ndb.IntegerProperty(
|
| - indexed=False, default=7*24*60*60)
|
|
|
| - # The amount of time that has to pass before a machine is considered dead.
|
| - bot_death_timeout_secs = ndb.IntegerProperty(default=10*60)
|
| +ConfigApi = config.ConfigApi
|
|
|
| - # Enable ts_mon based monitoring.
|
| - enable_ts_monitoring = ndb.BooleanProperty(indexed=False, default=False)
|
|
|
| +@validation.self_rule(SETTINGS_CFG_FILENAME, config_pb2.SettingsCfg)
|
| +def validate_settings(cfg, ctx):
|
| + """Validates settings.cfg file against proto message schema."""
|
| + def within_year(value):
|
| + if value < 0:
|
| + ctx.error('cannot be negative')
|
| + elif value > 60 * 60 * 24 * 365:
|
| + ctx.error('cannot be more than a year')
|
|
|
| -def settings(fresh=False):
|
| - """Loads GlobalConfig or a default one if not present.
|
| + with ctx.prefix('bot_death_timeout_secs '):
|
| + within_year(cfg.bot_death_timeout_secs)
|
| + with ctx.prefix('reusable_task_age_secs '):
|
| + within_year(cfg.reusable_task_age_secs)
|
|
|
| - If fresh=True, a full fetch from NDB is done.
|
| +
|
| +@utils.memcache('config:get_configs_url', time=60)
|
| +def _get_configs_url():
|
| + """Returns URL where luci-config fetches configs from."""
|
| + url = None
|
| + try:
|
| + url = config.get_config_set_location(config.self_config_set())
|
| + except net.Error:
|
| + logging.info(
|
| + 'Could not get configs URL. Possibly config directory for this '
|
| + 'instance of swarming does not exist')
|
| + return url or 'about:blank'
|
| +
|
| +
|
| +def _gitiles_url(configs_url, rev, path):
|
| + """URL to a directory in gitiles -> URL to a file at concrete revision."""
|
| + try:
|
| + loc = gitiles.Location.parse(configs_url)
|
| + return str(loc._replace(
|
| + treeish=rev or loc.treeish,
|
| + path=posixpath.join(loc.path, path)))
|
| + except ValueError:
|
| + # Not a gitiles URL, return as is.
|
| + return configs_url
|
| +
|
| +
|
| +def _get_settings():
|
| + """Returns (rev, cfg) where cfg is a parsed SettingsCfg message.
|
| +
|
| + If config does not exists, returns (None, <cfg with defaults>).
|
| +
|
| + The config is cached in the datastore.
|
| """
|
| - if fresh:
|
| - GlobalConfig.clear_cache()
|
| - return GlobalConfig.cached()
|
| + rev = None
|
| + cfg = None
|
| + try:
|
| + # store_last_good=True tells config component to update the config file
|
| + # in a cron job. Here we just read from datastore.
|
| + rev, cfg = config.get_self_config(
|
| + SETTINGS_CFG_FILENAME, config_pb2.SettingsCfg, store_last_good=True)
|
| + except config.CannotLoadConfigError as ex:
|
| + logging.info('Could not load settings.cfg: %s; using defaults', ex)
|
| + if not cfg:
|
| + cfg = config_pb2.SettingsCfg(
|
| + reusable_task_age_secs=7*24*60*60,
|
| + bot_death_timeout_secs=10*60)
|
| + return rev, cfg
|
| +
|
| +
|
| +def settings_info():
|
| + """Returns information about the settings file.
|
| +
|
| + Returns a dict with keys:
|
| + 'cfg': parsed SettingsCfg message
|
| + 'rev': revision of cfg
|
| + 'rev_url': URL of a human-consumable page that displays the config
|
| + 'config_service_url': URL of the config_service.
|
| + """
|
| + rev, cfg = _get_settings()
|
| + rev_url = _gitiles_url(_get_configs_url(), rev, SETTINGS_CFG_FILENAME)
|
| + cfg_service_hostname = config.config_service_hostname()
|
| + return {
|
| + 'cfg': cfg,
|
| + 'rev': rev,
|
| + 'rev_url': rev_url,
|
| + 'config_service_url': (
|
| + 'https://%s' % cfg_service_hostname if cfg_service_hostname else ''
|
| + ),
|
| + }
|
| +
|
| +
|
| +def settings():
|
| + """Loads settings from an NDB-based cache or a default one if not present."""
|
| + return _get_settings()[1]
|
|
|