Esempio n. 1
0
 def _event(self, result, event_type):
     if Event.exists(event_type):
         Event(event_type).fire(alert=self, 
             severity=result[0], event=result[1],
             otherInfo=result[2]
         )
     return self #transform the callback so the caller get's us
Esempio n. 2
0
    def __init__(self, service, name, callback, **kwargs):
        """
           
        """
        #get ready for python3
        if not hasattr(callback, '__call__'):
            raise AssertionError("%s is not callable" % (callback.__name__, ))

        event_name = str(service) + '-' + str(name)
        self.event = Event(event_name)
        self.name = name
        self.loop = None
        self.service = service

        #borderline laziness on my part
        self.log = AppManager(service).log

        self.condition = kwargs.get('condition', None)
        self.recurring = float(kwargs.get('recurring', 0))
        self.silent = kwargs.get('silent', False)

        assert not (self.recurring and self.condition), \
            "recurring and condition args are mutually exclusive"

        self.func = callback.__name__
        if not self.silent:
            self.event.subscribe(self.announce)
        #send data only if we have it, keeps compatibility with legacy api
        self.event.subscribe(lambda x: (hasattr(x, 'params') and x.params) \
            and callback(x) or callback())

        #our event loop is controlled by the Service
        if self.recurring > 0.0:
            self.loop = LoopingCall(self.event.fire)
            self.occurred()  #automatically start re-occuring events
Esempio n. 3
0
 def _setenabled(self, enabled):
     enabled = bool(enabled)
     status = self._getenabled()
     self.info['enabled'] = enabled
     if (enabled != status) and enabled:
         Event('instance-enabled').fire(instance=self)
     elif (enabled != status) and not enabled:
         Event('instance-disabled').fire(instance=self)
Esempio n. 4
0
 def stopService(self):
     Event('instance-started').unsubscribe(self.write)
     Event('signal').unsubscribe(self.write)
     Event('journal-error').unsubscribe(self._journal_failure)
     if self._task.running: self._task.stop()
     if not self.writing.called:
         self.writing.addBoth(lambda x: Service.stopService(self) and x or x)
         return self.writing #the main service will deal with it
     Service.stopService(self)
Esempio n. 5
0
def notification(conversation, event, string):
    #hopefully you know how to parse this string
    if Event.exists(event):
        context = {
            'conversation': conversation,
            'message': string,
            'event': event,
        }
        Event(event).fire(**context)
Esempio n. 6
0
 def startService(self):
     self._task = task.LoopingCall(self.write)
     #delay first journaling
     config.reactor.callLater(
         config.JOURNAL_FREQUENCY, 
         self._start_hook, 
         config.JOURNAL_FREQUENCY
     )
     #minimize the chances of losing started instances
     Event('journal-error').subscribe(self._journal_failure)
     Event('instance-started').subscribe(self.write)
     Event('signal').subscribe(self.write)
     Service.startService(self)
Esempio n. 7
0
 def blocking_journal_write(self):
     if not self._task.running: return #account for lazy task start
     now = int( time.time() )
     snapshot = '%d.pickle' % now
     path = os.path.join(config.JOURNAL_DIR, snapshot)
     outfile = open(path, 'wb')
     c = 0
     for obj in gc.get_objects():
         if isinstance(obj, Entity) and obj.serializable and \
                 obj.__class__.isValid(obj):
             try:
                 data = obj.serialize()
                 outfile.write(data)
                 c += 1
             except:
                 #don't ever reference the ``obj`` in here, it is probably
                 #an invalid Entity and will raise an Exception on access.
                 failure = err('Exception Serializing an Object')
                 Event('journal-error').fire(failure=failure, journal=path)
     outfile.close()
     plural = 's'
     if c == 1: plural = ''
     log('stored %d object%s' % (c,plural))
     old = sorted( map(int, list_snapshots()) )[:-config.JOURNAL_RETENTION]
     for timestamp in old:
         path = os.path.join(config.JOURNAL_DIR, str(timestamp) + SUFFIX)
         os.unlink(path)
