import grok import logging import os from zope.authentication.interfaces import IAuthentication from zope.component import createObject, getUtilitiesFor from zope.component.interfaces import ObjectEvent from zope.pluggableauth import PluggableAuthentication from waeup.sirp.authentication import setup_authentication from waeup.sirp.datacenter import DataCenter from waeup.sirp.interfaces import ( IUniversity, IDataCenter, IWAeUPSIRPPluggable, IDataCenterStorageMovedEvent, IObjectUpgradeEvent, ) from waeup.sirp.users import UserContainer from waeup.sirp.utils.helpers import attrs_to_fields class University(grok.Application, grok.Container): """A university. """ grok.implements(IUniversity) # Setup authentication for this app. Note: this is only # initialized, when a new instance of this app is created. grok.local_utility( PluggableAuthentication, provides = IAuthentication, setup = setup_authentication,) @property def logger(self): """The application logger. Returns a standard logger object as provided by :mod:`logging` module from the standard library. Other components can use this logger to perform log entries into the 'main' logfile. The logger is initialized the first time, it is called. """ sitename = self.__name__ loggername = 'waeup.sirp.%s' % sitename logger = logging.getLogger(loggername) if not logger.handlers: logger = self._setupLogger(logger) return logger def __init__(self, name=None, skin=None, title=None, frontpage=None, **kw): super(University, self).__init__(**kw) if name is not None: self.name = name if skin is not None: self.skin = skin if title is not None: self.title = title if frontpage is not None: self.frontpage = frontpage self.setup() def setup(self): """Setup some hard-wired components. Create local datacenter, containers for users, students and the like. """ self['users'] = UserContainer() self['datacenter'] = DataCenter() self['students'] = createObject(u'waeup.StudentContainer') self['hostels'] = createObject(u'waeup.HostelContainer') self._createPlugins() def _createPlugins(self): """Create instances of all plugins defined somewhere. """ for name, plugin in getUtilitiesFor(IWAeUPSIRPPluggable): plugin.setup(self, name, self.logger) return def updatePlugins(self): """Lookup all plugins and call their `update()` method. """ name = getattr(self, '__name__', '') self.logger.info('Fire upgrade event for site %s' % name) grok.notify(ObjectUpgradeEvent(self)) self.logger.info('Done.') self.logger.info('Now upgrading any plugins.') for name, plugin in getUtilitiesFor(IWAeUPSIRPPluggable): plugin.update(self, name, self.logger) self.logger.info('Plugin update finished.') return def _setupLogger(self, logger): """Setup general application logger. The logfile will be stored in the datacenter logs/ dir. """ logdir = os.path.join(self['datacenter'].storage, 'logs') if not os.path.exists(logdir): os.mkdir(logdir) filename = os.path.join(logdir, 'main.log') # Create a rotating file handler logger for application. handler = logging.handlers.RotatingFileHandler( filename, maxBytes=5*1024**1, backupCount=7) formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) # Don't send log msgs to ancestors. This stops displaying # logmessages on the commandline. logger.propagate = False logger.addHandler(handler) return logger attrs_to_fields(University) @grok.subscribe(IDataCenter, IDataCenterStorageMovedEvent) def handle_storage_move(obj, event): """Event handler, in case datacenter storage moves. We initialize the application log again, then. """ app = grok.getSite() if app is None: return if obj is not app['datacenter']: return logger = app.logger logger.warn('Log Dir moved. Closing.') handlers = logger.handlers for handler in handlers: logger.removeHandler(handler) app._setupLogger(logger) logger.warn('Log file moved. Opening.') class ObjectUpgradeEvent(ObjectEvent): """An event fired, when datacenter storage moves. """ grok.implements(IObjectUpgradeEvent)