/mandos/trunk

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

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2009-04-16 10:41:41 UTC
  • Revision ID: teddy@fukt.bsnet.se-20090416104141-19m1kqbwr5v1q416
Code cleanup.

* mandos: Move some global stuff into classes.
  (server, group): Moved into "AvahiService".  All users changed.
  (AvahiService.group, AvahiService.server): New attributes.
  (entry_group_state_changed, server_state_changed): Moved into
                                                     "AvahiService".
                                                     All callers
                                                     changed.
  (AvahiService.cleanup, AvahiService.activate): New.
  (_datetime_to_dbus): Moved into "ClientDBus".  All callers changed.
  (ClientDBus._datetime_to_dbus): New.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
# This program is partly derived from an example program for an Avahi
7
7
# service publisher, downloaded from
8
8
# <http://avahi.org/wiki/PythonPublishExample>.  This includes the
9
 
# methods "add" and "remove" in the "AvahiService" class, the
10
 
# "server_state_changed" and "entry_group_state_changed" functions,
11
 
# and some lines in "main".
 
9
# methods "add", "remove", "server_state_changed",
 
10
# "entry_group_state_changed", "cleanup", and "activate" in the
 
11
# "AvahiService" class, and some lines in "main".
12
12
13
13
# Everything else is
14
14
# Copyright © 2008,2009 Teddy Hogeborn
124
124
    max_renames: integer; maximum number of renames
125
125
    rename_count: integer; counter so we only rename after collisions
126
126
                  a sensible number of times
 
127
    group: D-Bus Entry Group
 
128
    server: D-Bus Server
