Exemple #1
0
  def issueResolved(self, issue):
    if issue != self.currentIssue: #got resolved by someone else
      return

    log("Agent %s resolved issue \"%s\" resolution=%s" % (self.name, issue.description, issue.resolution), type='issues')
    self.currentIssue = None
    self.sop = None

    if self.available and any(self.issues):
      self.engage( self.issues.next() )

    return issue
Exemple #2
0
    def issueResolved(self, issue):
        if issue != self.currentIssue:  #got resolved by someone else
            return

        log("Agent %s resolved issue \"%s\" resolution=%s" %
            (self.name, issue.description, issue.resolution),
            type='issues')
        self.currentIssue = None
        self.sop = None

        if self.available and any(self.issues):
            self.engage(self.issues.next())

        return issue
Exemple #3
0
    def postOptions(self):
        """used to decide what we need to do now. i am called by parseOptions.
        """
        if self.running: return
        #if we are given external configuration use it overrides commandline
        if self.CONFIGFILE and os.path.exists(self.CONFIGFILE):
            from ConfigParser import ConfigParser as _cf
            _config = _cf()
            _config.read(self.CONFIGFILE)
            for key in self.keys():
                if  any([ i for i in self.optFlags if key in i]):
                    continue #things like stop and nodaemon are not meant for config
                try: #attempt to update the keys
                    t = type(self[key])
                    self[key] = t(_config.get('droned', key))
                except: pass

        self.sanitize_droned(kill=self['stop'])
        if self['stop']: sys.exit(0)
Exemple #4
0
    def postOptions(self):
        """used to decide what we need to do now. i am called by parseOptions.
        """
        if self.running: return
        #if we are given external configuration use it overrides commandline
        if self.CONFIGFILE and os.path.exists(self.CONFIGFILE):
            from ConfigParser import ConfigParser as _cf
            _config = _cf()
            _config.read(self.CONFIGFILE)
            for key in self.keys():
                if any([i for i in self.optFlags if key in i]):
                    continue  #things like stop and nodaemon are not meant for config
                try:  #attempt to update the keys
                    t = type(self[key])
                    self[key] = t(_config.get('droned', key))
                except:
                    pass

        self.sanitize_droned(kill=self['stop'])
        if self['stop']: sys.exit(0)
Exemple #5
0
    def build_plugin(self, name):
        """build or lookup plugins

           @param name C{str} name of the application

           @return L{IDroneDApplication} provider
        """
        if name in self._instanceMap:
            return self._instanceMap[name]
        #create a logging router
        logging = logWithContext(
            type="%s,plugin" % (name,),
            route='application'
        )
        logging('dynamically building new plugin class')

        pluginConfig = self._config.get(name, {})
        #look up the application class by name
        className = pluginConfig.get('CLASS')
        if isinstance(className, bool) and not className:
            return None #this is explicitly disabled in config
        #get the positional constructor args from configuration
        classArgs = tuple(pluginConfig.get('CLASSARGS', ()))
        #get the constructor keyword args from configuration
        classKwargs = pluginConfig.get('CLASSKWARGS', {})

        #try to get your application plugin, defaults to builtin
        bases = (self._classMap.get(className, self._default),)
        MRO = set()
        for x in bases:
            MRO.add(x)
            for i in x.__bases__: MRO.add(i)
        #check if mro is ok
        MRO = any([b for b in MRO if ApplicationPlugin is b or \
                issubclass(b, ApplicationPlugin)])
        if not MRO:
            i = 'adding %s to %s for MRO safety' % \
                    (ApplicationPlugin, bases[0])
            logging(i) #log what we are doing to take the mystory out of it.
            bases += (ApplicationPlugin,)
        else: logging('Method Resolution Order looks good')
        logging('Adding Storage API to the Plugin.')
        bases = (StorageMixin,) + bases
        #######################################################################
        # new class defaults!!!!
        #######################################################################
        #setup the plugin by dynamically building a new class based
        #off of the provided reference design.
        newClassName = "Plugin(app=%s, class=%s)" % (name, bases[1].__name__)
        logging('creating plugin %s' % (newClassName,))
        plugin = self.makeAdaptable(type(newClassName, bases, {
            'name': property(lambda s: name),
            'service': property(lambda s: IDroneModelAppManager(s)),
            'configuration': property(lambda s: pluginConfig),
            'reactor': property(lambda s: reactor),
            'STARTUP_INFO': {
                'START_USEPTY' : 0,
                'START_CHILDFD' : {0:'w',1:'r',2:'r'},
                'START_ENV' : {},
                'START_PATH' : None,
                'START_CMD' : '/bin/true',
                'START_ARGS' : (),
            },
            'SHUTDOWN_INFO': {
                'STOP_USEPTY' : 0,
                'STOP_CHILDFD' : {0:'w',1:'r',2:'r'},
                'STOP_ENV' : {},
                'STOP_PATH' : None,
                'STOP_CMD' : '/bin/true',
                'STOP_ARGS' : (),
            },
            'startProtocol': ApplicationProtocol,
            'startProtoArgs': tuple(),
            'startProtoKwargs': dict(),
            'stopProtocol': ApplicationProtocol,
            'stopProtoArgs': tuple(),
            'stopProtoKwargs': dict(),
        })) #this guarentees we have a known API to work against
        #instantiate the plugin object with it's parameters
        self._instanceMap[name] = plugin(*classArgs, **classKwargs)
        self._instanceMap[name].log('application plugin interface initialized')
        self._pluginSetup(self._instanceMap[name])
        return self._instanceMap[name]
