From: Yang Zhang Date: Tue, 29 Jul 2008 05:35:57 +0000 (-0400) Subject: * moved more generic code into `common` package X-Git-Tag: sipb-xen-base/8.9~1 X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-base.git/commitdiff_plain/8bfea358c4a93a7c46efbefe0694036f38f390c4 * moved more generic code into `common` package * silently fail if cache fails * load the configuration on module load * produce a struct-based representation of the configuration * allowing full exception messages for OSErrors (default behavior) * added some dependencies specs svn path=/trunk/packages/sipb-xen-base/; revision=778 --- diff --git a/debian/control b/debian/control index 00396d8..59fea99 100644 --- a/debian/control +++ b/debian/control @@ -2,12 +2,12 @@ Source: sipb-xen-base Section: base Priority: extra Maintainer: SIPB Xen Project -Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 4.1.0), python-json (>= 3.4-2), python-yaml (>= 3.05-1andersk1) +Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 4.1.0) Standards-Version: 3.7.2 Package: sipb-xen-base Architecture: all -Depends: ${misc:Depends}, +Depends: ${misc:Depends}, python-json (>= 3.4-2), python-yaml (>= 3.05) Description: Base configuration required for all SIPB xen servers This package includes apt configuration, .k5login and other files that should be synchronized among all our servers. diff --git a/files/usr/sbin/invirt-getconf b/files/usr/sbin/invirt-getconf index d503dea..ce0dfa6 100755 --- a/files/usr/sbin/invirt-getconf +++ b/files/usr/sbin/invirt-getconf @@ -1,13 +1,14 @@ #!/usr/bin/env python """ -invirt-getconf [-f FILE] KEY prints the configuration the option named KEY from -the invirt configuration file FILE. Keys are dot-separated paths into the YAML +invirt-getconf loads an invirt configuration file (either the original YAML +source or the faster-to-load JSON cache) and prints the configuration option +with the given name (key). Keys are dot-separated paths into the YAML configuration tree. List indexes (0-based) are also treated as path components. (Due to this path language, certain restrictions are placed on the keys used in -the YAML configuration, e.g. they cannot contain dots.) +the YAML configuration; e.g., they cannot contain dots.) Examples: @@ -57,7 +58,7 @@ def main(argv): except IndexError: raise invirt_exception( '%s: index %s out of range' % (progress, component)) print conf - except (invirt_exception, OSError), ex: + except invirt_exception, ex: print >> stderr, ex return 1 diff --git a/files/usr/share/python-support/sipb-xen-base/invirt/common.py b/files/usr/share/python-support/sipb-xen-base/invirt/common.py new file mode 100644 index 0000000..250078e --- /dev/null +++ b/files/usr/share/python-support/sipb-xen-base/invirt/common.py @@ -0,0 +1,41 @@ +import unittest + +class struct(object): + 'A simple namespace object.' + def __init__(self, d = {}): + 'd is the dictionary to update my __dict__ with.' + self.__dict__.update(d) + +def dicts2struct(x): + """ + Given a tree of lists/dicts, perform a deep traversal to transform all the + dicts to structs. + """ + if type(x) == dict: + return struct((k, dicts2struct(v)) for k,v in x.iteritems()) + elif type(x) == list: + return [dicts2struct(v) for v in x] + else: + return x + +def wrap(rsrc, func): + "Utility to that emulates with Python 2.5's `with closing(rsrc)`." + try: return func(rsrc) + finally: rsrc.close() + +class common_tests(unittest.TestCase): + def test_dicts2structs(self): + dicts = { + 'atom': 0, + 'dict': { 'atom': 'atom', 'list': [1,2,3] }, + 'list': [ 'atom', {'key': 'value'} ] + } + structs = dicts2struct(dicts) + self.assertEqual(structs.atom, dicts['atom']) + self.assertEqual(structs.dict.atom, dicts['dict']['atom']) + self.assertEqual(structs.dict.list, dicts['dict']['list']) + self.assertEqual(structs.list[0], dicts['list'][0]) + self.assertEqual(structs.list[1].key, dicts['list'][1]['key']) + +if __name__ == '__main__': + unittest.main() diff --git a/files/usr/share/python-support/sipb-xen-base/invirt/config.py b/files/usr/share/python-support/sipb-xen-base/invirt/config.py index dab9f20..fad48fe 100644 --- a/files/usr/share/python-support/sipb-xen-base/invirt/config.py +++ b/files/usr/share/python-support/sipb-xen-base/invirt/config.py @@ -1,4 +1,5 @@ import json, yaml +from invirt.common import * from os import error, makedirs from os.path import dirname, getmtime @@ -8,11 +9,6 @@ default_cache_path = '/var/lib/invirt/invirt.json' try: default_loader = yaml.CSafeLoader except: default_loader = yaml.SafeLoader -def wrap(rsrc, func): - "Utility to that emulates with Python 2.5's `with closing(rsrc)`." - try: return func(rsrc) - finally: rsrc.close() - def load(src_path = default_src_path, cache_path = default_cache_path, force_refresh = False): @@ -30,12 +26,19 @@ def load(src_path = default_src_path, except OSError: do_refresh = True else: do_refresh = src_mtime > cache_mtime + if not do_refresh: + # try reading from the cache first + try: cfg = wrap(file(cache_path), lambda f: json.read(f.read())) + except: do_refresh = True + if do_refresh: # reload the source and regenerate the cache cfg = wrap(file(src_path), lambda f: yaml.load(f, default_loader)) - wrap(file(cache_path, 'w'), lambda f: f.write(json.write(cfg))) - else: - cfg = wrap(file(cache_path), lambda f: json.read(f.read())) + try: wrap(file(cache_path, 'w'), lambda f: f.write(json.write(cfg))) + except: pass # silent failure return cfg +dicts = load() +structs = dicts2struct(dicts) + # vim:et:sw=4:ts=4