Esempio n. 8
0
def remove_hooks(occurrence):
    """remove hook from droned's default server resource"""
    if occurrence.service.SERVICENAME not in (dependant_service, SERVICENAME):
        return
    global service
    service = False
    try:
        resource = get_resource()
        if SERVICENAME in resource.children:
            resource.children.pop(SERVICENAME)
    except: pass
    Event('service-stopped').unsubscribe(remove_hooks)
    if occurrence.service.SERVICENAME == 'drone':
        Event('service-stopped').fire(service=__module__)
    else:
        Event('service-started').unsubscribe(add_hooks)
Esempio n. 9
0
    def __init__(self, service, name, callback, **kwargs):
        """
           
        """
        #get ready for python3
        if not hasattr(callback, '__call__'):
            raise AssertionError("%s is not callable" % (callback.__name__,))

        event_name = str(service) + '-' + str(name)
        self.event = Event(event_name)
        self.name = name
        self.loop = None
        self.service = service

        #borderline laziness on my part
        self.log = AppManager(service).log

        self.condition = kwargs.get('condition', None)
        self.recurring = float(kwargs.get('recurring', 0))
        self.silent = kwargs.get('silent', False)

        assert not (self.recurring and self.condition), \
            "recurring and condition args are mutually exclusive"

        self.func = callback.__name__
        if not self.silent:
            self.event.subscribe(self.announce)
        #send data only if we have it, keeps compatibility with legacy api
        self.event.subscribe(lambda x: (hasattr(x, 'params') and x.params) \
            and callback(x) or callback())

        #our event loop is controlled by the Service
        if self.recurring > 0.0:
            self.loop = LoopingCall(self.event.fire)
            self.occurred() #automatically start re-occuring events
Esempio n. 10
0
 def connectionLost(self, xmlstream):
     log('connection lost')
     self.authenticated = False
     if self.broadcastTask.running:
         self.broadcastTask.stop()
     if self.connected:
         Event('jabber-offline').fire()
     self.xmlstream = None
Esempio n. 11
0
 def construct(state):
     conversation = Conversation(state['buddy'])
     conversation.context['subscriptions'] = set(state['subscriptions'])
     if state.get('authorized'):
         conversation.grantAuthorization(notify=False)
     for name in state['subscriptions']:
         Event(name).subscribe(conversation.notify)
     return conversation
Esempio n. 12
0
def notification(conversation, event, string):
    #hopefully you know how to parse this string
    if Event.exists(event):
        context = {
            'conversation': conversation,
            'message': string,
            'event': event,
        }
        Event(event).fire(**context)
Esempio n. 13
0
    def _pluginSetup(self, plugin):
        """get romeo configuration bound in order to update the instance

           This gets called by the factory below.

           Note: ROMEO configuration always overrides the ApplicationPlugin's
             default constructor!!!!
        """
        plugin.log('applying configuration from romeo')
        tmp = getattr(plugin, 'INSTANCES',
                      1)  #allow constructor to set this up
        plugin.INSTANCES = plugin.configuration.get('INSTANCES', tmp)
        #get the real settings from configuration
        plugin.STARTUP_INFO.update(plugin.configuration.get(
            'STARTUP_INFO', {}))
        plugin.STARTUP_INFO['START_ARGS'] = tuple(
            plugin.STARTUP_INFO['START_ARGS'])
        plugin.SHUTDOWN_INFO.update(
            plugin.configuration.get('SHUTDOWN_INFO', {}))
        plugin.SHUTDOWN_INFO['STOP_ARGS'] = tuple(
            plugin.SHUTDOWN_INFO['STOP_ARGS'])
        #how long to wait before searching for a newly started process
        tmp = getattr(plugin, 'SEARCH_DELAY',
                      5.0)  #allow constructor to set this up
        plugin.SEARCH_DELAY = plugin.configuration.get('SEARCH_DELAY', tmp)
        #how long to wait on a command before timing out!!! Timeout implies failure!
        tmp = getattr(plugin, 'DEFAULT_TIMEOUT',
                      120)  #allow constructor to set this up
        plugin.DEFAULT_TIMEOUT = plugin.configuration.get(
            'DEFAULT_TIMEOUT', tmp)  #seconds
        #how to assimilate an application
        tmp = getattr(plugin, 'ASSIMILATION_PATTERN',
                      None)  #allow constructor to set this up
        plugin.ASSIMILATION_PATTERN = plugin.configuration.get(
            'ASSIMILATION_PATTERN', tmp)
        #prepare the process regular expression
        plugin.PROCESS_REGEX = None
        if plugin.ASSIMILATION_PATTERN:
            plugin.PROCESS_REGEX = re.compile(plugin.ASSIMILATION_PATTERN,
                                              re.I)
        #if you don't like the default behavior of addInstance override it
        for i in range(plugin.INSTANCES):
            try:
                plugin.getInstance(i)
            except AssertionError:
                plugin.addInstance(i)
        tmp = getattr(plugin, 'AUTO_RECOVER',
                      False)  #allow constructor to set this up
        #configure automatic restart after crash
        if plugin.configuration.get('AUTO_RECOVER', tmp):
            Event('instance-crashed').subscribe(plugin.recoverInstance)
        #allow romeo to hint that droned manages the daemonization of this app.
        if plugin.configuration.get('MANAGED', False):
            plugin.startProtoKwargs.update({'daemonize': True})
        plugin.log('plugin is configured and ready to be used')