Exemple #6
0
 def workNextIssue(self):
   while any(self.availableAgents) and any(self.pendingIssues):
     issue = self.pendingIssues.next()
     agent = self.availableAgents.next()
     agent.engage(issue)
     issue.whenResolved(lambda result: self.workNextIssue() or result)
Exemple #7
0
    def build_plugin(self, name):
        """build or lookup plugins

           @param name C{str} name of the application

           @return L{IDroneDApplication} provider
        """
        if name in self._instanceMap:
            return self._instanceMap[name]
        #create a logging router
        logging = logWithContext(type="%s,plugin" % (name, ),
                                 route='application')
        logging('dynamically building new plugin class')

        pluginConfig = self._config.get(name, {})
        #look up the application class by name
        className = pluginConfig.get('CLASS')
        if isinstance(className, bool) and not className:
            return None  #this is explicitly disabled in config
        #get the positional constructor args from configuration
        classArgs = tuple(pluginConfig.get('CLASSARGS', ()))
        #get the constructor keyword args from configuration
        classKwargs = pluginConfig.get('CLASSKWARGS', {})

        #try to get your application plugin, defaults to builtin
        bases = (self._classMap.get(className, self._default), )
        MRO = set()
        for x in bases:
            MRO.add(x)
            for i in x.__bases__:
                MRO.add(i)
        #check if mro is ok
        MRO = any([b for b in MRO if ApplicationPlugin is b or \
                issubclass(b, ApplicationPlugin)])
        if not MRO:
            i = 'adding %s to %s for MRO safety' % \
                    (ApplicationPlugin, bases[0])
            logging(i)  #log what we are doing to take the mystory out of it.
            bases += (ApplicationPlugin, )
        else:
            logging('Method Resolution Order looks good')
        logging('Adding Storage API to the Plugin.')
        bases = (StorageMixin, ) + bases
        #######################################################################
        # new class defaults!!!!
        #######################################################################
        #setup the plugin by dynamically building a new class based
        #off of the provided reference design.
        newClassName = "Plugin(app=%s, class=%s)" % (name, bases[1].__name__)
        logging('creating plugin %s' % (newClassName, ))
        plugin = self.makeAdaptable(
            type(
                newClassName, bases, {
                    'name': property(lambda s: name),
                    'service': property(lambda s: IDroneModelAppManager(s)),
                    'configuration': property(lambda s: pluginConfig),
                    'reactor': property(lambda s: config.reactor),
                    'STARTUP_INFO': {
                        'START_USEPTY': 0,
                        'START_CHILDFD': {
                            0: 'w',
                            1: 'r',
                            2: 'r'
                        },
                        'START_ENV': {},
                        'START_PATH': None,
                        'START_CMD': '/bin/true',
                        'START_ARGS': (),
                    },
                    'SHUTDOWN_INFO': {
                        'STOP_USEPTY': 0,
                        'STOP_CHILDFD': {
                            0: 'w',
                            1: 'r',
                            2: 'r'
                        },
                        'STOP_ENV': {},
                        'STOP_PATH': None,
                        'STOP_CMD': '/bin/true',
                        'STOP_ARGS': (),
                    },
                    'startProtocol': ApplicationProtocol,
                    'startProtoArgs': tuple(),
                    'startProtoKwargs': dict(),
                    'stopProtocol': ApplicationProtocol,
                    'stopProtoArgs': tuple(),
                    'stopProtoKwargs': dict(),
                }))  #this guarentees we have a known API to work against
        #instantiate the plugin object with it's parameters
        self._instanceMap[name] = plugin(*classArgs, **classKwargs)
        self._instanceMap[name].log('application plugin interface initialized')
        self._pluginSetup(self._instanceMap[name])
        return self._instanceMap[name]
