Ori.livneh has uploaded a new change for review. https://gerrit.wikimedia.org/r/108312
Change subject: Add misc::evergreen resource to refresh services on config updates ...................................................................... Add misc::evergreen resource to refresh services on config updates If a role that writes its configuration to a recursively-managed foo.d/-type directory is disabled, its configuration file will be purged, but the service it configures will not necessarily be refreshed. This patch adds a misc::evergreen resource that takes a service name and one or more paths to search. If the most recent modification time of the path or any of the files or directories within it is newer than the oldest instance of the service, the service is automatically refreshed. Change-Id: Ib969eb352461ab655d1b0f368c91e6737122f1c3 --- M puppet/modules/apache/manifests/init.pp A puppet/modules/misc/files/check_service_freshness A puppet/modules/misc/manifests/evergreen.pp M puppet/modules/misc/manifests/init.pp 4 files changed, 116 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/vagrant refs/changes/12/108312/1 diff --git a/puppet/modules/apache/manifests/init.pp b/puppet/modules/apache/manifests/init.pp index 84a088c..cd96d06 100644 --- a/puppet/modules/apache/manifests/init.pp +++ b/puppet/modules/apache/manifests/init.pp @@ -35,4 +35,6 @@ require => Package['apache2'], hasrestart => true, } + + misc::evergreen { 'apache2': } } diff --git a/puppet/modules/misc/files/check_service_freshness b/puppet/modules/misc/files/check_service_freshness new file mode 100755 index 0000000..d7c7cd4 --- /dev/null +++ b/puppet/modules/misc/files/check_service_freshness @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + check_service_freshness + + Usage: check_service_freshness program_name config_path [config_path ...] + Example: check_service_freshness apache2 /etc/apache2 + + If the most recently-modified file in `config_path` is newer than the oldest + running process with `program_name` as its executable, set exit code to 1, + indicating that the service needs to be restarted to load the updated + configs. Otherwise set exit code to 0, indicating that the service is + up-to-date. + +""" +import os +import re +import sys + + +JIFFY = os.sysconf('SC_CLK_TCK') + +if len(sys.argv) < 3: + sys.stderr.write('Usage: %s program_name config_path [config_path ...]\n' + % __file__) + sys.exit(126) + +program_name, config_paths = sys.argv[1], sys.argv[2:] + + +def get_system_start(): + """Get the system start time, expressed as seconds since epoch.""" + with open('/proc/stat') as f: + match = re.search('(?<=btime )\d+', f.read()) + return float(match.group(0)) + + +def iter_files(dir): + """Yields (path, mtime) for `dir` and each file or dir within it.""" + yield dir, os.path.getmtime(dir) + for root, dirs, files in os.walk('/etc/apache2'): + for f in (dirs + files): + path = os.path.join(root, f) + yield path, os.path.getmtime(path) + + +def iter_procs(): + """Yields (executable name, start time) for each running process.""" + system_start = get_system_start() + for pid in os.listdir('/proc'): + try: + with open('/proc/%s/stat' % pid) as f: + stats = f.read().split() + executable = stats[1].strip('()') + start_time = (float(stats[21]) / JIFFY) + system_start + yield executable, start_time + except (IOError, ValueError): + pass + + +service_start = min(start_time for executable_name, start_time in iter_procs() + if executable_name == program_name) +latest_modification = max(modified_time for config_path in config_paths + for path, modified_time in iter_files(config_path)) + +if service_start < latest_modification: + # Service needs to be refreshed + sys.exit(1) +else: + # Service is up-to-date + sys.exit(0) diff --git a/puppet/modules/misc/manifests/evergreen.pp b/puppet/modules/misc/manifests/evergreen.pp new file mode 100644 index 0000000..84ddcac --- /dev/null +++ b/puppet/modules/misc/manifests/evergreen.pp @@ -0,0 +1,38 @@ +# == Define: misc::evergreen +# +# Refresh a service if its configuration files have changed. +# +# === Parameters +# +# [*service*] +# Service name. Defaults to the resource title. +# +# [*executable*] +# Base name of program's executable file. The process table will be +# scanned for processes matching this name to determine if the service +# needs to be refreshed. Defaults to the resource title. +# +# [*config_path*] +# Path to service's configuration directory. Defaults to /etc/$title. +# Multiple paths may be specified as an array. +# +# === Examples +# +# misc::evergreen { 'apache2': +# config_path => '/etc/apache2', +# } +# +define misc::evergreen( + $service = $title, + $executable = $title, + $config_path = "/etc/${title}", +) { + include ::misc + + exec { "check ${service} freshness": + command => '/bin/true', + unless => "/usr/sbin/check_service_freshness ${executable} ${config_path}", + require => File['/usr/sbin/check_service_freshness'], + notify => Service[$service], + } +} diff --git a/puppet/modules/misc/manifests/init.pp b/puppet/modules/misc/manifests/init.pp index 772e042..0dc67f3 100644 --- a/puppet/modules/misc/manifests/init.pp +++ b/puppet/modules/misc/manifests/init.pp @@ -49,6 +49,11 @@ source => 'puppet:///modules/misc/mediawiki-vagrant.logrotate', } + file { '/usr/sbin/check_service_freshness': + source => 'puppet:///modules/misc/check_service_freshness', + mode => '0755', + } + # Look, I didn't pick the name.. package { [ 'toilet', 'toilet-fonts' ]: ensure => present, -- To view, visit https://gerrit.wikimedia.org/r/108312 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ib969eb352461ab655d1b0f368c91e6737122f1c3 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/vagrant Gerrit-Branch: master Gerrit-Owner: Ori.livneh <o...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits