This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/servers/Dispatcher/Dispatcher.py

398 lines
16 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Dispatcher"""
__version__ = '$Revision$'[11:-2]
import sys
import whrandom
glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
sys.path.insert(0, glasnostPythonDir)
import glasnost
import glasnost.common.faults as faults
import glasnost.common.tools_new as commonTools
from glasnost.server.ObjectsServer import Server, VirtualServer
from glasnost.server.tools import *
from glasnost.proxy.DispatcherProxy import callServer, getApplicationToken
applicationName = 'Dispatcher'
applicationRole = None
class DispatcherVirtualServer(VirtualServer):
"""Partial class designed for aggregation.
The aggregation of this class in the Dispatcher is used in order to provide
special virtual server, a dispatcher virtual server.
Attributes:
===========
*applicationTokens*:
The dictionnary containing all the Glasnost application token. The
key is the client token.
*serverAccessors*:
The servers access informations dictionnary, sorted by applicationId.
It consists of:
serverHostName:
The server IP adress or hostname.
serverPort:
The port where request will be sent.
isGateway:
If true (or 1), the request are sent through the Glasnost gateway.
*serverInfos*:
The role and accessor of each server, sorted by "hostName:port".
*virtualServerIds*:
The dictionnary containing all the Glasnost servers ID string
(including virtual servers) registered to this Dispatcher instance. The
key is the application Token, the value is the virtual server ID
string.
"""
applicationTokens = None
dispatcherIds = None
serverAccessors = None
defaultAccessors = None
serverInfos = None
virtualServerIds = None
def init(self):
VirtualServer.init(self)
self.applicationTokens = {}
self.defaultAccessors = {}
self.dispatcherIds = ['glasnost://system']
self.serverAccessors = {}
self.serverInfos = {}
self.virtualServerIds = {}
class Dispatcher(Server):
VirtualServer = DispatcherVirtualServer
hasMultipleVirtualServers = 0
randomGenerator = None
useDataFile = 0
def getApplicationId(self, applicationToken):
"""Get the application ID from the application token.
Keyword arguments:
==================
*applicationToken*:
The valid application token.
Return the application ID string.
Exception:
==========
*faults.UnknownApplicationToken*:
The given application token is not in the dispatcher virtual server
ids dictionnary.
"""
virtualServer = self.getVirtualServer(None)
if not virtualServer.virtualServerIds.has_key(applicationToken):
raise faults.UnknownApplicationToken(applicationToken)
return virtualServer.virtualServerIds[applicationToken]
def getApplicationToken(self, clientId):
virtualServer = self.getVirtualServer(None)
virtualServer.lock.acquire()
if virtualServer.applicationTokens.has_key(clientId):
clientToken = virtualServer.applicationTokens[clientId]
virtualServer.lock.release()
else:
while 1:
clientToken = str(self.randomGenerator.uniform(0.1, 1))[2:]
if not virtualServer.virtualServerIds.has_key(clientToken):
break
virtualServer.applicationTokens[clientId] = clientToken
virtualServer.virtualServerIds[clientToken] = clientId
virtualServer.lock.release()
virtualServer.markCoreAsDirty()
return clientToken
def getRegisteredRoles(self):
virtualServer = self.getVirtualServer(None)
dispatcherId = context.getVar('applicationId')
# Note: in the next lines, the dispatcher role ('') is removed from the
# list of roles.
if virtualServer.serverAccessors.has_key(dispatcherId):
return [serverInfo['role']
for serverInfo in virtualServer.serverInfos.values()
if virtualServer.serverAccessors.has_key(
commonTools.makeApplicationId(
dispatcherId, serverInfo['role'])) \
and serverInfo['role']]
else:
# Use the roles of the default accessors.
return [serverInfo['role']
for serverInfo in virtualServer.serverInfos.values()
if serverInfo['role']]
def getServerAccessor(self, serverId):
"""Return the server access information dictionnary.
Keyword argument:
=================
*serverId*:
The server ID string to access to.
Return the server access information dictionnary.
*Exceptions*:
=============
*faults.UnknownServerId*:
The server ID does not exists in the server dictionnary of server
access informations dictionnary.
"""
virtualServer = self.getVirtualServer(None)
if not virtualServer.serverAccessors.has_key(serverId):
serverDispatcherId = commonTools.extractDispatcherId(serverId)
if serverDispatcherId != context.getVar('dispatcherId'):
raise faults.UnknownDispatcherInId(serverId)
serverRole = commonTools.extractRole(serverId)
if not virtualServer.defaultAccessors.has_key(serverRole):
raise faults.UnknownServerId(serverId)
serverAccessor = virtualServer.defaultAccessors[serverRole]
if serverDispatcherId != self.dispatcherId:
serverAccessor = serverAccessor.copy()
serverAccessor['isDefault'] = 1
return serverAccessor
return virtualServer.serverAccessors[serverId]
def init(self):
self.randomGenerator = whrandom.whrandom()
Server.init(self)
def loadConfigOptions(self):
Server.loadConfigOptions(self)
configContext = context.get(_level = 'config')
autorizedHostNames = commonTools.getConfig(
'Security', 'RestrictRegisterTo', default = '')
autorizedHostNames = autorizedHostNames.replace(',', ' ')
autorizedHostNames = autorizedHostNames.strip().split()
configContext.setVar('autorizedHostNames', autorizedHostNames)
def registerDispatcherId(self, dispatcherId):
"""Register a new dispatcherId to the dispatcher."""
virtualServer = self.getVirtualServer(None)
# Ensure that dispatcherId has a valid syntax.
dispatcherId = commonTools.extractDispatcherId(dispatcherId)
if dispatcherId in virtualServer.dispatcherIds:
return
clientToken = context.getVar('clientToken')
if not virtualServer.virtualServerIds.has_key(clientToken):
raise faults.UnknownApplicationToken(clientToken)
clientId = virtualServer.virtualServerIds[clientToken]
virtualServer.dispatcherIds.append(dispatcherId)
print 'Registered dispatcher id "%s"' % dispatcherId
if virtualServer.serverAccessors.has_key(clientId):
clientAccessor = virtualServer.serverAccessors[clientId]
else:
clientAccessor = virtualServer.defaultAccessors[
commonTools.extractRole(clientId)]
for serverInfo in virtualServer.serverInfos.values():
serverAccessor = serverInfo['accessor']
if serverAccessor == clientAccessor:
# We must avoid to call the VirtualHosts server back, because
# when it calls registerDispatcherId at initialization, it is
# not yet ready to receive public calls (serve_forever has not
# yet been called).
continue
serverId = commonTools.makeApplicationId(
'glasnost://%s' % serverAccessor['serverHostName'],
serverInfo['role'])
print 'Calling addDispatcher(%s) for %s' % (dispatcherId, serverId)
callServer(serverId, 'addDispatcher', [
serverId, getApplicationToken(),
context.getVar('userToken'), dispatcherId])
print 'Called addDispatcher(%s) for %s' % (dispatcherId, serverId)
def registerToDispatcher(self):
applicationId = context.getVar('applicationId')
applicationToken = self.getApplicationToken(applicationId)
context.getVar('applicationTokens')[applicationId] = applicationToken
context.push(clientToken = applicationToken)
self.registerServer(self.hostName, self.port)
virtualServer = self.getVirtualServer(None)
for dispatcherId in virtualServer.dispatcherIds:
applicationToken = self.getApplicationToken(dispatcherId)
context.getVar('applicationTokens')[dispatcherId] \
= applicationToken
self.registerVirtualServer(self.hostName, self.port, dispatcherId)
context.pull()
def registerPublicMethods(self):
Server.registerPublicMethods(self)
self.registerPublicMethod('getApplicationId')
self.registerPublicMethod('getApplicationToken')
self.registerPublicMethod('getRegisteredRoles')
self.registerPublicMethod('getServerAccessor')
self.registerPublicMethod('registerDispatcherId')
self.registerPublicMethod('registerServer')
self.registerPublicMethod('registerVirtualServer')
self.registerPublicMethod('unregisterServer')
self.registerPublicMethod('unregisterVirtualServer')
def registerServer(self, serverHostName, serverPort):
virtualServer = self.getVirtualServer(None)
clientToken = context.getVar('clientToken')
if not virtualServer.virtualServerIds.has_key(clientToken):
raise faults.UnknownApplicationToken(clientToken)
clientId = virtualServer.virtualServerIds[clientToken]
clientRole = commonTools.extractRole(clientId)
serverNameAndPort = '%s:%s' % (serverHostName, serverPort)
autorizedHostNames = context.getVar('autorizedHostNames')
if autorizedHostNames and not serverHostName in autorizedHostNames:
raise faults.ServerRegistrationDenied(
serverHostName, serverPort)
accessor = {
'serverHostName': serverHostName,
'serverPort': serverPort,
}
virtualServer.serverInfos[serverNameAndPort] = {
'accessor': accessor,
'role': clientRole,
}
virtualServer.defaultAccessors[clientRole] = accessor
virtualServer.markCoreAsDirty()
print 'Registered server %s (role = %s)' % (
serverNameAndPort, clientRole)
return virtualServer.dispatcherIds
def registerVirtualServer(self, serverHostName, serverPort, serverId):
virtualServer = self.getVirtualServer(None)
# Ensure that serverId has a valid syntax.
serverId = commonTools.extractServerId(serverId)
clientToken = context.getVar('clientToken')
if not virtualServer.virtualServerIds.has_key(clientToken):
raise faults.UnknownApplicationToken(clientToken)
serverDispatcherId = commonTools.extractDispatcherId(serverId)
if not serverDispatcherId in virtualServer.dispatcherIds:
raise faults.UnknownDispatcherInId(serverId)
serverNameAndPort = '%s:%s' % (serverHostName, serverPort)
if not virtualServer.serverInfos.has_key(serverNameAndPort):
raise faults.UnregisteredServer(serverHostName, serverPort)
virtualServer.serverAccessors[serverId] = virtualServer.serverInfos[
serverNameAndPort]['accessor']
print 'Registered virtual server %s (for %s:%s)' % (
serverId, serverHostName, serverPort)
virtualServer.markCoreAsDirty()
def unregisterServer(self, serverHostName, serverPort):
virtualServer = self.getVirtualServer(None)
clientToken = context.getVar('clientToken')
if not virtualServer.virtualServerIds.has_key(clientToken):
raise faults.UnknownApplicationToken(clientToken)
serverNameAndPort = '%s:%s' % (serverHostName, serverPort)
if not virtualServer.serverInfos.has_key(serverNameAndPort):
raise faults.UnregisteredServer(serverHostName, serverPort)
serverInfo = virtualServer.serverInfos[serverNameAndPort]
serverAccessor = serverInfo['accessor']
# Unregister every virtual servers running on this server.
for virtualServerId, virtualServerAccessor in \
virtualServer.serverAccessors.items():
if virtualServerAccessor == serverAccessor:
del virtualServer.serverAccessors[virtualServerId]
del virtualServer.defaultAccessors[serverAccessor['role']]
del virtualServer.serverInfos[serverNameAndPort]
virtualServer.markCoreAsDirty()
def unregisterVirtualServer(self, serverId):
virtualServer = self.getVirtualServer(None)
clientToken = context.getVar('clientToken')
if not virtualServer.virtualServerIds.has_key(clientToken):
raise faults.UnknownApplicationToken(clientToken)
if not virtualServer.serverAccessors.has_key(serverId):
raise faults.UnknownServerId(serverId)
del virtualServer.serverAccessors[serverId]
virtualServer.markCoreAsDirty()
dispatcher = Dispatcher()
if __name__ == "__main__":
dispatcher.launch(applicationName, applicationRole)