Esempio n. 14
0
def subscribe(conversation, event):
    subscriptions = set(conversation.context.get('subscriptions', set()))
    if event == 'all':
        events = Event.objects
    else:
        events = [Event(event)]
    for event in events:
        conversation.say("Subscribed to %s events" % event.name)
        subscriptions.add(event.name)
        event.subscribe(conversation.notify)
    conversation.context['subscriptions'] = subscriptions
Esempio n. 15
0
 def assimilate(selfs, appname, appversion, applabel):
     """attempt to manage an unmanaged process"""
     if self.running:
         ai = AppInstance(self.server, AppVersion(App(appname), appversion),
                          applabel)
         if ai.running: return False  #this instance is already running
         ai.updateInfo({'pid': self.process.pid})
         if ai.running and ai.pid == self.process.pid:
             Event('scab-lost').fire(scab=self)
             return True
     return False
Esempio n. 16
0
def unsubscribe(conversation, event):
    subscriptions = set(conversation.context.get('subscriptions', []))
    if event == 'all':
        eventList = Event.objects
    else:
        eventList = [Event(event)]
    for event in eventList:
        conversation.say("Unsubscribed from %s events" % event.name)
        event.unsubscribe(conversation.notify)
        subscriptions.discard(event.name)
    conversation.context['subscriptions'] = sorted(subscriptions)
Esempio n. 17
0
 def newfunc():
     try:
         if obj.running():
             log('Stopping Service')
             func()  #we don't really care about the return
             if obj.running():
                 raise AssertionError("%s is still running" % (name, ))
             Event('service-stopped').fire(service=obj)
             log('Stopped Service')
     except:
         return Failure()
     return True
Esempio n. 18
0
 def signal_emitter(self, signum, frame):
     """trap as many os signals as we can and the send the signal as an event
        !!only call this right before reactor.run
     """
     if signum == signal.SIGTERM:
         #suppress further signals
         signal.signal(signal.SIGTERM, signal.SIG_IGN)
         self.log('Received SIGTERM Shutting Down in 5 seconds')
         self.reactor.callLater(5.0, self.reactor.stop)
     #imported below in this file
     Event('signal').fire(signum=signum,
                          signame=self.SIGNALS[signum],
                          frame=frame)
Esempio n. 19
0
 def _setversion(self, version):
     """sets the self.appversion and self.version"""
     checkVersion = hasattr(self, '_version')  #could be reconstructing
     if checkVersion:
         checkVersion = self._getappversion()
     if IDroneModelAppVersion.providedBy(version):
         self._version = IDroneModelAppVersion(version)
     else:
         self._version = IDroneModelAppVersion(
             AppVersion.makeAppVersion(self.app.name, version))
     if checkVersion:
         data = {
             'instance': self,
             'version': self._version,
             'previous': checkVersion
         }
         if checkVersion < self._version:
             if checkVersion.major < self._version.major:
                 Event('new-major-release').fire(**data)
             else:
                 Event('new-release-version').fire(**data)
             return  #done
         Event('release-change').fire(**data)
