From 08b1b347949867f0df5eab827461e33b0cefe825 Mon Sep 17 00:00:00 2001 From: work Date: Wed, 11 Mar 2009 10:34:59 +0100 Subject: [PATCH] implemented detecting Murmur instances on syncdb. --- pyweb/mumble/management.py | 103 +++++++++++++++++++++++++++++++++++++ pyweb/mumble/models.py | 55 +++++++++++--------- 2 files changed, 135 insertions(+), 23 deletions(-) create mode 100644 pyweb/mumble/management.py diff --git a/pyweb/mumble/management.py b/pyweb/mumble/management.py new file mode 100644 index 0000000..2cf8fda --- /dev/null +++ b/pyweb/mumble/management.py @@ -0,0 +1,103 @@ +""" This file is part of the mumble-django application. + + Copyright (C) 2009, Michael "Svedrin" Ziegler + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the Mumble Developers nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + + +import models +import dbus +from django.db.models import signals + +def find_in_dicts( keys, conf, default, valueIfNotFound=None ): + if not isinstance( keys, tuple ): + keys = ( keys, ); + + for keyword in keys: + if keyword in conf: + return conf[keyword]; + + for keyword in keys: + keyword = keyword.lower(); + if keyword in default: + return default[keyword]; + + return valueIfNotFound; + + +def find_existing_instances( **kwargs ): + print "Searching DBus for existing murmur instances. Hope Murmur is running."; + + bus = dbus.SystemBus(); + murmur = dbus.Interface( bus.get_object( 'net.sourceforge.mumble.murmur', '/' ), 'net.sourceforge.mumble.Meta'); + + default = murmur.getDefaultConf(); + + servIDs = murmur.getAllServers(); + bootedIDs = murmur.getBootedServers(); + + for id in servIDs: + conf = murmur.getAllConf( dbus.Int32( id ) ); + # We need at least: + # name srvid addr + + values = { + "name": find_in_dicts( "registerName", conf, default, "noname" ), + "srvid": id, + "addr": find_in_dicts( ( "registerHostame", "host" ), conf, default, "0.0.0.0" ), + "port": find_in_dicts( "port", conf, default ), + "url": find_in_dicts( "registerUrl", conf, default ), + "motd": find_in_dicts( "welcometext", conf, default ), + "passwd": find_in_dicts( "password", conf, default ), + "supw": '', + "users": find_in_dicts( "users", conf, default ), + "bwidth": find_in_dicts( "bandwidth", conf, default ), + "sslcrt": find_in_dicts( "certificate", conf, default ), + "sslkey": find_in_dicts( "key", conf, default ), + "booted": ( id in bootedIDs ), + } + + if values['addr'].find( ':' ) != -1: + # The addr is a hostname which actually contains a port number, but we already got that from + # the port field, so we can simply drop it. + values['addr'] = values['addr'].split(':')[0]; + + print 'Found Murmur "%s" running on %s:%s.' % ( values['name'], values['addr'], values['port'] ); + + # now create a model for the record set. + instance = models.Mumble( **values ); + instance.save( dontConfigureMurmur=True ); + + +signals.post_syncdb.connect( find_existing_instances, sender=models ); + + + + + diff --git a/pyweb/mumble/models.py b/pyweb/mumble/models.py index 89345f9..74d76db 100644 --- a/pyweb/mumble/models.py +++ b/pyweb/mumble/models.py @@ -39,20 +39,20 @@ import dbus import socket class Mumble( models.Model ): - name = models.CharField( 'Server Name', max_length = 200 ); - dbus = models.CharField( 'DBus base', max_length = 200, default = 'net.sourceforge.mumble.murmur' ); - srvid = models.IntegerField( 'Server ID', editable = False ); - addr = models.CharField( 'Server Address', max_length = 200 ); - port = models.IntegerField( 'Server Port', blank = True, null = True ); - url = models.CharField( 'Website URL', max_length = 200, blank = True ); - motd = models.TextField( 'Welcome Message', blank = True ); - passwd = models.CharField( 'Server Password', max_length = 200, blank = True ); + name = models.CharField( 'Server Name', max_length = 200 ); + dbus = models.CharField( 'DBus base', max_length = 200, default = 'net.sourceforge.mumble.murmur' ); + srvid = models.IntegerField( 'Server ID', editable = False ); + addr = models.CharField( 'Server Address', max_length = 200 ); + port = models.IntegerField( 'Server Port', blank = True, null = True ); + url = models.CharField( 'Website URL', max_length = 200, blank = True ); + motd = models.TextField( 'Welcome Message', blank = True ); + passwd = models.CharField( 'Server Password', max_length = 200, blank = True ); supw = models.CharField( 'Superuser Password', max_length = 200, blank = True ); - users = models.IntegerField( 'Max. Users', blank = True, null = True ); - bwidth = models.IntegerField( 'Bandwidth [Bps]', blank = True, null = True ); - sslcrt = models.CharField( 'SSL Certificate', max_length = 200, blank = True ); - sslkey = models.CharField( 'SSL Key', max_length = 200, blank = True ); - booted = models.BooleanField( 'Boot Server', default = True ); + users = models.IntegerField( 'Max. Users', blank = True, null = True ); + bwidth = models.IntegerField( 'Bandwidth [Bps]', blank = True, null = True ); + sslcrt = models.TextField( 'SSL Certificate', blank = True ); + sslkey = models.TextField( 'SSL Key', blank = True ); + booted = models.BooleanField( 'Boot Server', default = True ); def getDbusMeta( self ): return dbus.Interface( dbus.SystemBus().get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta' ); @@ -60,7 +60,7 @@ class Mumble( models.Model ): def getDbusObject( self ): "Connects to DBus and returns an mmServer object representing this Murmur instance." bus = dbus.SystemBus(); - murmur = dbus.Interface( bus.get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta') + murmur = dbus.Interface( bus.get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta'); if self.srvid not in murmur.getBootedServers(): raise Exception, 'No murmur process with the given server ID (%d) is running and attached to system dbus under %s.' % ( self.srvid, self.dbus ); @@ -73,7 +73,11 @@ class Mumble( models.Model ): def __unicode__( self ): return u'Murmur "%s" (%d)' % ( self.name, self.srvid ); - def save( self ): + def save( self, dontConfigureMurmur=False ): + if dontConfigureMurmur: + # skip murmur configuration, e.g. because we're inserting models for existing servers. + return models.Model.save( self ); + # Prior to saving the model, connect to murmur via dbus and update its settings. murmur = self.getDbusMeta(); @@ -88,8 +92,8 @@ class Mumble( models.Model ): murmur.setConf( srvid, 'registerUrl', self.url ); murmur.setConf( srvid, 'welcometext', self.motd ); murmur.setConf( srvid, 'password', self.passwd ); - murmur.setConf( srvid, 'sslCert', self.sslcrt ); - murmur.setConf( srvid, 'sslKey', self.sslkey ); + murmur.setConf( srvid, 'certificate', self.sslcrt ); + murmur.setConf( srvid, 'key', self.sslkey ); if self.port is not None: murmur.setConf( srvid, 'port', str(self.port) ); @@ -102,7 +106,7 @@ class Mumble( models.Model ): murmur.setConf( srvid, 'users', '' ); if self.bwidth is not None: - murmur.setConf( srvid, 'bandwidth', str(self.port) ); + murmur.setConf( srvid, 'bandwidth', str(self.bwidth) ); else: murmur.setConf( srvid, 'bandwidth', '' ); @@ -114,6 +118,7 @@ class Mumble( models.Model ): if self.supw: murmur.setSuperUserPassword( srvid, self.supw ); + self.supw = ''; if self.booted != murmur.isBooted( dbus.Int32(self.srvid) ): if self.booted: @@ -129,7 +134,7 @@ class Mumble( models.Model ): murmur = self.getDbusMeta(); if murmur.isBooted( srvid ): murmur.stop( srvid ); - murmur.deleteServer( srvid ); + murmur.deleteServer( srvid ); @staticmethod def pre_delete_listener( **kwargs ): @@ -149,7 +154,11 @@ class MumbleUser( models.Model ): def __unicode__( self ): return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner ); - def save( self ): + def save( self, dontConfigureMurmur=False ): + if dontConfigureMurmur: + # skip murmur configuration, e.g. because we're inserting models for existing players. + return models.Model.save( self ); + # Before the record set is saved, update Murmur via dbus. murmur = self.server.getDbusObject(); @@ -159,10 +168,10 @@ class MumbleUser( models.Model ): # Update user's registration murmur.setRegistration( - dbus.Int32( self.mumbleid ), - dbus.String( self.name ), + dbus.Int32( self.mumbleid ), + dbus.String( self.name ), dbus.String( self.owner.email ), - dbus.String( self.password ) + dbus.String( self.password ) ); # Don't save the users' passwords, we don't need them anyway