Exemple #8
0
 def workNextIssue(self):
     while any(self.availableAgents) and any(self.pendingIssues):
         issue = self.pendingIssues.next()
         agent = self.availableAgents.next()
         agent.engage(issue)
         issue.whenResolved(lambda result: self.workNextIssue() or result)
Exemple #9
0
class Team(Entity):
    jabber_service = property(lambda s: services.getService('jabber'))
    jabber_config = property(lambda s: s.jabber_service.SERVICECONFIG)
    availableAgents = property(
        lambda s: (agent for agent in s.agents if agent.available))
    available = property(lambda self: any(self.availableAgents))
    busy = property(lambda s: not s.available)
    rosterPath = property(lambda s: '%s/%s' %
                          (s.jabber_config.JABBER_TEAM_ROSTER, s.name))
    pendingIssues = property(lambda s: \
          (i for i in Issue.objects if not i.resolved and i.assignedTo == s))

    def __init__(self, name):
        self.name = name
        self.agents = set()
        self.worker = LoopingCall(self.workNextIssue)
        self.worker.start(5)
        self.loadRoster()

    def __getstate__(self):
        return {
            'name': self.name,
            'members': set(agent.jid for agent in self.agents),
        }

    @staticmethod
    def construct(state):
        team = Team(state['name'])
        team.agents = set(SupportAgent(jid) for jid in state['members'])
        return team

    def loadRoster(self):
        if not os.path.exists(self.rosterPath):
            log('no roster exists for the %s team, so it has no members!' %
                self.name,
                warning=True)
            return
        for line in open(self.rosterPath):
            line = line.strip()
            if not line or line.startswith('#'): continue
            jid = line
            agent = SupportAgent(jid)
            self.agents.add(agent)

    def saveRoster(self):
        jids = [agent.jid for agent in self.agents]
        content = '\n'.join(jids) + '\n'

        def blockingWrite():
            roster = open(self.rosterPath, 'w')
            roster.write(content)
            roster.close()

        config.reactor.callInThread(blockingWrite)

    def addMember(self, jid):
        self.agents.add(SupportAgent(jid))
        self.saveRoster()

    def removeMember(self, jid):
        self.agents.discard(SupportAgent(jid))
        self.saveRoster()

    def workNextIssue(self):
        while any(self.availableAgents) and any(self.pendingIssues):
            issue = self.pendingIssues.next()
            agent = self.availableAgents.next()
            agent.engage(issue)
            issue.whenResolved(lambda result: self.workNextIssue() or result)

    def notify(self, message):
        for agent in self.agents:
            agent.tell("<b>%s team notification:</b> %s" %
                       (self.name, message))