Tim Landscheidt has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/328030 )
Change subject: Tools: Generate node sets dynamically ...................................................................... Tools: Generate node sets dynamically Currently, the list of nodes per hostgroup is regenerated every minute. This is far more often than clush is actually used according to the log file, and additionally this two-step process can result in confusing behaviour in cases where the cron job fails in some way. This change generates the node sets dynamically, on demand. Thus they are always up-to-date and errors in generating the list make themselves known immediately. Technically, the generated "load" on wikitech will be reduced, but given the low frequency of API calls (once per clush invocation) this is not a factor. Change-Id: I5bb630836beb1c6a2aa2b346bef03687db9f4732 --- D modules/role/files/toollabs/clush/tools-clush-generator A modules/role/files/toollabs/clush/tools-clush-generator.py D modules/role/files/toollabs/clush/tools-clush-interpreter M modules/role/manifests/toollabs/clush/master.pp 4 files changed, 108 insertions(+), 131 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/puppet refs/changes/30/328030/1 diff --git a/modules/role/files/toollabs/clush/tools-clush-generator b/modules/role/files/toollabs/clush/tools-clush-generator deleted file mode 100644 index 2b8f7cb..0000000 --- a/modules/role/files/toollabs/clush/tools-clush-generator +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python3 -""" -Simple script that generates a YAML file classifying all instances -on the tools project into groups based on the role they perform. - -This YAML file can then be read by `tools-clush-interpreter` to -list instances within a group. This can be used by `clush` to -allow arbitrary command execution on targeted list of instances. - -This is run in a cron every hour. -""" -import json -import yaml -import argparse -from urllib.request import urlopen - - -# Maps prefixes to hostgroup names -TOOLS_PREFIX_CLASSIFIER = { - 'webgrid-lighttpd-12': 'webgrid-lighttpd-precise', - 'webgrid-lighttpd-14': 'webgrid-lighttpd-trusty', - 'webgrid-generic': 'webgrid-generic', - 'webgrid-': 'webgrid', - 'exec-': 'exec', - 'exec-12': 'exec-precise', - 'exec-14': 'exec-trusty', - 'proxy-': 'webproxy', - 'checker-': 'checker', - 'redis-': 'redis', - 'services-': 'services', - 'bastion-': 'bastion', - 'cron-': 'cron', - 'grid-master': 'grid-master', - 'grid-shadow': 'grid-shadow', - 'mail': 'mail', - 'static-': 'static', - 'worker': 'k8s-worker', - 'k8s-master': 'k8s-master', - 'flannel-etcd': 'flannel-etcd', - 'k8s-etcd': 'k8s-etcd', - 'logs': 'logs', - 'precise-dev': 'precise-dev', - 'docker-builder': 'docker-builder', - 'prometheus': 'prometheus', - '': 'all', -} - - -def get_hostgroups(classifier, project_name): - hostgroups = {name: [] for name in classifier.values()} - - api_url = 'https://wikitech.wikimedia.org/w/api.php' \ - '?action=query&list=novainstances&niregion=eqiad&format=json' \ - '&niproject=' + project_name - - data = json.loads(urlopen(api_url).read().decode('utf-8')) - - for instance in data['query']['novainstances']: - name = instance['name'] - for prefix in classifier: - if name.startswith('%s-%s' % (project_name, prefix)): - role = classifier[prefix] - hostgroups[role].append('%s.%s.eqiad.wmflabs' % (name, project_name)) - - return hostgroups - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument( - 'outputpath', - help='Path to output hostgroup to host mappings' - ) - args = parser.parse_args() - - with open('/etc/wmflabs-project', 'r') as f: - project_name = f.read().rstrip('\n') - - hostgroups = get_hostgroups(TOOLS_PREFIX_CLASSIFIER, project_name) - with open(args.outputpath, 'w') as f: - f.write(yaml.safe_dump(hostgroups, default_flow_style=False)) diff --git a/modules/role/files/toollabs/clush/tools-clush-generator.py b/modules/role/files/toollabs/clush/tools-clush-generator.py new file mode 100644 index 0000000..15b54c4 --- /dev/null +++ b/modules/role/files/toollabs/clush/tools-clush-generator.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 + + +"""Simple generator script for clustershell to dynamically list all + instances and classify them into groups based on their hostname. + +""" + + +import argparse +import json +import urllib.request + + +# Maps hostgroup names to prefixes. +TOOLS_HOSTGROUPS = { + 'all': '', + 'bastion': 'bastion-', + 'checker': 'checker-', + 'cron': 'cron-', + 'docker-builder': 'docker-builder', + 'exec': 'exec-', + 'exec-precise': 'exec-12', + 'exec-trusty': 'exec-14', + 'flannel-etcd': 'flannel-etcd', + 'grid-master': 'grid-master', + 'grid-shadow': 'grid-shadow', + 'k8s-etcd': 'k8s-etcd', + 'k8s-master': 'k8s-master', + 'k8s-worker': 'worker', + 'logs': 'logs', + 'mail': 'mail', + 'precise-dev': 'precise-dev', + 'prometheus': 'prometheus', + 'redis': 'redis-', + 'services': 'services-', + 'static': 'static-', + 'webgrid': 'webgrid-', + 'webgrid-generic': 'webgrid-generic', + 'webgrid-lighttpd-precise': 'webgrid-lighttpd-12', + 'webgrid-lighttpd-trusty': 'webgrid-lighttpd-14', + 'webproxy': 'proxy-', +} + + +def list_hostgroups(): + """List all hostgroups on stdout.""" + for hostgroup in sorted(TOOLS_HOSTGROUPS): + print(hostgroup) + + +def list_nodes(project_name, hostgroup): + """List all nodes of a hostgroup on stdout.""" + prefix = '%s-%s' % (project_name, TOOLS_HOSTGROUPS[hostgroup]) + + api_url = 'https://wikitech.wikimedia.org/w/api.php' \ + '?action=query&list=novainstances&niregion=eqiad&format=json' \ + '&niproject=' + project_name + + opener = urllib.request.build_opener() + opener.addheaders = [('User-Agent', __file__)] + data = json.loads(opener.open(api_url).read().decode('utf-8')) + + for instance in data['query']['novainstances']: + name = instance['name'] + if name.startswith(prefix): + print('%s.%s.eqiad.wmflabs' % (name, project_name)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='action') + + parser_map = subparsers.add_parser( + 'map', + help='Print list of hosts in a hostgroup' + ) + parser_map.add_argument( + 'group', + help='Name of group whose instances should be printed' + ) + + parser_list = subparsers.add_parser( + 'list', + help='List all hostgroups', + ) + + args = parser.parse_args() + if args.action == 'list': + list_hostgroups() + elif args.action == 'map': + with open('/etc/wmflabs-project', 'r') as f: + project_name = f.read().rstrip('\n') + + list_nodes(project_name, args.group) diff --git a/modules/role/files/toollabs/clush/tools-clush-interpreter b/modules/role/files/toollabs/clush/tools-clush-interpreter deleted file mode 100644 index c2fb0a3..0000000 --- a/modules/role/files/toollabs/clush/tools-clush-interpreter +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/python3 -import yaml -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument( - '--hostgroups', - help='Path to YAML file with hostgroup information', - required=True -) -subparsers = parser.add_subparsers(dest='action') - -parser_map = subparsers.add_parser( - 'map', - help='Print list of hosts in a hostgroup' -) -parser_map.add_argument( - 'group', - help='Name of group whose instances should be printed' -) - -parser_list = subparsers.add_parser( - 'list', - help='List all hostgroups', -) -args = parser.parse_args() - - -with open(args.hostgroups) as f: - groups = yaml.safe_load(f) - if args.action == 'map': - print('\n'.join(groups[args.group])) - if args.action == 'list': - print('\n'.join(groups.keys())) diff --git a/modules/role/manifests/toollabs/clush/master.pp b/modules/role/manifests/toollabs/clush/master.pp index eb869a2..0da9cd8 100644 --- a/modules/role/manifests/toollabs/clush/master.pp +++ b/modules/role/manifests/toollabs/clush/master.pp @@ -4,8 +4,7 @@ # command execution on classes of toollabs instances. Hits # the wikitech API to do discovery of all instances in # toollabs. They are then classified by prefix using a list, -# maintained in modules/role/files/toollabs/clush/toollabs-clush-generator. -# This is refreshed every hour. +# maintained in modules/role/files/toollabs/clush/toollabs-clush-generator.py. # # You'll have to be a member of tools.admin to run this. All accesses # are logged to /var/log/clush.log. @@ -22,22 +21,17 @@ username => 'clushuser', } - require_package('python3-yaml') - file { '/usr/local/sbin/tools-clush-generator': ensure => file, - source => 'puppet:///modules/role/toollabs/clush/tools-clush-generator', + source => 'puppet:///modules/role/toollabs/clush/tools-clush-generator.py', owner => 'root', group => 'root', mode => '0555', } + # TODO: Remove after Puppet cycle. file { '/usr/local/sbin/tools-clush-interpreter': - ensure => file, - source => 'puppet:///modules/role/toollabs/clush/tools-clush-interpreter', - owner => 'root', - group => 'root', - mode => '0555', + ensure => absent, } # override /usr/bin/clush with this! Just does additional logging @@ -51,11 +45,14 @@ mode => '0555', } + # TODO: Remove after Puppet cycle. cron { 'update_tools_clush': - ensure => present, - command => '/usr/local/sbin/tools-clush-generator /etc/clustershell/tools.yaml', - hour => '*/1', - user => 'root' + ensure => absent, + } + + # TODO: Remove after Puppet cycle. + file { '/etc/clustershell/tools.yaml': + ensure => absent, } $groups_config = { @@ -63,8 +60,8 @@ 'default' => 'Tools', }, 'Tools' => { - 'map' => '/usr/local/sbin/tools-clush-interpreter --hostgroups /etc/clustershell/tools.yaml map $GROUP', - 'list' => '/usr/local/sbin/tools-clush-interpreter --hostgroups /etc/clustershell/tools.yaml list', + 'map' => '/usr/local/sbin/tools-clush-generator map $GROUP', + 'list' => '/usr/local/sbin/tools-clush-generator list', } } -- To view, visit https://gerrit.wikimedia.org/r/328030 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5bb630836beb1c6a2aa2b346bef03687db9f4732 Gerrit-PatchSet: 1 Gerrit-Project: operations/puppet Gerrit-Branch: production Gerrit-Owner: Tim Landscheidt <t...@tim-landscheidt.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits