diff options
Diffstat (limited to 'src/lib/Bcfg2/Client/Tools/Systemd.py')
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Systemd.py | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/src/lib/Bcfg2/Client/Tools/Systemd.py b/src/lib/Bcfg2/Client/Tools/Systemd.py index 027d91c71..f7e5b1b0b 100644 --- a/src/lib/Bcfg2/Client/Tools/Systemd.py +++ b/src/lib/Bcfg2/Client/Tools/Systemd.py @@ -13,34 +13,81 @@ class Systemd(Bcfg2.Client.Tools.SvcTool): __handles__ = [('Service', 'systemd')] __req__ = {'Service': ['name', 'status']} + def get_svc_name(self, service): + """Append .service to name if name doesn't specify a unit type.""" + svc = service.get('name') + if svc.endswith(('.service', '.socket', '.device', '.mount', + '.automount', '.swap', '.target', '.path', + '.timer', '.snapshot', '.slice', '.scope')): + return svc + else: + return '%s.service' % svc + def get_svc_command(self, service, action): - return "/bin/systemctl %s %s.service" % (action, service.get('name')) + return "/bin/systemctl %s %s" % (action, self.get_svc_name(service)) def VerifyService(self, entry, _): """Verify Service status for entry.""" - if entry.get('status') == 'ignore': + entry.set('target_status', entry.get('status')) # for reporting + + bootstatus = self.get_bootstatus(entry) + if bootstatus is None: + # bootstatus is unspecified and status is ignore return True - cmd = "/bin/systemctl status %s.service " % (entry.get('name')) - rv = self.cmd.run(cmd) + if self.cmd.run(self.get_svc_command(entry, 'is-enabled')): + current_bootstatus = 'on' + else: + current_bootstatus = 'off' - if 'Loaded: error' in rv.stdout: - entry.set('current_status', 'off') - return False - elif 'Active: active' in rv.stdout: - entry.set('current_status', 'on') - return entry.get('status') == 'on' + if entry.get('status') == 'ignore': + return current_bootstatus == bootstatus + + cmd = self.get_svc_command(entry, 'show') + ' -p ActiveState' + rv = self.cmd.run(cmd) + if rv.stdout.strip() in ('ActiveState=active', + 'ActiveState=activating', + 'ActiveState=reloading'): + current_status = 'on' else: - entry.set('current_status', 'off') - return entry.get('status') == 'off' + current_status = 'off' + entry.set('current_status', current_status) + return (entry.get('status') == current_status and + bootstatus == current_bootstatus) def InstallService(self, entry): """Install Service entry.""" - if entry.get('status') == 'on': - rv = self.cmd.run(self.get_svc_command(entry, 'enable')).success - rv &= self.cmd.run(self.get_svc_command(entry, 'start')).success + self.logger.info("Installing Service %s" % (entry.get('name'))) + bootstatus = self.get_bootstatus(entry) + if bootstatus is None: + # bootstatus is unspecified and status is ignore + return True + + # Enable or disable the service + if bootstatus == 'on': + cmd = self.get_svc_command(entry, 'enable') + else: + cmd = self.get_svc_command(entry, 'disable') + if not self.cmd.run(cmd).success: + # Return failure immediately and do not start/stop the service. + return False + + # Start or stop the service, depending on the current servicemode + cmd = None + if Bcfg2.Options.setup.servicemode == 'disabled': + # 'disabled' means we don't attempt to modify running svcs + pass + elif Bcfg2.Options.setup.servicemode == 'build': + # 'build' means we attempt to stop all services started + if entry.get('current_status') == 'on': + cmd = self.get_svc_command(entry, 'stop') else: - rv = self.cmd.run(self.get_svc_command(entry, 'stop')).success - rv &= self.cmd.run(self.get_svc_command(entry, 'disable')).success + if entry.get('status') == 'on': + cmd = self.get_svc_command(entry, 'start') + else: + cmd = self.get_svc_command(entry, 'stop') - return rv + if cmd: + return self.cmd.run(cmd).success + else: + return True |