Esempio n. 20
0
    def connectionAuthenticated(self, xmlstream):
        log('connection authenticated')
        self.authenticated = True
        if not self.broadcastTask.running:
            self.broadcastTask.start(
                self.SERVICECONFIG.JABBER_BROADCAST_INTERVAL)

        xmlstream.addObserver('/message', self.receivedMessage)
        xmlstream.addObserver('/presence', self.receivedPresence)
        xmlstream.addObserver('/iq', self.receivedIQ)
        xmlstream.addObserver('/error', self.receivedError)
        Event('jabber-online').fire()
        while self.sendQueue:
            self.xmlstream.send(self.sendQueue.pop(0))
Esempio n. 21
0
 def newfunc():
     try:
         if not self.SERVICE_STATE[name]:
             raise AssertionError('%s is disabled' % (name, ))
         if not obj.running():
             log('Starting Service')
             func()  #don't really care about the return
             if not obj.running():
                 raise AssertionError("%s not running" % (name, ))
             Event('service-started').fire(service=obj)
             log('Started Service')
     except:
         return Failure()
     return True
Esempio n. 22
0
 def stopService(self):
     """Stop All AppManager Services"""
     for x in ['allapps', 'applist']:
         if x in drone.builtins:
             del drone.builtins[x]
     Event('instance-started').unsubscribe(self.reset_tracking)
     for manager in AppManager.objects:
         if manager.running:
             mesg = 'Stopping Application Manager'
             logWithContext(type=manager.name, route=SERVICENAME)(mesg)
             manager.stop()
             #plugins are stateless by design
             pluginFactory.delete_plugin(manager.model)
     if self._task.running: self._task.stop()
     Service.stopService(self)
Esempio n. 23
0
    def startService(self):
        """Start All AppManager Services"""
        if self.scanning.called:  #need to pre-populate values
            self.scanning = defer.maybeDeferred(self._first_scan)
        self.first_run = True
        self._task = task.LoopingCall(self.scan_app_instances)

        #plugins will be created and loaded when needed
        for shortname in config.APPLICATIONS.keys():
            manager = None
            try:
                applog = logWithContext(type=shortname, route=SERVICENAME)
                applog('Loading Application Plugin')
                applog('Creating Application Manager')
                manager = AppManager(shortname)
                manager.parentService = self
                #check and see if the model is bound
                if not AppManager(shortname).running:
                    applog('Starting Application Manager')
                    manager.start()
            except:
                failure = Failure()
                #bad plugin, not adaptable
                failures = (InvalidPlugin, TypeError)
                if failure.check(*failures) and manager:
                    log('plugin for %s is invalid' % (manager.name, ))
                    manager.action.__class__.delete(manager.action)
                    try:
                        pluginFactory.delete_plugin(manager.model)
                    except:
                        pass  #silence
                    AppManager.delete(manager)
                    if not config.EXCESSIVE_LOGGING:
                        continue  #avoid extra logging
                try:
                    failure.raiseException()
                except:
                    crashReport('ApplicationLoader', self)
        Service.startService(self)
        Event('instance-started').subscribe(self.reset_tracking)
        #wire allapps action into the server
        drone.builtins.update({
            'allapps': self.allapps_action,
            'applist': self.applist_action,
        })
        #delay scanning by some interval
        config.reactor.callLater(SERVICECONFIG.initial_delay,
                                 self._start_all_tasks)
Esempio n. 24
0
            event.unsubscribe(conversation.notify)


