/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos-monitor

  • Committer: Teddy Hogeborn
  • Date: 2024-11-24 14:41:36 UTC
  • mfrom: (237.7.863 trunk)
  • Revision ID: teddy@recompile.se-20241124144136-0fej6fm6woitsooj
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python3 -bb
 
1
#!/usr/bin/python3 -bbI
2
2
# -*- mode: python; coding: utf-8 -*-
3
3
#
4
4
# Mandos Monitor - Control and monitor the Mandos server
23
23
#
24
24
# Contact the authors at <mandos@recompile.se>.
25
25
#
26
 
 
27
26
from __future__ import (division, absolute_import, print_function,
28
27
                        unicode_literals)
 
28
 
29
29
try:
30
30
    from future_builtins import *
31
31
except ImportError:
32
32
    pass
33
33
 
34
34
import sys
 
35
import logging
35
36
import os
36
37
import warnings
37
38
import datetime
 
39
import locale
38
40
 
39
41
import urwid.curses_display
40
42
import urwid
44
46
 
45
47
import dbus
46
48
 
47
 
import locale
48
 
 
49
 
import logging
50
 
 
51
49
if sys.version_info.major == 2:
 
50
    __metaclass__ = type
52
51
    str = unicode
 
52
    input = raw_input
 
53
 
 
54
# Show warnings by default
 
55
if not sys.warnoptions:
 
56
    warnings.simplefilter("default")
53
57
 
54
58
log = logging.getLogger(os.path.basename(sys.argv[0]))
55
59
logging.basicConfig(level="NOTSET", # Show all messages
57
61
 
58
62
logging.captureWarnings(True)   # Show warnings via the logging system
59
63
 
60
 
locale.setlocale(locale.LC_ALL, '')
 
64
locale.setlocale(locale.LC_ALL, "")
61
65
 
62
 
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
 
66
logging.getLogger("dbus.proxies").setLevel(logging.CRITICAL)
 
67
logging.getLogger("urwid").setLevel(logging.INFO)
63
68
 
64
69
# Some useful constants
65
 
domain = 'se.recompile'
66
 
server_interface = domain + '.Mandos'
67
 
client_interface = domain + '.Mandos.Client'
68
 
version = "1.8.9"
 
70
domain = "se.recompile"
 
71
server_interface = domain + ".Mandos"
 
72
client_interface = domain + ".Mandos.Client"
 
73
version = "1.8.17"
69
74
 
70
75
try:
71
76
    dbus.OBJECT_MANAGER_IFACE
90
95
                             int(fraction*1000000))  # Microseconds
91
96
 
92
97
 
93
 
class MandosClientPropertyCache(object):
 
98
class MandosClientPropertyCache:
94
99
    """This wraps a Mandos Client D-Bus proxy object, caches the
95
100
    properties and calls a hook function when any of them are
96
101
    changed.
123
128
        self.property_changed_match.remove()
124
129
 
125
130
 
126
 
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
 
131
class MandosClientWidget(MandosClientPropertyCache, urwid.Widget):
127
132
    """A Mandos Client which is visible on the screen.
128
133
    """
129
134
 
 
135
    _sizing = frozenset(["flow"])
 
136
 
130
137
    def __init__(self, server_proxy_object=None, update_hook=None,
131
138
                 delete_hook=None, **kwargs):
132
139
        # Called on update
167
174
                                         self.rejected,
168
175
                                         client_interface,
169
176
                                         byte_arrays=True))
170
 
        log.debug('Created client %s', self.properties["Name"])
 
177
        log.debug("Created client %s", self.properties["Name"])
171
178
 
172
179
    def using_timer(self, flag):
173
180
        """Call this method with True or False when timer should be
185
192
    def checker_completed(self, exitstatus, condition, command):
186
193
        if exitstatus == 0:
187
194
            log.debug('Checker for client %s (command "%s")'
188
 
                      ' succeeded', self.properties["Name"], command)
 
