Skip to content

Commit

Permalink
Merge pull request #7 from luisfdez/master
Browse files Browse the repository at this point in the history
Fix probing after "systemctl daemon-reexec"
  • Loading branch information
mbachry authored Oct 17, 2018
2 parents a35287b + 9c09af2 commit 212cb79
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
13 changes: 12 additions & 1 deletion collectd_systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def log_verbose(self, msg):
collectd.info('{} plugin [verbose]: {}'.format(self.plugin_name, msg))

def init_dbus(self):
self.units = {}
self.bus = dbus.SystemBus()
self.manager = dbus.Interface(self.bus.get_object('org.freedesktop.systemd1',
'/org/freedesktop/systemd1'),
Expand All @@ -39,7 +40,11 @@ def get_service_state(self, name):
if not unit:
return 'broken'
else:
return unit.Get('org.freedesktop.systemd1.Unit', 'SubState')
try:
return unit.Get('org.freedesktop.systemd1.Unit', 'SubState')
except dbus.exceptions.DBusException as e:
self.log_verbose('{} plugin: failed to monitor unit {}: {}'.format(self.plugin_name, name, e))
return 'broken'

def configure_callback(self, conf):
for node in conf.children:
Expand All @@ -65,7 +70,13 @@ def read_callback(self):
self.log_verbose('Read callback called')
for name in self.services:
full_name = name + '.service'

state = self.get_service_state(full_name)
if state == 'broken':
self.log_verbose ('Unit {0} reported as broken. Reinitializing the connection to dbus & retrying.'.format(full_name))
self.init_dbus()
state = self.get_service_state(full_name)

value = (1.0 if state == 'running' or state == 'reload' else 0.0)
self.log_verbose('Sending value: {}.{}={} (state={})'
.format(self.plugin_name, name, value, state))
Expand Down
25 changes: 25 additions & 0 deletions tests/test_collectd_systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def test_get_service_state(configured_mon):
with mock.patch('dbus.Interface', side_effect=dbus.exceptions.DBusException):
state = configured_mon.get_service_state('missing')
assert state == 'broken'
with mock.patch.object(configured_mon, 'get_unit') as m:
m().Get.side_effect=dbus.exceptions.DBusException
state = configured_mon.get_service_state('broken-cache')
assert state == 'broken'


def test_send_metrics(configured_mon):
Expand All @@ -94,3 +98,24 @@ def test_send_metrics(configured_mon):
c3_kwargs = val_mock.call_args_list[2][1]
assert c3_kwargs['plugin_instance'] == 'service3'
assert c3_kwargs['values'] == [1]


def test_retry_if_broken(configured_mon):
with mock.patch.object(configured_mon, 'get_service_state') as m:
m.side_effect = ['broken', 'running', 'failed', 'running']
with mock.patch.object(configured_mon, 'init_dbus') as idm:
with mock.patch('collectd.Values') as val_mock:
configured_mon.read_callback()
idm.assert_called_once()
assert m.call_count == 4
m.call_args_list[0][0][0] == m.call_args_list[1][0][0] == 'service1'
assert val_mock.call_count == 3
c1_kwargs = val_mock.call_args_list[0][1]
assert c1_kwargs['plugin_instance'] == 'service1'
assert c1_kwargs['values'] == [1]
c2_kwargs = val_mock.call_args_list[1][1]
assert c2_kwargs['plugin_instance'] == 'service2'
assert c2_kwargs['values'] == [0]
c3_kwargs = val_mock.call_args_list[2][1]
assert c3_kwargs['plugin_instance'] == 'service3'
assert c3_kwargs['values'] == [1]

0 comments on commit 212cb79

Please sign in to comment.