#!/usr/bin/env python import sys import re # Expand a hostgroup recursively, return a set. def expand(thing, hostgroups): if thing not in hostgroups: expanded_thing = set([thing]) else: # Set comprehension (python 3) is not suitable for # this because deeper expand() calls return sets # set comprehension would make a 'set of sets' out # of it which (1) is not supported, (2) is not what # we want. expanded_thing = set([]) for sub_thing in hostgroups[thing]: expanded_thing |= expand(sub_thing, hostgroups) return(expanded_thing) def slurp_hostgroups_cfg(handle, hostgroups): # Slurp file into one string remainder_of_file = handle.read() # While possible to extract another hostgroup definition from the string, do so. while True: if [ m for m in [ re.search("^.*?(define\s+hostgroup\s+{.*?}\n)(.*)$", remainder_of_file, flags=re.DOTALL) ] if m is None ]: break hostgroupdef = m.group(1) remainder_of_file = m.group(2) # Extract directives from hostgroup definition. if [ m for m in [ re.search("^define\s+hostgroup\s+\{\n\s+hostgroup_name\s+(\S+)\n\s+alias\s+[^\n]+\n(?:|(\s+(members)\s+(\S+)\n|\s+(hostgroup_members)\s+(\S+)\n)+)\}", hostgroupdef, flags=re.DOTALL) ] if m is None ]: print "badly formatted hostgroup definition: %s" % (hostgroupdef) sys.exit(1) # Which groups in m are the ones we want depends on whether hostgroup members, # host members or nothing declared. But in all cases, we need to turn # comma-separated string into a set. if m.group(3) is not None: members = set(m.group(4).split(",")) elif m.group(5) is not None: members = set(m.group(6).split(",")) else: members = set([]) hostgroups[m.group(1)] = members return 0 def filter_services_cfg_in(handle, hostgroups): # Process each line of services.cfg writing result to stdout. while True: # Read line line = handle.readline() if not line: break # Rewrite it if it contains hostset_exp. m = re.search("^(\s*)hostset_exp(\s+)(.*?)\s*$", line) if m is not None: lead_spacing = m.group(1) mid_spacing = m.group(2) remainder_of_line = m.group(3) # Process each word of the hostset_exp's value writing result to line. line = "%s# hostset_exp%s%s\n" % (lead_spacing, " " * (len(mid_spacing)-len("# ")), remainder_of_line) line += "%shost_name%s" % (lead_spacing, " " * (len(mid_spacing)+len("hostset_exp")-len("host_name"))) expression_code_string = "" while True: m = re.search("^(.*?)(\w+(?:-\w+)*)(.*)$", remainder_of_line) # If not enough left to extract a word, flush. if m is None: expression_code_string += remainder_of_line break leading_nonidentifier = m.group(1) identifier = m.group(2) remainder_of_line = m.group(3) # Cruft before identifier (e.g. brackets) is part of the expression code; keep it. For # the identifier part, if it is not a hostgroup make python code for a set of it and keep it. # If it is a hostgroup then expand it to the set and make python code for the set of it and # keep it. if identifier not in hostgroups: expression_code_string += leading_nonidentifier + "set([\"%s\"])" % (identifier) else: expression_code_string += leading_nonidentifier + "set([\"%s\"])" % "\", \"".join((hostgroups[identifier])) # Once the python expression code has been assembled then we need to evaluate it. It will # return a set, so that needs to be converted to a comma-separated listed and that needs # to be appended to the line we're gonna output. Then output it. line += ",".join(eval(expression_code_string)) + "\n" # Output the line sys.stdout.write(line) def main(): # Get hostgroups_cfg and services_cfg_in filenames off command line. if len(sys.argv) != 3: print "usage error" sys.exit(1) hostgroups_cfg = sys.argv[1] services_cfg_in = sys.argv[2] # Load hostgroup definitions. hostgroups = {} try: f = open(hostgroups_cfg) except IOError: print "%s: can't open" % (hostgroups_cfg) sys.exit(1) slurp_hostgroups_cfg(f, hostgroups) f.close() # Expand hostgroup definitions recursively. expanded_hostgroups = {} for hostgroup in hostgroups.keys(): expanded_hostgroups[hostgroup] = expand(hostgroup, hostgroups) # Filter services.cfg.in to stdout, substituting hostset_exp occurrences. try: f = open(services_cfg_in) except IOError: print "%s: can't open" % (services_cfg_in) sys.exit(1) filter_services_cfg_in(f, expanded_hostgroups) f.close() main()