pvl/hosts/config.py
changeset 713 d5e2d1d9716a
parent 692 34f25380d0e7
equal deleted inserted replaced
712:97fa1b086b36 713:d5e2d1d9716a
    20     hosts.add_option('--hosts-domain',          metavar='DOMAIN',
    20     hosts.add_option('--hosts-domain',          metavar='DOMAIN',
    21             help="Default domain for hosts. Default uses config file basename")
    21             help="Default domain for hosts. Default uses config file basename")
    22 
    22 
    23     hosts.add_option('--hosts-include',         metavar='PATH',
    23     hosts.add_option('--hosts-include',         metavar='PATH',
    24             help="Optional path for hosts includes, in addition to the host config dir")
    24             help="Optional path for hosts includes, in addition to the host config dir")
       
    25 
       
    26     hosts.add_option('--hosts-include-trace',   metavar='FILE',
       
    27             help="Write out all included file paths")
    25     
    28     
    26     return hosts
    29     return hosts
    27 
    30 
    28 class HostConfigError (Exception):
    31 class HostConfigError (Exception):
    29     """
    32     """
   205 
   208 
   206 
   209 
   207         log.info("%s: include: %s", config_path, path)
   210         log.info("%s: include: %s", config_path, path)
   208         yield path
   211         yield path
   209 
   212 
   210 def apply_hosts_configs (options, path, name, config, parent=None, defaults={}):
   213 def apply_hosts_configs (options, path, name, config, parent=None, defaults={}, include_trace=None):
   211     """
   214     """
   212         Load hosts from a configobj.Section (which can be the top-level ConfigObj).
   215         Load hosts from a configobj.Section (which can be the top-level ConfigObj).
   213 
   216 
   214             options         global options
   217             options         global options
   215             path            filesystem path of file (for errors)
   218             path            filesystem path of file (for errors)
   216             name            name of this section/file
   219             name            name of this section/file
   217             config          configobj.Section
   220             config          configobj.Section
   218             parent          parent section from included files or --hosts-domain
   221             parent          parent section from included files or --hosts-domain
   219             defaults        hierarchial section defaults
   222             defaults        hierarchial section defaults
       
   223             include_trace   - optional list to append loaded files to
   220     """
   224     """
   221     
   225     
   222     # items in this section
   226     # items in this section
   223     section = dict(defaults)
   227     section = dict(defaults)
   224     for scalar in config.scalars:
   228     for scalar in config.scalars:
   225         section[scalar] = config[scalar]
   229         section[scalar] = config[scalar]
   226 
   230 
   227     # process includes?
   231     # process includes?
   228     if 'include' in section:
   232     if 'include' in section:
   229         includes = section.pop('include').split()
   233         # convert from unicode
       
   234         includes = [str(include) for include in section.pop('include').split()]
   230 
   235 
   231         includes = list(parse_config_includes(options, path, includes))
   236         includes = list(parse_config_includes(options, path, includes))
   232 
   237 
   233         # within our domain context
   238         # within our domain context
   234         for host in apply_hosts_files(options, includes, parent=name, defaults=section):
   239         for host in apply_hosts_files(options, includes, include_trace=include_trace,
       
   240                 parent=name, defaults=section
       
   241         ):
   235             yield host
   242             yield host
   236     else:
   243     else:
   237         includes = None
   244         includes = None
   238 
   245 
   239     if config.sections:
   246     if config.sections:
   302     except configobj.ConfigObjError as ex:
   309     except configobj.ConfigObjError as ex:
   303         raise HostConfigObjError(path, ex)
   310         raise HostConfigObjError(path, ex)
   304     
   311     
   305     return apply_hosts_configs(options, path, name, config, **opts)
   312     return apply_hosts_configs(options, path, name, config, **opts)
   306 
   313 
   307 def apply_hosts_file (options, path, **opts):
   314 def apply_hosts_file (options, path, include_trace=None, **opts):
   308     """
   315     """
   309         Load Hosts from a file path.
   316         Load Hosts from a file path.
   310     """
   317             
       
   318             include_trace           - optional list to append loaded files to
       
   319     """
       
   320     
       
   321     if include_trace is not None:
       
   322         log.debug("%s: include trace", path)
       
   323         include_trace.append(path)
   311 
   324 
   312     try:
   325     try:
   313         file = open(path)
   326         file = open(path)
   314     except IOError as ex:
   327     except IOError as ex:
   315         raise HostConfigError(path, ex.strerror)
   328         raise HostConfigError(path, ex.strerror)
   316 
   329 
   317     for host in apply_hosts_config(options, file, **opts):
   330     for host in apply_hosts_config(options, file, include_trace=include_trace, **opts):
   318         yield host
   331         yield host
   319 
   332 
   320 def apply_hosts_directory (options, root, **opts):
   333 def apply_hosts_directory (options, root, include_trace=None, **opts):
   321     """
   334     """
   322         Load Hosts from a directory, loading each file within the directory.
   335         Load Hosts from a directory, loading each file within the directory.
   323 
   336 
       
   337             include_trace           - optional list to append loaded files to
       
   338 
   324         Skips .dotfiles.
   339         Skips .dotfiles.
   325     """
   340     """
       
   341 
       
   342     if include_trace is not None:
       
   343         log.debug("%s: include trace", root)
       
   344         include_trace.append(root)
   326 
   345 
   327     for name in sorted(os.listdir(root)):
   346     for name in sorted(os.listdir(root)):
   328         path = os.path.join(root, name)
   347         path = os.path.join(root, name)
   329 
   348 
   330         if name.startswith('.'):
   349         if name.startswith('.'):
   333 
   352 
   334         if os.path.isdir(path):
   353         if os.path.isdir(path):
   335             log.debug("%s: skip directory: %s", root, name)
   354             log.debug("%s: skip directory: %s", root, name)
   336             continue
   355             continue
   337 
   356 
   338         for host in apply_hosts_file(options, path, **opts):
   357         for host in apply_hosts_file(options, path, include_trace=include_trace, **opts):
   339             yield host
   358             yield host
   340 
   359 
   341 def apply_hosts_files (options, files, **opts):
   360 def apply_hosts_files (options, files, **opts):
   342     """
   361     """
   343         Load Hosts from files.
   362         Load Hosts from files.
   357     """
   376     """
   358         Load Hosts from arguments.
   377         Load Hosts from arguments.
   359 
   378 
   360         Exits with status=2 if loading the confs fails.
   379         Exits with status=2 if loading the confs fails.
   361     """
   380     """
       
   381 
       
   382     if options.hosts_include_trace:
       
   383         log.debug("include trace")
       
   384         include_trace = [ ]
       
   385     else:
       
   386         include_trace = None
   362     
   387     
   363     try:
   388     try:
   364         # load hosts from configs
   389         # load hosts from configs
   365         hosts = list(apply_hosts_files(options, args))
   390         hosts = list(apply_hosts_files(options, args, include_trace=include_trace))
   366     except HostConfigObjError as error:
   391     except HostConfigObjError as error:
   367         log.error("%s", error)
   392         log.error("%s", error)
   368         log.error("\t%s", error.line_contents)
   393         log.error("\t%s", error.line_contents)
   369         sys.exit(2)
   394         sys.exit(2)
   370 
   395 
   371     except HostConfigError as error:
   396     except HostConfigError as error:
   372         log.error("%s", error)
   397         log.error("%s", error)
   373         sys.exit(2)
   398         sys.exit(2)
       
   399         
       
   400     if options.hosts_include_trace:
       
   401         with pvl.args.apply_file(options.hosts_include_trace, 'w') as file:
       
   402             for include in include_trace:
       
   403                 print >>file, include
   374 
   404 
   375     # stable ordering
   405     # stable ordering
   376     return sorted(hosts, key=Host.sort_key)
   406     return sorted(hosts, key=Host.sort_key)
   377 
   407