| OLD | NEW |
| 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 os.path |
| 6 import re | 7 import re |
| 7 import subprocess | 8 import subprocess |
| 8 import getopt | 9 import getopt |
| 9 import yaml | 10 import yaml |
| 10 | 11 |
| 11 def usage(): | 12 def usage(): |
| 12 print >>sys.stderr, ''' | 13 print >>sys.stderr, ''' |
| 13 Usage: %s [-u <user>] [-h <host>|<group>] [-i] ... <command> | 14 Usage: %s [-u <user>] [-h <host>|<group>] [-i] ... <command> |
| 14 | 15 |
| 15 Runs a command on the given hosts or groups of hosts. | 16 Runs a command on the given hosts or groups of hosts. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 34 for option, value in options: | 35 for option, value in options: |
| 35 if option == '-u': | 36 if option == '-u': |
| 36 user = value | 37 user = value |
| 37 elif option == '-h': | 38 elif option == '-h': |
| 38 hosts.append(value) | 39 hosts.append(value) |
| 39 elif option == '-i': | 40 elif option == '-i': |
| 40 ignore_errors = True | 41 ignore_errors = True |
| 41 | 42 |
| 42 return user, hosts, ignore_errors, args | 43 return user, hosts, ignore_errors, args |
| 43 | 44 |
| 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 | 45 |
| 64 def getValidHosts(): | 46 def getValidHosts(): |
| 65 def processNode(node, hosts=None, groups=None): | 47 dirname = os.path.dirname(sys.argv[0]) |
| 66 if hosts == None: | 48 path_name = os.path.join(dirname, "hiera", "private", "hosts.yaml") |
| 67 hosts = set() | 49 with open(path_name, 'rb') as handle: |
| 68 if groups == None: | 50 config = yaml.load(handle) |
| 69 groups = {} | 51 servers = config.get('servers', {}) |
| 70 | 52 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 | 53 |
| 96 def resolveHostList(hosts): | 54 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 | 55 |
| 56 host_names = set(str(item) for item in hosts) |
| 102 result = set() | 57 result = set() |
| 103 for param in hosts: | 58 |
| 104 if param in validGroups: | 59 try: |
| 105 for host in validGroups[param]: | 60 valid_hosts = getValidHosts() |
| 106 if host == '*': | 61 except Warning as error: |
| 107 result = result | validHosts | 62 print >>sys.stderr, 'Warning: failed to determine valid hosts:', error |
| 108 else: | 63 result.update(host_names) |
| 109 result.add(host) | 64 else: |
| 110 elif param in validHosts: | 65 for name in host_names: |
| 111 result.add(param) | 66 chunk = tuple( |
| 112 elif '%s.adblockplus.org' % param in validHosts: | 67 item[1].get('dns', item[0]) for item in valid_hosts.items() |
| 113 result.add('%s.adblockplus.org' % param) | 68 |
| 114 else: | 69 if name == item[0] |
| 115 print >>sys.stderr, 'Warning: failed to recognize host or group %s' %param | 70 or name == '*' |
| 71 or name == item[1].get('dns', None) |
| 72 or name in item[1]['ip'] |
| 73 or name in item[1].get('groups', ()) |
| 74 ) |
| 75 |
| 76 if len(chunk) == 0: |
| 77 print >>sys.stderr, 'Warning: failed to recognize host or group', name |
| 78 else: |
| 79 result.update(chunk) |
| 80 |
| 116 return result | 81 return result |
| 117 | 82 |
| 118 def runCommand(user, host, command, ignore_errors=False): | 83 def runCommand(user, host, command, ignore_errors=False): |
| 119 if not isinstance(command, list): | 84 if not isinstance(command, list): |
| 120 command = [command] | 85 command = [command] |
| 121 command = ["ssh"] + (["-l", user] if user else []) + [host] + command | 86 command = ["ssh"] + (["-l", user] if user else []) + [host] + command |
| 122 if ignore_errors: | 87 if ignore_errors: |
| 123 subprocess.call(command) | 88 subprocess.call(command) |
| 124 else: | 89 else: |
| 125 subprocess.check_call(command) | 90 subprocess.check_call(command) |
| 126 | 91 |
| 127 if __name__ == "__main__": | 92 if __name__ == "__main__": |
| 128 user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) | 93 user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) |
| 129 selectedHosts = resolveHostList(hosts) | 94 selectedHosts = resolveHostList(hosts) |
| 130 if len(selectedHosts) == 0: | 95 if len(selectedHosts) == 0: |
| 131 print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' | 96 print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' |
| 132 sys.exit(0) | 97 sys.exit(0) |
| 133 for host in selectedHosts: | 98 for host in selectedHosts: |
| 134 print >>sys.stderr, 'Running on %s...' % host | 99 print >>sys.stderr, 'Running on %s...' % host |
| 135 runCommand(user, host, args, ignore_errors=ignore_errors) | 100 runCommand(user, host, args, ignore_errors=ignore_errors) |
| OLD | NEW |