diff --git a/config.cfg b/config.cfg index ab53309..d9925ee 100644 --- a/config.cfg +++ b/config.cfg @@ -24,6 +24,8 @@ do_package_upgrade=yes # restart services affected by previous upgrades do_service_restart=yes +# what to do with identified services by default. See services section. +default_service_policy=ignore # do depclean on Gentoo do_depclean=yes @@ -48,8 +50,15 @@ dev-db/postgresql=1 gitlab=1 -# The services section contains = +# The processes section contains = # The process name is whatever psutil returns and I haven't checked if it's # trustworthy, so it's probably not... Use with care. -[services] +# To ignore processes, just add them with empty values +[processes] gitlab-workhorse=gitlab +qemu-system-x86_64= + +# The services section contains restart policy for specific services. +# valid policies are 'ignore', 'warn' and 'restart'. +[services] +libvirtd=ignore diff --git a/sau/services.py b/sau/services.py index 96d6ad9..b6aa3f0 100644 --- a/sau/services.py +++ b/sau/services.py @@ -100,6 +100,8 @@ def restart_services(): retest_procs.add(proc) services = set() + processes = set() + services = {} for proc in service_procs: try: service_exe = proc.exe() @@ -108,7 +110,15 @@ def restart_services(): log.debug('{} died before it could be restarted'.format(proc)) continue - service_name = conf.get('services', proc_name, fallback=None) + if proc_name in services: + # we have already checked a process with this name + continue + + service_name = conf.get('processes', proc_name, fallback=False) + if service_name == None: + log.debug('Ignoring process {}'.format(proc)) + continue + if not service_name: # if the exe file has been deleted since started, service_exe will be empty # and we'll have to guess @@ -125,23 +135,51 @@ def restart_services(): log.warning('Could not find service for process {}'.format(proc)) continue - if service_name: - services.add(service_name) + services[proc_name] = service_name + + for service in [x for x in services.values() if x]: + policy = _get_service_restart_policy(service) + if policy == 'ignore': + log.info('Service "{}" ignored by configuration'.format(service)) + continue + elif policy == 'warn': + log.warning('Service "{}" has open deleted files and should be restarted'.format(service)) + continue - for service in services: log.info('Restarting service {}'.format(service)) platform.restart_service(service) recommend_restart = False for proc in retest_procs: try: - exe = proc.exe() name = proc.name() except (psutil.NoSuchProcess, psutil.ZombieProcess, psutil.AccessDenied): log.debug('{} was successfully killed'.format(proc)) continue if _get_deleted_open_files(proc): + if name in services and not services[name]: + log.warning('{} does not belong to a service and could not be restarted'.format(proc)) + recommend_restart = True + continue + elif name in services: + policy = _get_service_restart_policy(services[name]) + if policy == 'ignore': + continue log.warning('{} still has deleted files open'.format(proc)) recommend_restart = True return recommend_restart + +def _get_service_restart_policy(service): + conf = sau.config + policy = conf.get('services', service, fallback=None) + if policy and policy.lower() in ('restart', 'warn', 'ignore'): + return policy.lower() + elif policy: + log.warning('service policy {} for {} is invalid'.format(policy, service)) + + default_policy = conf.get('services', 'default_service_policy', fallback='warn') + if default_policy.lower() in ('restart', 'warn', 'ignore'): + return default_policy.lower() + log.warning('default service policy {} is invalid'.format(default_policy)) + return 'warn'