def joinEnvironmentalChatRoom(event):
    """determine if we should join a chatroom"""
    chat = ChatRoom(config.ROMEO_ENV_NAME)
    #make sure the drone can be managed by the room
    username = config.ROMEO_ENV_NAME
    jbserver = jconfig.JABBER_CHAT_SERVICE
    jid = "%(username)s@%(jbserver)s" % locals()
    Team('support').addMember(jid)
    #get the conversation context set to some sane defaults
    conversation = Conversation(jid)
    #grant the room access to the server
    if jconfig.JABBER_TRUST_ROOM:
        conversation.grantAuthorization(notify=False)
    #be vain assume all conversations revolve around ourself
    context = {
        'server': Server(config.HOSTNAME),
        'subject': Server(config.HOSTNAME),
    }
    conversation.context.update(context)
    #finally join the room
    chat.join()


if jconfig and jconfig.JABBER_JOIN_CHATROOM:
    Event('jabber-online').subscribe(joinEnvironmentalChatRoom)
Event('jabber-online').subscribe(notify_online)
Event('jabber-offline').subscribe(remove_conversation_subscriptions)
Esempio n. 25
0
 def _scan(self):
     for pid in listProcesses():
         try:
             AppProcess(Server(config.HOSTNAME), pid)
         except InvalidProcess:
             pass
         except IOError:
             pass  #happens on linux when a pid dies
         except:
             err('process table scanning error')
     #scan for crashed instances
     for app in App.objects:
         if not app.__class__.isValid(app): continue
         for ai in app.localappinstances:
             if not ai.__class__.isValid(ai): continue
             if ai in self.tracking: continue
             if not self.first_run:  #avoid process table races
                 self.tracking.add(ai)
                 config.reactor.callLater(SERVICECONFIG.recovery_period,
                                          self.tracking.discard, ai)
                 if not ai.enabled: continue  #skip disabled
             result = None
             if ai.running and not ai.shouldBeRunning:
                 ai.shouldBeRunning = True
             if ai.running: continue
             manager = AppManager(ai.app.name)
             if not manager.running:
                 continue  #skip managers that are not running
             if not manager.discover:
                 continue  #app manager claims to be ok
             #look for processes that we can assimilate
             d = manager.model.findProcesses()
             wfd = defer.waitForDeferred(d)
             yield wfd
             for (pid, result) in wfd.getResult():
                 d = manager.model.assimilateProcess(result)
                 wfd2 = defer.waitForDeferred(d)
                 yield wfd2
                 ai2 = wfd2.getResult()
                 if ai2 and isinstance(ai2, AppInstance) and ai2 is ai:
                     Event('instance-found').fire(instance=ai)
                     manager.log('Sucessfully assimilated PID %d' % ai2.pid)
             if ai.running: continue  #may have assimilated the app
             if not ai.crashed: continue
             if not ai.enabled:
                 continue  #disabled instances are not actionable
             if self.first_run: continue  #avoid process table races
             Event('instance-crashed').fire(instance=ai)
             #cool off on eventing for a little while
     #keep the process objects up to date
     for process in AppProcess.objects:
         try:
             if not process.localInstall: continue
             if not process.running:
                 AppProcess.delete(process)
         except:
             err('process book keeping error')
     d = defer.Deferred()
     config.reactor.callLater(0.01, d.callback, None)
     wfd = defer.waitForDeferred(d)
     yield wfd
     wfd.getResult()
     self.first_run = False
     yield 'done'