127
129
    """
128
130
    def __init__(self, interface = avahi.IF_UNSPEC, name = None,
129
131
                 servicetype = None, port = None, TXT = None,
139
141
        self.rename_count = 0
140
142
        self.max_renames = max_renames
141
143
        self.protocol = protocol
 
144
        self.group = None       # our entry group
 
145
        self.server = None
142
146
    def rename(self):
143
147
        """Derived from the Avahi example code"""
144
148
        if self.rename_count >= self.max_renames:
146
150
                            u" after %i retries, exiting.",
147
151
                            self.rename_count)
148
152
            raise AvahiServiceError(u"Too many renames")
149
 
        self.name = server.GetAlternativeServiceName(self.name)
 
153
        self.name = self.server.GetAlternativeServiceName(self.name)
150
154
        logger.info(u"Changing Zeroconf service name to %r ...",
151
 
                    self.name)
 
155
                    unicode(self.name))
152
156
        syslogger.setFormatter(logging.Formatter
153
157
                               (u'Mandos (%s) [%%(process)d]:'
154
158
                                u' %%(levelname)s: %%(message)s'
158
162
        self.rename_count += 1
159
163
    def remove(self):
160
164
        """Derived from the Avahi example code"""
161
 
        if group is not None:
162
 
            group.Reset()
 
165
        if self.group is not None:
 
166
            self.group.Reset()
163
167
    def add(self):
164
168
        """Derived from the Avahi example code"""
165
 
        global group
166
 
        if group is None:
167
 
            group = dbus.Interface(bus.get_object
168
 
                                   (avahi.DBUS_NAME,
169
 
                                    server.EntryGroupNew()),
170
 
                                   avahi.DBUS_INTERFACE_ENTRY_GROUP)
171
 
            group.connect_to_signal('StateChanged',
172
 
                                    entry_group_state_changed)
 
169
        if self.group is None:
 
170
            self.group = dbus.Interface(
 
171
                bus.get_object(avahi.DBUS_NAME,
 
172
                               self.server.EntryGroupNew()),
 
173
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
 
174
            self.group.connect_to_signal('StateChanged',
 
175
                                         self.entry_group_state_changed)
173
176
        logger.debug(u"Adding Zeroconf service '%s' of type '%s' ...",
174
 
                     service.name, service.type)
175
 
        group.AddService(
176
 
                self.interface,         # interface
177
 
                self.protocol,          # protocol
178
 
                dbus.UInt32(0),         # flags
179
 
                self.name, self.type,
180
 
                self.domain, self.host,
181
 
                dbus.UInt16(self.port),
182
 
                avahi.string_array_to_txt_array(self.TXT))
183
 
        group.Commit()
184
 
 
185
 
# From the Avahi example code:
186
 
group = None                            # our entry group
187
 
# End of Avahi example code
188
 
 
189
 
 
190
 
def _datetime_to_dbus(dt, variant_level=0):
191
 
    """Convert a UTC datetime.datetime() to a D-Bus type."""
192
 
    return dbus.String(dt.isoformat(), variant_level=variant_level)
 
177
                     self.name, self.type)
 
178
        self.group.AddService(
 
179
            self.interface,
 
180
            self.protocol,
 
181
            dbus.UInt32(0),     # flags
 
182
            self.name, self.type,
 
183
            self.domain, self.host,
 
184
            dbus.UInt16(self.port),
 
185
            avahi.string_array_to_txt_array(self.TXT))
 
186
        self.group.Commit()
 
187
    def entry_group_state_changed(self, state, error):
 
188
        """Derived from the Avahi example code"""
 
189
        logger.debug(u"Avahi state change: %i", state)
 
190
        
 
191
        if state == avahi.ENTRY_GROUP_ESTABLISHED:
 
192
            logger.debug(u"Zeroconf service established.")
 
193
        elif state == avahi.ENTRY_GROUP_COLLISION:
 
194
            logger.warning(u"Zeroconf service name collision.")
 
195
            self.rename()
 
196
        elif state == avahi.ENTRY_GROUP_FAILURE:
 
197
            logger.critical(u"Avahi: Error in group state changed %s",
 
198
                            unicode(error))
 
199
            raise AvahiGroupError(u"State changed: %s"
 
200
                                  % unicode(error))
 
201
    def cleanup(self):
 
202
        """Derived from the Avahi example code"""
 
203
        if self.group is not None:
 
204
            self.group.Free()
 
205
            self.group = None
 
206
    def server_state_changed(self, state):
 
207
        """Derived from the Avahi example code"""
 
208
        if state == avahi.SERVER_COLLISION:
 
209
            logger.error(u"Zeroconf server name collision")
 
210
            self.remove()
 
211
        elif state == avahi.SERVER_RUNNING:
 
212
            self.add()
 
213
    def activate(self):
 
214
        """Derived from the Avahi example code"""
 
215
        if self.server is None:
 
216
            self.server = dbus.Interface(
 
217
                bus.get_object(avahi.DBUS_NAME,
 
218
                               avahi.DBUS_PATH_SERVER),
 
219
                avahi.DBUS_INTERFACE_SERVER)
 
220
        self.server.connect_to_signal(u"StateChanged",
 
221
                                 self.server_state_changed)
 
222
        self.server_state_changed(self.server.GetState())
193
223
 
194
224
 
195
225
class Client(object):
459
489
                                  + self.name.replace(u".", u"_")))
460
490
        dbus.service.Object.__init__(self, bus,
461
491
                                     self.dbus_object_path)
 
492
    
 
493
    @staticmethod
 
494
    def _datetime_to_dbus(dt, variant_level=0):
 
495
        """Convert a UTC datetime.datetime() to a D-Bus type."""
 
496
        return dbus.String(dt.isoformat(),
 
497
                           variant_level=variant_level)
 
498
    
462
499
    def enable(self):
463
500
        oldstate = getattr(self, u"enabled", False)
464
501
        r = Client.enable(self)
466
503
            # Emit D-Bus signals
467
504
            self.PropertyChanged(dbus.String(u"enabled"),
468
505
                                 dbus.Boolean(True, variant_level=1))
469
 
            self.PropertyChanged(dbus.String(u"last_enabled"),
470
 
                                 (_datetime_to_dbus(self.last_enabled,
471
 
                                                    variant_level=1)))
 
506
            self.PropertyChanged(
 
507
                dbus.String(u"last_enabled"),
 
508
                self._datetime_to_dbus(self.last_enabled,
 
509
                                       variant_level=1))
472
510
        return r
473
511
    
474
512
    def disable(self, signal = True):
516
554
        # Emit D-Bus signal
517
555
        self.PropertyChanged(
518
556
            dbus.String(u"last_checked_ok"),
519
 
            (_datetime_to_dbus(self.last_checked_ok,
520
 
                               variant_level=1)))
 
557
            (self._datetime_to_dbus(self.last_checked_ok,
 
558
                                    variant_level=1)))
521
559
        return r
522
560
    
523
561
    def start_checker(self, *args, **kwargs):
578
616
                dbus.String(u"host"):
579
617
                    dbus.String(self.host, variant_level=1),
580
618
                dbus.String(u"created"):
581
 
                    _datetime_to_dbus(self.created, variant_level=1),
 
619
                    self._datetime_to_dbus(self.created,
 
620
                                           variant_level=1),
582
621
                dbus.String(u"last_enabled"):
583
 
                    (_datetime_to_dbus(self.last_enabled,
584
 
                                       variant_level=1)
 
622
                    (self._datetime_to_dbus(self.last_enabled,
 
623
                                            variant_level=1)
585
624
                     if self.last_enabled is not None
586
625
                     else dbus.Boolean(False, variant_level=1)),
587
626
                dbus.String(u"enabled"):
588
627
                    dbus.Boolean(self.enabled, variant_level=1),
589
628
                dbus.String(u"last_checked_ok"):
590
 
                    (_datetime_to_dbus(self.last_checked_ok,
591
 
                                       variant_level=1)
 
629
                    (self._datetime_to_dbus(self.last_checked_ok,
 
630
                                            variant_level=1)
592
631
                     if self.last_checked_ok is not None
593
632
                     else dbus.Boolean (False, variant_level=1)),
594
633
                dbus.String(u"timeout"):
1049
1088
    return timevalue
1050
1089
 
1051
1090
 
1052
 
def server_state_changed(state):
1053
 
    """Derived from the Avahi example code"""
1054
 
    if state == avahi.SERVER_COLLISION:
1055
 
        logger.error(u"Zeroconf server name collision")
1056
 
        service.remove()
1057
 
    elif state == avahi.SERVER_RUNNING:
1058
 
        service.add()
1059
 
 
1060
 
 
1061
 
def entry_group_state_changed(state, error):
1062
 
    """Derived from the Avahi example code"""
1063
 
    logger.debug(u"Avahi state change: %i", state)
1064
 
    
1065
 
    if state == avahi.ENTRY_GROUP_ESTABLISHED:
1066
 
        logger.debug(u"Zeroconf service established.")
1067
 
    elif state == avahi.ENTRY_GROUP_COLLISION:
1068
 
        logger.warning(u"Zeroconf service name collision.")
1069
 
        service.rename()
1070
 
    elif state == avahi.ENTRY_GROUP_FAILURE:
1071
 
        logger.critical(u"Avahi: Error in group state changed %s",
1072
 
                        unicode(error))
1073
 
        raise AvahiGroupError(u"State changed: %s" % unicode(error))
1074
 
 
1075
1091
def if_nametoindex(interface):
1076
1092
    """Call the C function if_nametoindex(), or equivalent
