X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-base.git/blobdiff_plain/1eff7d13e6578fc1e4da25cd3e78c126ebe62ebd..58779732826ce6a4f91fdb8a55f0c7a480d1544e:/python/invirt/config.py diff --git a/python/invirt/config.py b/python/invirt/config.py index 7c2b805..86d9c8a 100644 --- a/python/invirt/config.py +++ b/python/invirt/config.py @@ -2,24 +2,69 @@ from __future__ import with_statement import json from invirt.common import * +import os from os import rename from os.path import getmtime from contextlib import closing import yaml +import re try: loader = yaml.CSafeLoader except: loader = yaml.SafeLoader -src_path = '/etc/invirt/master.yaml' -cache_path = '/var/lib/invirt/cache.json' -lock_path = '/var/lib/invirt/cache.lock' +src_path = '/etc/invirt/master.yaml' +src_dirpath = '/etc/invirt/conf.d' +cache_path = '/var/lib/invirt/cache.json' +lock_path = '/var/lib/invirt/cache.lock' + +def augment(d1, d2): + """Splice dict-tree d2 into d1. Return d1. + + Example: + >>> d = {'a': {'b': 1}, 'c': 2} + >>> augment(d, {'a': {'d': 3}}) + {'a': {'b', 1, 'd': 3}, 'c': 2} + >>> d + {'a': {'b', 1, 'd': 3}, 'c': 2} + """ + for k in d2: + if k in d1 and isinstance(d1[k], dict): + augment(d1[k], d2[k]) + else: + d1[k] = d2[k] + return d1 + +def run_parts_list(dirname): + """Reimplements Debian's run-parts --list. + + One difference from run-parts's behavior: run-parts --list /foo/ + will give output like /foo//bar, because Python code tends to expect this. + + Matches documented behavior of run-parts in debianutils v2.28.2, dated 2007. + """ + # From run-parts(8). + lanana_re = re.compile('^[a-z0-9]+$') + lsb_re = re.compile('^_?([a-z0-9_.]+-)+[a-z0-9]+$') + deb_cron_re = re.compile('^[a-z0-9][a-z0-9-]*$') + for name in os.listdir(dirname): + if lanana_re.match(name) or lsb_re.match(name) or deb_cron_re.match(name): + yield os.path.join(dirname, name) + +def list_files(): + yield src_path + for name in run_parts_list(src_dirpath): + yield name def load_master(): - with closing(file(src_path)) as f: - return yaml.load(f, loader) + config = dict() + for filename in list_files(): + with closing(file(filename)) as f: + augment(config, yaml.load(f, loader)) + return config def get_src_mtime(): - return getmtime(src_path) + return max(max(getmtime(filename) for filename in list_files()), + getmtime(src_dirpath)) def load(force_refresh = False): """