Esempio n. 26
0
    def stopInstance(self, label):
        """Stops an application instance by label

           @param label: (string)

           @fires Event('instance-stopped')

           return defer.Deferred()
        """
        result = {}
        template = '[%(application)s,%(label)s] %(description)s'
        context = {'code': 254}
        thisInst = None
        try:
            thisInst = self.model.getInstance(label)
            thisInst.shouldBeRunning = False
            if not thisInst.running:
                context.update(self.model.statusInstance(label))
                raise DroneCommandFailed(context)
            pid = thisInst.process.pid
            self.log("Trying to shutdown %d gracefully" % (pid, ))

            def failed(result):
                """attempting to be consistant"""
                self.log("Failed to shutdown process gracefully")
                return result

            def success(result):
                """attempting to be consistant"""
                self.log("process %d gracefully shutdown" % (pid, ))
                return result

            d = self._start_stop_common(label, 'stopInstance')
            d.addCallback(success)
            d.addErrback(failed)
            d.addErrback(self._killInstance, thisInst)
            wfd = defer.waitForDeferred(d)
            yield wfd
            #refresh the instance as it can change
            thisInst = self.model.getInstance(label)
            result = wfd.getResult()
            if isinstance(result, dict):
                context.update(result)
            elif isinstance(result, DroneCommandFailed):
                context.update(result.resultContext)
            if not thisInst.running:
                context['code'] = 0
                Event('instance-stopped').fire(instance=thisInst)
                raise AssertionError('ignore me')
            raise DroneCommandFailed(context)
        except AssertionError:
            #update the instance model
            wfd = defer.waitForDeferred(self.statusInstance(label))
            yield wfd
            result = wfd.getResult()
            result['code'] = context['code']
        except:
            failure = Failure()
            if failure.check(DroneCommandFailed):
                context = failure.value.resultContext
                template = '%(description)s'
            else:
                temp = "%s: %s" % (getException(failure),
                                   failure.getErrorMessage())
                context = {'error': failure, 'code': 253, 'description': temp}
            result = self.resultContext(template, thisInst, **context)
        try:
            thisInst = self.model.getInstance(label)
            thisInst.shouldBeRunning = False
        except:
            pass
        yield result
Esempio n. 27
0
 def __del__(self):
     if self.loop.running: self.loop.stop()
     try: Event.delete(self.event)
     except: pass
Esempio n. 28
0
class ApplicationEvent(Entity):
    """The Extents Eventing For AppManagers"""
    implements(IDroneModelApplicationEvent)
    serializable = False
    reactor = property(lambda s: reactor)

    def __del__(self):
        if self.loop.running: self.loop.stop()
        try: Event.delete(self.event)
        except: pass


#TODO document
    def __init__(self, service, name, callback, **kwargs):
        """
           
        """
        #get ready for python3
        if not hasattr(callback, '__call__'):
            raise AssertionError("%s is not callable" % (callback.__name__,))

        event_name = str(service) + '-' + str(name)
        self.event = Event(event_name)
        self.name = name
        self.loop = None
        self.service = service

        #borderline laziness on my part
        self.log = AppManager(service).log

        self.condition = kwargs.get('condition', None)
        self.recurring = float(kwargs.get('recurring', 0))
        self.silent = kwargs.get('silent', False)

        assert not (self.recurring and self.condition), \
            "recurring and condition args are mutually exclusive"

        self.func = callback.__name__
        if not self.silent:
            self.event.subscribe(self.announce)
        #send data only if we have it, keeps compatibility with legacy api
        self.event.subscribe(lambda x: (hasattr(x, 'params') and x.params) \
            and callback(x) or callback())

        #our event loop is controlled by the Service
        if self.recurring > 0.0:
            self.loop = LoopingCall(self.event.fire)
            self.occurred() #automatically start re-occuring events


    def announce(self, *args, **kargs):
        """Anounce the Occurrence of an Event"""
        self.log("%s event occurred calling %s" % (self.name, self.func))
        return True


    def occurred(self):
        """Check for Occurrence or Start Event Loop"""
        if not self.condition and self.loop and not self.loop.running:
            self.loop.start(self.recurring)
        elif self.condition and self.condition():
            self.event.fire()
            return True
        return False
            

#TODO document
    def trigger(self, data=None, delay=0.0):
        """Trigger an event, the return object can be cancelled"""
        kwargs = {}
        if data:
            kwargs['data'] = data
        return self.reactor.callLater(delay, self.event.fire, **kwargs)
Esempio n. 29
0
def start():
    global service
    service = True
    Event('service-started').subscribe(add_hooks)
    Event('service-stopped').subscribe(remove_hooks)
Esempio n. 30
0
class ApplicationEvent(Entity):
    """The Extents Eventing For AppManagers"""
    implements(IDroneModelApplicationEvent)
    serializable = False
    reactor = property(lambda s: config.reactor)

    def __del__(self):
        if self.loop.running: self.loop.stop()
        try:
            Event.delete(self.event)
        except:
            pass

