⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatcher.py

📁 Network Administration Visualized 网络管理可视化源码
💻 PY
字号:
#! /usr/bin/env python# -*- coding: ISO8859-1 -*-## Copyright 2006 UNINETT AS## This file is part of Network Administration Visualized (NAV)## NAV 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.## NAV 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 NAV; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#"""Class with common functions inherited/overrided by other dispatchers."""__copyright__ = "Copyright 2006 UNINETT AS"__license__ = "GPL"__author__ = "Stein Magnus Jodal (stein.magnus.jodal@uninett.no)"__id__ = "$Id: gammudispatcher.py 3464 2006-06-22 08:58:05Z jodal $"import loggingimport sysimport timeimport nav.smsd # eval() wants itclass DispatcherError(Exception):    """Base class for all exceptions raised by dispatchers."""class PermanentDispatcherError(DispatcherError):    """Thrown for permanent errors in dispatchers."""class DispatcherHandler(object):    """    Handler for communication with the dispatchers.        This layer makes it possible to use multiple dispatchers which works as    failovers for each other.    """    def __init__(self, config):        """Constructor."""        # Create logger        self.logger = logging.getLogger("nav.smsd.dispatcher")        # Get config        try:            self.dispatcherretry = config['dispatcher']['dispatcherretry']        except KeyError, error:            self.dispatcherretry = 300 # 5 min            self.logger.debug("Dispatcher retry time not set, using default.")        # Get dispatchers        self.dispatchers = []        for pri in range(len(config['dispatcher']) + 1):            key = 'dispatcher' + str(pri)            if key in config['dispatcher']:                dispatcher = config['dispatcher'][key]                self.logger.debug("Init dispatcher %d: %s", pri, dispatcher)                # Import dispatcher module                modulename = 'nav.smsd.' + dispatcher.lower()                try:                    module = self.importbyname(modulename)                    self.logger.debug("Imported module %s", modulename)                except DispatcherError, error:                    self.logger.warning("Failed to import %s: %s",                     dispatcher, error)                    continue                 except Exception, error:                    self.logger.exception("Unknown exception: %s", error)                # Initialize dispatcher                 try:                    instance = eval("%s.%s(%s)" % \                     (module.__name__, dispatcher, config[dispatcher]))                    self.dispatchers.append((dispatcher, instance))                    self.logger.debug("Dispatcher loaded: %s", dispatcher)                except DispatcherError, error:                    self.logger.warning("Failed to init %s: %s",                     dispatcher, error)                    continue                except Exception, error:                    self.logger.exception("Unknown exception: %s", error)    def importbyname(self, name):        """Import module given by name."""        mod = __import__(name)        components = name.split('.')        for comp in components[1:]:            mod = getattr(mod, comp)        return mod    def sendsms(self, phone, msgs):        """        Formats and sends with help of the wanted dispatcher.                Arguments:            ``phone'' is the phone number the messages are to be dispatched to.            ``msgs'' is a list of messages ordered with the most severe first.            Each message is a tuple with ID, text and severity of the message.        Returns four values:            The formatted SMS.            A list of IDs of sent messages.            A list of IDs of ignored messages.            An integer which is the sending ID if available or 0 otherwise.        Raises a DispatcherError if it doesn't find a working dispatcher and        succeeds in sending the SMS.        """        for i, (dispatchername, dispatcher) in enumerate(self.dispatchers):            if dispatcher.lastfailed:                sincelastfail = int(time.time()) - dispatcher.lastfailed                if sincelastfail < self.dispatcherretry:                    self.logger.debug("%s last failed %ds ago. Skipping.",                      dispatchername, sincelastfail)                    continue # Skip this dispatcher for now            try:                self.logger.debug("Trying %s...", dispatchername)                (sms, sent, ignored, result, smsid) = \                 dispatcher.sendsms(phone, msgs)            except PermanentDispatcherError, error:                self.logger.error("%s failed permanently to send SMS: %s",                 dispatchername, error)                self.logger.info("Removing failed dispatcher %s.",                 dispatchername)                del self.dispatchers[i]                continue # Skip to next dispatcher            except DispatcherError, error:                self.logger.warning("%s failed to send SMS: %s",                 dispatchername, error)                dispatcher.lastfailed = int(time.time())                continue # Skip to next dispatcher            except Exception, error:                self.logger.exception("Unknown exception: %s", error)            if result is False:                self.logger.warning("%s failed to send SMS: Returned false.",                 dispatchername)                dispatcher.lastfailed = int(time.time())                continue # Skip to next dispatcher                        # No exception and true result? Success!            return (sms, sent, ignored, smsid)        # Still running? All dispatchers failed permanently.        if len(self.dispatchers) == 0:            raise PermanentDispatcherError, \                  "No dispatchers available. None configured " + \                  "or all dispatchers failed permanently."        # Still running? All dispatchers failed!        raise DispatcherError, "All dispatchers failed to send SMS."class Dispatcher(object):    """The SMS dispatcher mother class."""    def __init__(self):        """Constructor."""        # Create logger        self.logger = logging.getLogger("nav.smsd.dispatcher")        # Field for last failed timestamp        self.lastfailed = None        # Max length of SMS        self.maxlen = 160        # Max length of ignored message. 15 gives us up to four digits.        self.ignlen = 15    def formatsms(self, msgs):        """        Format a SMS from one or more messages.        ``msgs'' is a list of messages ordered with the most severe first. Each        message is a tuple with ID, text and severity of the message.        Returns a tuple with the SMS, a list of IDs of sent messages and a list        of IDs of ignored messages.        Pseudo code:        If one message            SMS = message        If multiple messages            SMS = as many msgs as possible + how many was ignored        """        # Copies so we can modify them without wreaking the next SMS        maxlen = self.maxlen        ignlen = self.ignlen        msgcount = len(msgs) # Number of messages        msgno = 0 # Number of messages processed        addmsg = True # Whether we shall continue to add msgs to the SMS        tmpsms = "" # We format first and then checks the length        # The empty result        sms = ""        sent = []        ignored = []        # Concatenate as many msgs as possible        for msg in msgs:            msgno += 1            # If this is the last message we don't need to reserve space for            # the ignored count. If we have enough space, we can add the            # message itself instead. If we don't have enough space, the "+1            # see web" is added as normal.            if msgno == msgcount:                ignlen = 0            # We create a temporary SMS first and then afterwards checks if            # it's short enough to be accepted. This makes it easy to also            # count all extra space, numbering, etc.            if msgno == 1:                tmpsms = msg[1]            elif msgno == 2:                tmpsms = "1: %s; 2: %s" % (sms, msg[1])            else:                tmpsms = "%s; %d: %s" % (sms, msgno, msg[1])            # If we have enough space...            if len(tmpsms) < (maxlen - ignlen) and addmsg:                # Accept updated SMS                sms = tmpsms                sent.append(msg[0])            else:                # Ignore message                ignored.append(msg[0])                # Stop adding messages when the first fail to fit                addmsg = False        # Tell how many was ignored        if len(ignored) > 0:            sms = "%s +%d see web." % (sms, len(ignored))        return (sms, sent, ignored)    def sendsms(self, phone, msgs):        """        Empty shell for the sendsms method implemented by subclasses.                Arguments:            ``phone'' is the phone number the messages are to be dispatched to.            ``msgs'' is a list of messages ordered with the most severe first.            Each message is a tuple with ID, text and severity of the message.        Returns five values:            The formatted SMS.            A list of IDs of sent messages.            A list of IDs of ignored messages.            A boolean which is true for success and false for failure.            An integer which is the sending ID if available or 0 otherwise.        """        # Format SMS        (sms, sent, ignored) = self.formatsms(msgs)        # Send SMS        result = False        smsid = 0        return (sms, sent, ignored, result, smsid)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -