| LEFT | RIGHT | 
|---|
| (no file at all) |  | 
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # coding: utf-8 | 2 # coding: utf-8 | 
| 3 | 3 | 
| 4 import sys | 4 import sys | 
| 5 import os | 5 import os | 
| 6 import re | 6 import re | 
| 7 import subprocess | 7 import subprocess | 
| 8 import getopt | 8 import getopt | 
| 9 import yaml | 9 import yaml | 
| 10 | 10 | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 34   for option, value in options: | 34   for option, value in options: | 
| 35     if option == '-u': | 35     if option == '-u': | 
| 36       user = value | 36       user = value | 
| 37     elif option == '-h': | 37     elif option == '-h': | 
| 38       hosts.append(value) | 38       hosts.append(value) | 
| 39     elif option == '-i': | 39     elif option == '-i': | 
| 40       ignore_errors = True | 40       ignore_errors = True | 
| 41 | 41 | 
| 42   return user, hosts, ignore_errors, args | 42   return user, hosts, ignore_errors, args | 
| 43 | 43 | 
| 44 def readMonitoringConfig(): |  | 
| 45   # Use Puppet's parser to convert monitoringserver.pp into YAML |  | 
| 46   manifest = os.path.join(os.path.dirname(__file__), 'manifests', 'monitoringser
     ver.pp') |  | 
| 47   parseScript = ''' |  | 
| 48     require 'puppet' |  | 
| 49     require 'puppet/parser' |  | 
| 50     parser = Puppet::Parser::Parser.new(Puppet[:environment]) |  | 
| 51     Puppet.settings[:ignoreimport] = true |  | 
| 52     parser.file = ARGV[0] |  | 
| 53     print ZAML.dump(parser.parse) |  | 
| 54   ''' |  | 
| 55   data, dummy = subprocess.Popen(['ruby', '', manifest], |  | 
| 56                   stdin=subprocess.PIPE, |  | 
| 57                   stdout=subprocess.PIPE).communicate(parseScript) |  | 
| 58 |  | 
| 59   # See http://stackoverflow.com/q/8357650/785541 on parsing Puppet's YAML |  | 
| 60   yaml.add_multi_constructor(u"!ruby/object:", lambda loader, suffix, node: load
     er.construct_yaml_map(node)) |  | 
| 61   yaml.add_constructor(u"!ruby/sym", lambda loader, node: loader.construct_yaml_
     str(node)) |  | 
| 62   return yaml.load(data) |  | 
| 63 | 44 | 
| 64 def getValidHosts(): | 45 def getValidHosts(): | 
| 65   def processNode(node, hosts=None, groups=None): | 46   dirname = os.path.dirname(sys.argv[0]) | 
| 66     if hosts == None: | 47   path_name = os.path.join(dirname, "hiera", "private", "hosts.yaml") | 
| 67       hosts = set() | 48   with open(path_name, 'rb') as handle: | 
| 68     if groups == None: | 49     config = yaml.load(handle) | 
| 69       groups = {} | 50   servers = config.get('servers', {}) | 
| 70 | 51   return servers | 
| 71     if 'context' in node and 'code' in node['context']: |  | 
| 72       node = node['context']['code'] |  | 
| 73 |  | 
| 74     if node.get('type', None) == 'nagios_hostgroup': |  | 
| 75       data = node['instances']['children'][0] |  | 
| 76       title = data['title']['value'] |  | 
| 77       members = filter(lambda c: c['param'] == 'members', data['parameters']['ch
     ildren'])[0]['value']['value'] |  | 
| 78       members = re.split(r'\s*,\s*', members) |  | 
| 79       groups[title] = members |  | 
| 80     elif node.get('type', None) == 'nagios_host': |  | 
| 81       data = node['instances']['children'][0] |  | 
| 82       title = data['title']['value'] |  | 
| 83       hosts.add(title) |  | 
| 84 |  | 
| 85     for child in node['children']: |  | 
| 86       processNode(child, hosts, groups) |  | 
| 87     return hosts, groups |  | 
| 88 |  | 
| 89   monitoringConfig = readMonitoringConfig() |  | 
| 90   if not monitoringConfig: |  | 
| 91     print >>sys.stderr, "Failed to parse monitoring configuration" |  | 
| 92     return [[], []] |  | 
| 93   # Extract hosts and groups from monitoring config |  | 
| 94   return processNode(monitoringConfig) |  | 
| 95 | 52 | 
| 96 def resolveHostList(hosts): | 53 def resolveHostList(hosts): | 
| 97   validHosts, validGroups = getValidHosts() |  | 
| 98   if not validHosts: |  | 
| 99     print >>sys.stderr, "Warning: No valid hosts found, not validating" |  | 
| 100     return hosts |  | 
| 101 | 54 | 
| 102   result = set() | 55   result = set() | 
| 103   for param in hosts: | 56 | 
| 104     if param in validGroups: | 57   try: | 
| 105       for host in validGroups[param]: | 58     valid_hosts = getValidHosts() | 
| 106         if host == '*': | 59   except Warning as error: | 
| 107           result = result | validHosts | 60     print >>sys.stderr, 'Warning: failed to determine valid hosts:', error | 
| 108         else: | 61     result.update(hosts) | 
| 109           result.add(host) | 62   else: | 
| 110     elif param in validHosts: | 63     for name in hosts: | 
| 111       result.add(param) | 64       chunk = [ | 
| 112     elif '%s.adblockplus.org' % param in validHosts: | 65           value.get('dns', key) for (key, value) in valid_hosts.items() | 
| 113       result.add('%s.adblockplus.org' % param) | 66 | 
| 114     else: | 67           if name == key | 
| 115       print >>sys.stderr, 'Warning: failed to recognize host or group %s' %param | 68           or name == '*' | 
|  | 69           or name == value.get('dns', None) | 
|  | 70           or name in value.get('groups', ()) | 
|  | 71       ] | 
|  | 72 | 
|  | 73       if len(chunk) == 0: | 
|  | 74         print >>sys.stderr, 'Warning: failed to recognize host or group', name | 
|  | 75       else: | 
|  | 76         result.update(chunk) | 
|  | 77 | 
| 116   return result | 78   return result | 
| 117 | 79 | 
| 118 def runCommand(user, host, command, ignore_errors=False): | 80 def runCommand(user, host, command, ignore_errors=False): | 
| 119   if not isinstance(command, list): | 81   if not isinstance(command, list): | 
| 120     command = [command] | 82     command = [command] | 
| 121   command = ["ssh"] + (["-l", user] if user else []) + [host] + command | 83   command = ["ssh"] + (["-l", user] if user else []) + [host] + command | 
| 122   if ignore_errors: | 84   if ignore_errors: | 
| 123     subprocess.call(command) | 85     subprocess.call(command) | 
| 124   else: | 86   else: | 
| 125     subprocess.check_call(command) | 87     subprocess.check_call(command) | 
| 126 | 88 | 
| 127 if __name__ == "__main__": | 89 if __name__ == "__main__": | 
| 128   user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) | 90   user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) | 
| 129   selectedHosts = resolveHostList(hosts) | 91   selectedHosts = resolveHostList(hosts) | 
| 130   if len(selectedHosts) == 0: | 92   if len(selectedHosts) == 0: | 
| 131     print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' | 93     print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' | 
| 132     sys.exit(0) | 94     sys.exit(0) | 
| 133   for host in selectedHosts: | 95   for host in selectedHosts: | 
| 134     print >>sys.stderr, 'Running on %s...' % host | 96     print >>sys.stderr, 'Running on %s...' % host | 
| 135     runCommand(user, host, args, ignore_errors=ignore_errors) | 97     runCommand(user, host, args, ignore_errors=ignore_errors) | 
| LEFT | RIGHT | 
|---|