#TODO document

    def __init__(self, service, name, callback, **kwargs):
        """
           
        """
        #get ready for python3
        if not hasattr(callback, '__call__'):
            raise AssertionError("%s is not callable" % (callback.__name__, ))

        event_name = str(service) + '-' + str(name)
        self.event = Event(event_name)
        self.name = name
        self.loop = None
        self.service = service

        #borderline laziness on my part
        self.log = AppManager(service).log

        self.condition = kwargs.get('condition', None)
        self.recurring = float(kwargs.get('recurring', 0))
        self.silent = kwargs.get('silent', False)

        assert not (self.recurring and self.condition), \
            "recurring and condition args are mutually exclusive"

        self.func = callback.__name__
        if not self.silent:
            self.event.subscribe(self.announce)
        #send data only if we have it, keeps compatibility with legacy api
        self.event.subscribe(lambda x: (hasattr(x, 'params') and x.params) \
            and callback(x) or callback())

        #our event loop is controlled by the Service
        if self.recurring > 0.0:
            self.loop = LoopingCall(self.event.fire)
            self.occurred()  #automatically start re-occuring events

    def announce(self, *args, **kargs):
        """Anounce the Occurrence of an Event"""
        self.log("%s event occurred calling %s" % (self.name, self.func))
        return True

    def occurred(self):
        """Check for Occurrence or Start Event Loop"""
        if not self.condition and self.loop and not self.loop.running:
            self.loop.start(self.recurring)
        elif self.condition and self.condition():
            self.event.fire()
            return True
        return False

#TODO document

    def trigger(self, data=None, delay=0.0):
        """Trigger an event, the return object can be cancelled"""
        kwargs = {}
        if data:
            kwargs['data'] = data
        return self.reactor.callLater(delay, self.event.fire, **kwargs)
Esempio n. 31
0
 def __init__(self, *args, **kwargs):
     Event('instance-found').subscribe(self._check_version)
Esempio n. 32
0
    def startInstance(self, label):
        """Starts an application instance by label

           @param label: (string)

           @fires Event('instance-started')

           return defer.Deferred()
        """
        template = '[%(application)s,%(label)s] %(description)s'
        context = {'description': 'Failed to Start', 'code': 254}
        result = {}
        thisInst = None
        try:
            if self.model.getInstance(label).running:
                context.update(self.model.statusInstance(label))
                raise DroneCommandFailed(context)

            d = self._start_stop_common(label, 'startInstance')
            wfd = defer.waitForDeferred(d)
            yield wfd
            result = wfd.getResult()

            d = self.statusInstance(label)
            wfd = defer.waitForDeferred(d)
            yield wfd
            result.update(wfd.getResult())
            #refresh the instance as it can change
            thisInst = self.model.getInstance(label)
            if isinstance(result, dict):
                context.update(result)
            elif isinstance(result, DroneCommandFailed):
                context.update(result.resultContext)
            if thisInst.running:
                Event('instance-started').fire(instance=thisInst)
                context['code'] = 0
                raise AssertionError('ignore')
            raise DroneCommandFailed(context)
        except AssertionError:
            #update the instance model
            wfd = defer.waitForDeferred(self.statusInstance(label))
            yield wfd
            result = wfd.getResult()
        except:
            thisInst = self.model.getInstance(label)
            failure = Failure()
            if failure.check(DroneCommandFailed):
                template = '%(description)s'
                context = failure.value.resultContext
            else:
                #log the error, allowing for debugging
                self.debugReport()
                #be nice and return something to the end user
                temp = "%s: %s" % (getException(failure),
                                   failure.getErrorMessage())
                context = {'error': failure, 'code': 253, 'description': temp}
            result = self.resultContext(template, thisInst, **context)
        try:
            thisInst = self.model.getInstance(label)
            thisInst.shouldBeRunning = True
        except:
            pass
        yield result
Esempio n. 33
0
 def doesNotRunOn(self, server):
     if server in self.shouldRunOn:
         self.shouldRunOn.remove(server)
         Event('app-servers-change').fire(app=self,
                                          server=server,
                                          change='removed')
Esempio n. 34
0
 def __del__(self):
     if self.loop.running: self.loop.stop()
     try:
         Event.delete(self.event)
     except:
         pass