195
                      " succeeded", self.properties["Name"], command)
189
196
            self.update()
190
197
            return
191
198
        # Checker failed
192
199
        if os.WIFEXITED(condition):
193
200
            log.info('Checker for client %s (command "%s") failed'
194
 
                     ' with exit code %d', self.properties["Name"],
 
201
                     " with exit code %d", self.properties["Name"],
195
202
                     command, os.WEXITSTATUS(condition))
196
203
        elif os.WIFSIGNALED(condition):
197
204
            log.info('Checker for client %s (command "%s") was'
198
 
                     ' killed by signal %d', self.properties["Name"],
 
205
                     " killed by signal %d", self.properties["Name"],
199
206
                     command, os.WTERMSIG(condition))
200
207
        self.update()
201
208
 
221
228
 
222
229
    def selectable(self):
223
230
        """Make this a "selectable" widget.
224
 
        This overrides the method from urwid.FlowWidget."""
 
231
        This overrides the method from urwid.Widget."""
225
232
        return True
226
233
 
227
234
    def rows(self, maxcolrow, focus=False):
228
235
        """How many rows this widget will occupy might depend on
229
236
        whether we have focus or not.
230
 
        This overrides the method from urwid.FlowWidget"""
 
237
        This overrides the method from urwid.Widget"""
231
238
        return self.current_widget(focus).rows(maxcolrow, focus=focus)
232
239
 
233
240
    def current_widget(self, focus=False):
249
256
        # Rebuild focus and non-focus widgets using current properties
250
257
 
251
258
        # Base part of a client. Name!
252
 
        base = '{name}: '.format(name=self.properties["Name"])
 
259
        base = "{name}: ".format(name=self.properties["Name"])
253
260
        if not self.properties["Enabled"]:
254
261
            message = "DISABLED"
255
262
            self.using_timer(False)
277
284
                timer = datetime.timedelta(0)
278
285
            else:
279
286
                expires = (datetime.datetime.strptime
280
 
                           (expires, '%Y-%m-%dT%H:%M:%S.%f'))
 
287
                           (expires, "%Y-%m-%dT%H:%M:%S.%f"))
281
288
                timer = max(expires - datetime.datetime.utcnow(),
282
289
                            datetime.timedelta())
283
 
            message = ('A checker has failed! Time until client'
284
 
                       ' gets disabled: {}'
 
290
            message = ("A checker has failed! Time until client"
 
291
                       " gets disabled: {}"
285
292
                       .format(str(timer).rsplit(".", 1)[0]))
286
293
            self.using_timer(True)
287
294
        else:
325
332
 
326
333
    def render(self, maxcolrow, focus=False):
327
334
        """Render differently if we have focus.
328
 
        This overrides the method from urwid.FlowWidget"""
 
335
        This overrides the method from urwid.Widget"""
329
336
        return self.current_widget(focus).render(maxcolrow,
330
337
                                                 focus=focus)
331
338
 
332
339
    def keypress(self, maxcolrow, key):
333
340
        """Handle keys.
334
 
        This overrides the method from urwid.FlowWidget"""
 
341
        This overrides the method from urwid.Widget"""
335
342
        if key == "+":
336
343
            self.proxy.Set(client_interface, "Enabled",
337
344
                           dbus.Boolean(True), ignore_reply=True,
408
415
        return ret
409
416
 
410
417
 
411
 
class UserInterface(object):
 
418
class UserInterface:
412
419
    """This is the entire user interface - the whole screen
413
420
    with boxes, lists of client widgets, etc.
414
421
    """
471
478
                           "Mandos Monitor version " + version))
472
479
        self.add_log_line(("bold", "q: Quit  ?: Help"))
473
480
 
474
 
        self.busname = domain + '.Mandos'
 
481
        self.busname = domain + ".Mandos"
475
482
        self.main_loop = GLib.MainLoop()
476
483
 
477
484
    def client_not_found(self, key_id, address):