102
102
mandos_serv_object_manager = dbus.Interface(
103
103
mandos_dbus_object, dbus_interface=dbus.OBJECT_MANAGER_IFACE)
105
managed_objects = get_managed_objects(mandos_serv_object_manager)
105
log.debug("D-Bus: %s:%s:%s.GetManagedObjects()", dbus_busname,
106
server_dbus_path, dbus.OBJECT_MANAGER_IFACE)
108
with SilenceLogger("dbus.proxies"):
109
managed_objects = (mandos_serv_object_manager
110
.GetManagedObjects())
111
except dbus.exceptions.DBusException as e:
112
log.critical("Failed to access Mandos server through D-Bus:"
108
117
for path, ifs_and_props in managed_objects.items():
427
436
def get_mandos_dbus_object(bus):
428
log.debug("D-Bus: Connect to: (busname=%r, path=%r)",
429
dbus_busname, server_dbus_path)
430
with if_dbus_exception_log_with_exception_and_exit(
431
"Could not connect to Mandos server: %s"):
438
log.debug("D-Bus: Connect to: (busname=%r, path=%r)",
439
dbus_busname, server_dbus_path)
432
440
mandos_dbus_object = bus.get_object(dbus_busname,
433
441
server_dbus_path)
442
except dbus.exceptions.DBusException:
443
log.critical("Could not connect to Mandos server")
434
446
return mandos_dbus_object
437
@contextlib.contextmanager
438
def if_dbus_exception_log_with_exception_and_exit(*args, **kwargs):
441
except dbus.exceptions.DBusException as e:
442
log.critical(*(args + (e,)), **kwargs)
446
def get_managed_objects(object_manager):
447
log.debug("D-Bus: %s:%s:%s.GetManagedObjects()", dbus_busname,
448
server_dbus_path, dbus.OBJECT_MANAGER_IFACE)
449
with if_dbus_exception_log_with_exception_and_exit(
450
"Failed to access Mandos server through D-Bus:\n%s"):
451
with SilenceLogger("dbus.proxies"):
452
managed_objects = object_manager.GetManagedObjects()
453
return managed_objects
456
449
class SilenceLogger(object):
457
450
"Simple context manager to silence a particular logger"
458
451
def __init__(self, loggername):
842
class TestCaseWithAssertLogs(unittest.TestCase):
843
"""unittest.TestCase.assertLogs only exists in Python 3.4"""
845
if not hasattr(unittest.TestCase, "assertLogs"):
846
@contextlib.contextmanager
847
def assertLogs(self, logger, level=logging.INFO):
848
capturing_handler = self.CapturingLevelHandler(level)
849
old_level = logger.level
850
old_propagate = logger.propagate
851
logger.addHandler(capturing_handler)
852
logger.setLevel(level)
853
logger.propagate = False
855
yield capturing_handler.watcher
857
logger.propagate = old_propagate
858
logger.removeHandler(capturing_handler)
859
logger.setLevel(old_level)
860
self.assertGreater(len(capturing_handler.watcher.records),
863
class CapturingLevelHandler(logging.Handler):
864
def __init__(self, level, *args, **kwargs):
865
logging.Handler.__init__(self, *args, **kwargs)
866
self.watcher = self.LoggingWatcher([], [])
867
def emit(self, record):
868
self.watcher.records.append(record)
869
self.watcher.output.append(self.format(record))
871
LoggingWatcher = collections.namedtuple("LoggingWatcher",
875
class Test_string_to_delta(TestCaseWithAssertLogs):
835
class Test_string_to_delta(unittest.TestCase):
876
836
def test_handles_basic_rfc3339(self):
877
837
self.assertEqual(string_to_delta("PT0S"),
878
838
datetime.timedelta())
884
844
datetime.timedelta(0, 7200))
886
846
def test_falls_back_to_pre_1_6_1_with_warning(self):
887
with self.assertLogs(log, logging.WARNING):
888
value = string_to_delta("2h")
847
# assertLogs only exists in Python 3.4
848
if hasattr(self, "assertLogs"):
849
with self.assertLogs(log, logging.WARNING):
850
value = string_to_delta("2h")
852
class WarningFilter(logging.Filter):
853
"""Don't show, but record the presence of, warnings"""
854
def filter(self, record):
855
is_warning = record.levelno >= logging.WARNING
856
self.found = is_warning or getattr(self, "found",
858
return not is_warning
859
warning_filter = WarningFilter()
860
log.addFilter(warning_filter)
862
value = string_to_delta("2h")
864
log.removeFilter(warning_filter)
865
self.assertTrue(getattr(warning_filter, "found", False))
889
866
self.assertEqual(value, datetime.timedelta(0, 7200))
1042
1019
def get_object(self, busname, dbus_path):
1043
1020
raise dbus.exceptions.DBusException("Test")
1045
with self.assertLogs(log, logging.CRITICAL):
1046
with self.assertRaises(SystemExit) as e:
1047
bus = get_mandos_dbus_object(bus=MockBusFailing())
1022
# assertLogs only exists in Python 3.4
1023
if hasattr(self, "assertLogs"):
1024
with self.assertLogs(log, logging.CRITICAL):
1025
with self.assertRaises(SystemExit) as e:
1026
bus = get_mandos_dbus_object(bus=MockBus())
1028
critical_filter = self.CriticalFilter()
1029
log.addFilter(critical_filter)
1031
with self.assertRaises(SystemExit) as e:
1032
get_mandos_dbus_object(bus=MockBusFailing())
1034
log.removeFilter(critical_filter)
1035
self.assertTrue(critical_filter.found)
1049
1036
if isinstance(e.exception.code, int):
1050
1037
self.assertNotEqual(e.exception.code, 0)
1052
1039
self.assertIsNotNone(e.exception.code)
1055
class Test_get_managed_objects(TestCaseWithAssertLogs):
1056
def test_calls_and_returns_GetManagedObjects(self):
1057
managed_objects = {"/clients/foo": { "Name": "foo"}}
1058
class MockObjectManager(object):
1059
def GetManagedObjects(self):
1060
return managed_objects
1061
retval = get_managed_objects(MockObjectManager())
1062
self.assertDictEqual(managed_objects, retval)
1064
def test_logs_and_exits_on_dbus_error(self):
1065
dbus_logger = logging.getLogger("dbus.proxies")
1067
class MockObjectManagerFailing(object):
1068
def GetManagedObjects(self):
1069
dbus_logger.error("Test")
1070
raise dbus.exceptions.DBusException("Test")
1072
class CountingHandler(logging.Handler):
1074
def emit(self, record):
1077
counting_handler = CountingHandler()
1079
dbus_logger.addHandler(counting_handler)
1041
class CriticalFilter(logging.Filter):
1042
"""Don't show, but register, critical messages"""
1044
def filter(self, record):
1045
is_critical = record.levelno >= logging.CRITICAL
1046
self.found = is_critical or self.found
1047
return not is_critical
1050
class Test_SilenceLogger(unittest.TestCase):
1051
loggername = "mandos-ctl.Test_SilenceLogger"
1052
log = logging.getLogger(loggername)
1053
log.propagate = False
1054
log.addHandler(logging.NullHandler())
1057
self.counting_filter = self.CountingFilter()
1059
class CountingFilter(logging.Filter):
1060
"Count number of records"
1062
def filter(self, record):
1066
def test_should_filter_records_only_when_active(self):
1082
with self.assertLogs(log, logging.CRITICAL) as watcher:
1083
with self.assertRaises(SystemExit) as e:
1084
get_managed_objects(MockObjectManagerFailing())
1068
with SilenceLogger(self.loggername):
1069
self.log.addFilter(self.counting_filter)
1070
self.log.info("Filtered log message 1")
1071
self.log.info("Non-filtered message 2")
1072
self.log.info("Non-filtered message 3")
1086
dbus_logger.removeFilter(counting_handler)
1088
# Make sure the dbus logger was suppressed
1089
self.assertEqual(counting_handler.count, 0)
1091
# Test that the dbus_logger still works
1092
with self.assertLogs(dbus_logger, logging.ERROR):
1093
dbus_logger.error("Test")
1095
if isinstance(e.exception.code, int):
1096
self.assertNotEqual(e.exception.code, 0)
1098
self.assertIsNotNone(e.exception.code)
1074
self.log.removeFilter(self.counting_filter)
1075
self.assertEqual(self.counting_filter.count, 2)
1101
1078
class Test_commands_from_options(unittest.TestCase):