1077
1093
    
1292
1308
    
1293
1309
    global main_loop
1294
1310
    global bus
1295
 
    global server
1296
1311
    # From the Avahi example code
1297
1312
    DBusGMainLoop(set_as_default=True )
1298
1313
    main_loop = gobject.MainLoop()
1299
1314
    bus = dbus.SystemBus()
1300
 
    server = dbus.Interface(bus.get_object(avahi.DBUS_NAME,
1301
 
                                           avahi.DBUS_PATH_SERVER),
1302
 
                            avahi.DBUS_INTERFACE_SERVER)
1303
1315
    # End of Avahi example code
1304
1316
    if use_dbus:
1305
1317
        bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos", bus)
1341
1353
    
1342
1354
    def cleanup():
1343
1355
        "Cleanup function; run on exit"
1344
 
        global group
1345
 
        # From the Avahi example code
1346
 
        if not group is None:
1347
 
            group.Free()
1348
 
            group = None
1349
 
        # End of Avahi example code
 
1356
        service.cleanup()
1350
1357
        
1351
1358
        while clients:
1352
1359
            client = clients.pop()
1438
1445
    
1439
1446
    try:
1440
1447
        # From the Avahi example code
1441
 
        server.connect_to_signal(u"StateChanged", server_state_changed)
1442
1448
        try:
1443
 
            server_state_changed(server.GetState())
 
1449
            service.activate()
1444
1450
        except dbus.exceptions.DBusException, error:
1445
1451
            logger.critical(u"DBusException: %s", error)
1446
1452
            sys.exit(1)