Example #1
0
 def __init__(self, *args):
     self.dispatcher = Dispatcher()
     self._lock = threading.Lock()
     self.roles = []
     self.readonly = []
     self.homepage = '/'
     self.__password = ''
     self.description = ''
     super(User, self).__init__(*args)
Example #2
0
 def __init__(self, *args, **kw):
     super(AlarmManager, self).__init__(*args, **kw)
     self.dispatcher = Dispatcher('Alarm Manager')
     self.cloud = None
     self.max_raised = 5
     self.max_cleared = 5
     self.max_accepted = 5
     self.use_https = False
     self.remote_events = {}
Example #3
0
 def __init__(self, *args):
     self.events = {}
     self.max_raised = ""
     self.max_cleared = ""
     self.max_accepted = ""
     #CSCtf98046:changing default priority to P1
     self.priority = "P1"
     self.description = ""
     self.source = 'broadway'
     self.dispatcher = Dispatcher()
     super(NeoAlarm, self).__init__(*args)
Example #4
0
 def start(self):
     if self._thread is not None:
         raise Exception('Cannot call start on started '
                         'Manager without stopping.')
     if self.dispatcher is None:
         self.dispatcher = Dispatcher(self.url)
     self.triggersub = self.dispatcher.register_for_type(
         self.handle_triggered, TriggerActivated)
     self.clearsub = self.dispatcher.register_for_type(
         self.handle_cleared, TriggerCleared)
     self._startmanager()
     return super(TriggerManager, self).start()
Example #5
0
 def __init__(self, node, urlbase=''):
     self.node = node
     self.__urlbase = urlbase
     self.__state_lock = Lock()
     self.__override = None
     self.__overridden_at = None
     self.__clears_at = None
     self._clearing_value = None
     self.__last_result = None
     self.__cov_registered = False
     self.__dispatcher = Dispatcher()
     self.__dispatcher.__consumers = weakref.WeakKeyDictionary()
     self.source = None
     super(OverridablePoint, self).__init__(node)
Example #6
0
 def __init__(self,*args,**kw):
     super(AlarmManager, self).__init__(*args, **kw)
     self.dispatcher = Dispatcher('Alarm Manager')
     self.cloud = None
     self.max_raised = 5
     self.max_cleared = 5
     self.max_accepted = 5
     self.use_https = False
     self.remote_events = {}
Example #7
0
 def start(self):
     if self._thread is not None:
         raise Exception('Cannot call start on started '
                         'Manager without stopping.')
     if self.dispatcher is None:
         self.dispatcher = Dispatcher(self.url)
     self.triggersub = self.dispatcher.register_for_type(
         self.handle_triggered, TriggerActivated)
     self.clearsub = self.dispatcher.register_for_type(
         self.handle_cleared, TriggerCleared)
     self._startmanager()
     return super(TriggerManager, self).start()
Example #8
0
 def __init__(self, node, urlbase = ''):
     self.node = node
     self.__urlbase = urlbase
     self.__state_lock = Lock()
     self.__override = None
     self.__overridden_at = None
     self.__clears_at = None
     self._clearing_value = None
     self.__last_result = None
     self.__cov_registered = False
     self.__dispatcher = Dispatcher()
     self.__dispatcher.__consumers = weakref.WeakKeyDictionary()
     self.source = None
     super(OverridablePoint, self).__init__(node)
Example #9
0
 def __init__(self, *args):
     super(CloudManager, self).__init__(*args)
     self.dispatcher = Dispatcher('Cloud Manager:Dispatcher')
     register_utility(self, ICloudManager, 'Cloud Manager')
     self.peer = Event.LOCALORIGIN
     self.formation = []
     self._scheduled = None
     self.unreachable = {}
     self.subscription = None
     if((as_node('/services/network/https_server')).is_enabled()):
         self.secure_http = True
     else:
         self.secure_http = False
     self.channel_monitor = ChannelMonitor()
     self.channel_monitor.trigger = CallbackTrigger(self.channel_monitor)
Example #10
0
class OverridablePoint(object):
    adapts(ISettable)
    implements(IOverridable)
    active_overrides = {}
    
    def __new__(klass, node, urlbase = ''):
        overridable = klass.active_overrides.get(node.url)
        if overridable is None:
            overridable = super(OverridablePoint, klass).__new__(klass, node, urlbase)
        # Trickery intended to prevent race-conditions wherein an 
        #   active override is cached after first line of this method.
        return klass.active_overrides.get(node.url, overridable)

    def __init__(self, node, urlbase = ''):
        self.node = node
        self.__urlbase = urlbase
        self.__state_lock = Lock()
        self.__override = None
        self.__overridden_at = None
        self.__clears_at = None
        self._clearing_value = None
        self.__last_result = None
        self.__cov_registered = False
        self.__dispatcher = Dispatcher()
        self.__dispatcher.__consumers = weakref.WeakKeyDictionary()
        self.source = None
        super(OverridablePoint, self).__init__(node)

    def set_clearing_value(self, value):
        self._clearing_value = value

    def get_clearing_value(self):
        return self._clearing_value

    def override(self, value, seconds = None, *clearing_value):
        if len(clearing_value):
            self.set_clearing_value(clearing_value[0])
        self.__state_lock.acquire()
        try:
            self.__override = override = UUID()
            self.__overridden_at = time.time()
            self.__clears_at = None
            self.node.set(value)
            self.active_overrides.setdefault(self.node.url, self)
            if seconds is not None:
                self.__clears_at = self.__overridden_at + seconds
                scheduler.at(self.__clears_at, self.clear_override, (override,))
        finally:
            self.__state_lock.release()
        self.__notify_if_changed()
        return override

    def is_overridden(self):
        self.__state_lock.acquire()
        override = self.__override
        self.__state_lock.release()
        return override is not None

    def is_overridden_by(self, override_id):
        if override_id is None:
            raise ValueError('Provided "override_id" cannot be None.')
        return self.get_override_id() == override_id

    def get_override_id(self):
        self.__state_lock.acquire()
        override_id = self.__override
        self.__state_lock.release()
        return override_id

    def clear_override(self, override_id = None):
        self.__state_lock.acquire()
        try:
            current_id = self.__override
            if current_id is not None and override_id in (None, current_id):
                self.node.set(self.get_clearing_value())
                cleared_override = True
                self.__override = None
                self.__overridden_at = None
                self.__clears_at = None
                del(self.active_overrides[self.node.url])
            else:
                cleared_override = False
        finally:
            self.__state_lock.release()
        self.__notify_if_changed()
        return cleared_override
    
    def get_result(self, skip_cache = 0):
        self.__state_lock.acquire()
        try:
            value = self.node.get()
            result = self.__build_result(value, False)
        finally:
            self.__state_lock.release()
        return result
    
    def __build_result(self, value, blocking = False):
        locked = self.__state_lock.acquire(blocking)
        try:
            override_id = self.__override
            overridden_at = self.__overridden_at
            clears_at = self.__clears_at
            timestamp = time.time()
        finally:
            if blocking or locked:
                self.__state_lock.release()
        overridden = int(override_id is not None)
        result = OverridablePointResult(value, timestamp, overridden, 
                                        override_id, overridden_at, clears_at)
        return result
    
    def event_subscribe(self, consumer, event_type, *args, **kw):
        event_subscribe = getattr(self.node, 'event_subscribe')
        if issubclass(event_type, ChangeOfValueEvent):
            if getattr(self.node, 'has_cov', _CallableConstant(False))():
                self.__state_lock.acquire()
                try:
                    dispatcher = self.__dispatcher
                    handler = consumer.event_handler
                    sid = dispatcher.register_for_type(handler, event_type)
                    dispatcher.__consumers[consumer] = sid
                    if not self.__cov_registered:
                        self.__cov_registered = True
                        try: 
                            event_subscribe(self, event_type, *args, **kw)
                        except: 
                            self.__cov_registered = False
                            raise
                finally:
                    self.__state_lock.release()
        else: event_subscribe(consumer, event_type, *args, **kw)
        result = self.get_result()
        self.__dispatch_cov(self.__last_result, result)
        self.__last_result = result
        
    def event_unsubscribe(self, consumer, event_type, *args, **kw):
        event_unsubscribe = getattr(self.node, 'event_unsubscribe')
        if issubclass(event_type, ChangeOfValueEvent):
            self.__state_lock.acquire()
            try:
                dispatcher = self.__dispatcher
                sid = dispatcher.__consumers.get(consumer)
                if sid is None:
                    print 'Unsubscribe has no matching consumer, ignoring.'
                    return
                else:
                    dispatcher.unregister(sid)
                    del(dispatcher.__consumers[consumer])
                if self.__cov_registered and not len(dispatcher.__consumers):
                    event_unsubscribe(self, event_type, *args, **kw)
                    self.__cov_registered = False
            finally:
                self.__state_lock.release()
        else: event_unsubscribe(consumer, event_type, *args, **kw)
    
    def __event_handler(self, event, *args, **kw):
        result = self.__build_result(event.value)
        return self.__notify_if_changed(result)
    
    def __notify_if_changed(self, result = None):
        if not self.__cov_registered:
            self.__last_result = None
            return
        last_result = self.__last_result
        if result is None:
            result = self.get_result()
        self.__last_result = result
        if not result.equals(last_result):
            self.__dispatch_cov(last_result, result)
            return
            
    def __dispatch_cov(self, last_result, result):
        cov = ChangeOfValueEvent(self, last_result, result, result.timestamp)
        return self.__dispatcher.dispatch(cov)
        
    def __getattr__(self, name):
        if name == 'event_handler' and self.__cov_registered:
            return self.__event_handler
        return getattr(self.node, name)
    
    def __eq__(self, other):
        return self.url == other.url
    
    def __get_url(self):
        return self.__urlbase + self.node.url
    url = property(__get_url)
Example #11
0
class AlarmManager(CompositeNode):
    implements(IAlarmManager)
    security = SecurityInformation.from_default()
    secured_by(security)

    def __init__(self, *args, **kw):
        super(AlarmManager, self).__init__(*args, **kw)
        self.dispatcher = Dispatcher('Alarm Manager')
        self.cloud = None
        self.max_raised = 5
        self.max_cleared = 5
        self.max_accepted = 5
        self.use_https = False
        self.remote_events = {}

    security.protect('add_alarm', 'Configure')

    def add_alarm(self, alarm):
        self.add_child(alarm)

    security.protect('remove_alarm', 'Configure')

    def remove_alarm(self, name):
        self.get_alarm(name).prune()

    def get_alarm(self, name):
        return self.get_child(name)

    def get_alarms(self):
        return self.children_nodes()

    def get_alarm_names(self):
        return self.children_names()

    def get_alarm_dictionary(self):
        return self.children

    def get_remote_events(self):
        return self.remote_events.values()

    def get_local_events(self):
        events = []
        alarms = self.get_alarms()
        eventlists = map(Alarm.get_events, alarms)
        map(events.extend, eventlists)
        return events

    def get_all_events(self):
        return self.get_local_events() + self.get_remote_events()

    def get_event_dictionary(self, order_by='state', source='all'):
        try:
            events = getattr(self, 'get_' + source + '_events')()
        except AttributeError:
            raise ValueError('"%s" invalid value for source.' % source)
        eventdict = {}
        if order_by == 'state':
            for event in events:
                eventdict.setdefault(event.state, []).append(event)
        elif order_by == 'GUID' or order_by == 'guid':
            for event in events:
                eventdict[event.GUID] = event
        else:
            raise ValueError('"%s" invalid value for order_by' % order_by)
        return eventdict

    def get_events_by_state(self, state, source='all'):
        eventdict = self.get_event_dictionary('state', source)
        return eventdict.get(state.upper(), [])

    def handle_event_resend(self, cloudevent):
        self.message('Received Event Resend event %s' % (cloudevent))
        self.send_alarm_events_to_portal(cloudevent.origin)

    def send_alarm_events_to_portal(self, target):
        count = 0
        for alarm in self.get_alarms():
            for event in alarm.get_events():
                self.cloud.send_event_to_portal(event, ['Alarm Manager'],
                                                target)
                count += 1
        self.message('Dispatched %s events because of Event Resend Request' %
                     count)
        return count

    def handle_cloud_event(self, cloudevent):
        event = cloudevent()

    def dispatch(self, event, *args, **kw):
        result = self.dispatcher.timed_dispatch(event, *args, **kw)
        if isinstance(event, StateEvent):
            alarmevent = event.get_alarm_event()
            if alarmevent.is_local():
                self.cloud.handle_local_event(alarmevent, ['Alarm Manager'])
            else:
                guid = alarmevent.GUID
                if not self.remote_events.has_key(guid):
                    self.remote_events[guid] = alarmevent
                if isinstance(event, AlarmEventClosed):
                    del (self.remote_events[guid])
        return result

    def handle_cloud_change(self, event):
        count = 0
        for alarm in self.get_alarms():
            for event in alarm.get_events():
                self.cloud.handle_local_event(event, ['Alarm Manager'])
                count += 1
        self.message('Dispatched %s events because Cloud Change.' % count)
        self.dispatch(event)
        return count

    def register_for_type(self, *args, **kw):
        return self.dispatcher.register_for_type(*args, **kw)

    def configure(self, config):
        set_attribute(self, 'use_https', self.use_https, config, as_boolean)
        set_attribute(self, 'max_raised', 5, config, int)
        set_attribute(self, 'max_cleared', 5, config, int)
        set_attribute(self, 'max_accepted', 5, config, int)
        return super(AlarmManager, self).configure(config)

    def configuration(self):
        config = super(AlarmManager, self).configuration()
        get_attribute(self, 'use_https', config, str)
        get_attribute(self, 'max_raised', config, str)
        get_attribute(self, 'max_cleared', config, str)
        get_attribute(self, 'max_accepted', config, str)
        return config

    def start(self):
        self.message('Alarm Manager starting.')
        server = self.nodespace.as_node('/services/network/http_server')
        if not server.is_enabled() or self.use_https:
            server = self.nodespace.as_node('/services/network/https_server')
        config = {
            'parent': server,
            'enabled': 1,
            'secured': True,
            'debug': self.debug
        }
        syndic_handler_config = config.copy()
        config_handler_config = config.copy()
        cloud_handler_config = config.copy()
        cloud_config_handler_config = config.copy()
        exporter_handler_config = config.copy()
        trigger_handler_config = config.copy()
        syndic_handler_config['name'] = 'Syndication Viewer'
        syndic_handler_config['path'] = '/syndication'
        config_handler_config['name'] = 'Alarm Configurator'
        config_handler_config['path'] = '/alarmconfig'
        cloud_handler_config['name'] = 'Cloud Handler'
        cloud_handler_config['path'] = '/cloud'
        cloud_config_handler_config['name'] = 'Cloud Configurator'
        cloud_config_handler_config['path'] = '/cloudconfig'
        exporter_handler_config['name'] = 'Exporter Configurator'
        exporter_handler_config['path'] = '/exportconfig'
        trigger_handler_config['name'] = 'Trigger Configurator'
        trigger_handler_config['path'] = '/triggerconfig'

        ##
        # Frist create and setup Cloud Manager so events produced by
        #   startup of configurators can be propogated properly.
        startlist = []
        from mpx.service.cloud.manager import CloudManager
        cloud_manager = self.nodespace.create_node(CloudManager)
        cloud_manager.configure({
            'name': 'Cloud Manager',
            'parent': '/services',
            'debug': self.debug
        })
        self.cloud = cloud_manager
        startlist.append(cloud_manager)

        from mpx.service.cloud import request_handler
        cloud_handler_config['manager'] = '/services/Cloud Manager'
        cloud_handler = self.nodespace.create_node(
            request_handler.CloudHandler)
        cloud_handler.configure(cloud_handler_config)
        del request_handler
        startlist.insert(0, cloud_handler)

        from mpx.service.cloud.xhtml.configuration import request_handler
        cloud_config_handler_config['manager'] = '/services/Cloud Manager'
        cloud_config_handler = self.nodespace.create_node(
            request_handler.CloudConfigurator)
        cloud_config_handler.configure(cloud_config_handler_config)
        del request_handler
        startlist.append(cloud_config_handler)

        for cloudservice in startlist:
            cloudservice.start()
        self.message(
            'Alarm Manager configured and started Cloud Manager, Handler, and Configurator.'
        )

        ##
        # Syndication Handler is idempotent and so can be started anytime.
        from mpx.service.alarms2.presentation.syndication.http import request_handler
        syndic_handler = request_handler.SyndicationViewer()
        syndic_handler.configure(syndic_handler_config)
        del request_handler
        syndic_handler.start()
        self.message(
            'Alarm Manager configured and started Syndication Handler.')

        ##
        # Startup Alarm Manager's configurator so that pickled Alarm Events may be
        #   recreated.
        from mpx.service.alarms2.presentation.xhtml.configuration import request_handler
        config_handler = self.nodespace.create_node(
            request_handler.AlarmConfigurator)
        config_handler.configure(config_handler_config)
        del request_handler
        config_handler.start()
        self.message('Alarm Manager created and started Alarm Configurator.')

        ##
        # Now that old Alarm Events have been recreated, configure and
        #   startup Exporters.
        from mpx.service.alarms2.export import exporter
        container = self.nodespace.create_node(exporter.ExporterContainer)
        container.configure({
            'name': 'Alarm Exporters',
            'parent': '/services',
            'debug': self.debug
        })
        export = self.nodespace.create_node(exporter.AlarmExporter)
        export.configure({
            'name': 'Alarm Logger',
            'parent': container,
            'debug': self.debug
        })
        formatter = self.nodespace.create_node(
            exporter.AlarmDictionaryFormatter)
        formatter.configure({
            'name': 'Log Formatter',
            'parent': export,
            'debug': self.debug
        })
        transporter = self.nodespace.create_node(exporter.LoggingTransporter)
        transporter.configure({
            'name': 'Alarm Logger',
            'log': '/services/logger/Alarm Log',
            'parent': export,
            'debug': self.debug
        })
        export.add_source(self, StateEvent)
        container.start()
        self.message('Created and started alarm exporters and logger.')

        from mpx.service.alarms2.export.xhtml.configuration import request_handler
        export_config_handler = self.nodespace.create_node(
            request_handler.ExportersConfigurator)
        export_config_handler.configure(exporter_handler_config)
        del request_handler
        export_config_handler.start()
        self.message(
            'Alarm Manager created and started Exporter Configurator.')

        self.cloud.add_listener(self.handle_cloud_event, 'Alarm Manager')
        self.cloud.add_listener(self.handle_event_resend, 'EventResend')
        from mpx.service.cloud.manager import FormationUpdated
        self.cloud.dispatcher.register_for_type(self.handle_cloud_change,
                                                FormationUpdated)
        self.message(
            'Alarm Manager added itself as listender for Cloud Events.')

        ##
        # With all supporting infrastructure started, start triggers which may
        #   immediately generate alarms.
        from mpx.service.alarms2.trigger import triggermanager
        trigger_manager = self.nodespace.create_node(
            triggermanager.TriggerManager)
        trigger_manager.configure({
            'name': 'Trigger Manager',
            'parent': '/services',
            'debug': self.debug
        })
        del triggermanager
        trigger_manager.start()
        self.message('Alarm Manager created and started Trigger Manager.')

        from mpx.service.alarms2.trigger.xhtml.configuration import request_handler
        trigger_config_handler = self.nodespace.create_node(
            request_handler.TriggersConfigurator)
        trigger_config_handler.configure(trigger_handler_config)
        del request_handler
        self.message('Alarm Manager created and started Trigger Configurator.')
        trigger_config_handler.start()
        try:
            store = as_node("/services/Event Store")
        except KeyError:
            msglog.inform("Alarm Manager creating Event Store.")
            from mpx.service.alarms2 import store
            estore = store.EventStore()
            estore.configure({"name": "Event Store", "parent": "/services"})
            estore.start()
            msglog.inform("Alarm Manager setup and started Event Store.")
        else:
            msglog.inform("Alarm Manager found existing Event Store.")
        super(AlarmManager, self).start()
        self.message('Alarm Manager startup complete.')

    def message(self, message, mtype=msglog.types.INFO):
        if (mtype != msglog.types.DB) or self.debug:
            msglog.log('broadway', mtype, message)
        return
Example #12
0
class CloudManager(CompositeNode):
    implements(ICloudManager)
    security = SecurityInformation.from_default()
    secured_by(security)
    def __init__(self, *args):
        super(CloudManager, self).__init__(*args)
        self.dispatcher = Dispatcher('Cloud Manager:Dispatcher')
        register_utility(self, ICloudManager, 'Cloud Manager')
        self.peer = Event.LOCALORIGIN
        self.formation = []
        self._scheduled = None
        self.unreachable = {}
        self.subscription = None
        if((as_node('/services/network/https_server')).is_enabled()):
            self.secure_http = True
        else:
            self.secure_http = False
        self.channel_monitor = ChannelMonitor()
        self.channel_monitor.trigger = CallbackTrigger(self.channel_monitor)
    def stop(self):
        if self.subscription:
            self.remove_listener(self.subscription)
        if self.channel_monitor.is_running():
            self.channel_monitor.stop_monitor()
        self.subscription = None
        super(CloudManager, self).stop()

    def is_event_valid(self,cloudevent):
        portal = self.nformation.get_portal()
        topic=cloudevent.topics[0]
        if(topic == 'EventResend' ):
            if( (portal != None ) and utils.same_host(cloudevent.origin,portal) ):
                return(True)
        elif(topic == 'Alarm Manager' ):
            #if (self.is_peer_in_formation(cloudevent.origin) == True):
            return(True)
        elif(topic == 'CloudFormation' ):
            return(True)

        return(False)


    def handle_remote_event(self, data):
        cloudevent = IPickles(cPickle.loads(data))()
        self.message('Handling remote event from : %s topic=%s ' %(cloudevent.origin,cloudevent.topics))
        cloudevent.set_data(data)
        if(self.is_event_valid(cloudevent) == False ):
            self.message('Dropping the remote event from : %s topic=%s ' 
                           %(cloudevent.origin,cloudevent.topics),msglog.types.WARN)
            return
            
        self.dispatcher.dispatch(cloudevent, cloudevent.topics)
        if(not ('CloudFormation' in cloudevent.topics) ):
            return
        '''
        Dont propogate an event if we are Portal
        '''
        if((cloudevent.portal != None )and (utils.same_host(self.peer,cloudevent.portal)) ):
            self.message('Not Propagating remote event, since I am getting it as a portal:')
            return
        
        
        self.propogate(cloudevent)

    def send_event_to_portal(self,event,topic,target):
        cloudevent = CloudEvent(
            self, self.peer, [target], self.nformation.get_portal(),topic, event)

        protocol = "https" if self.secure_http else "http"
        notifier = CloudNotifier(self.channel_monitor,target, protocol,'/cloud', self.debug)
        notifier.cloudevent = cloudevent
        if not cloudevent.has_data():
            cloudevent.set_data(cPickle.dumps(IPickles(cloudevent)))
        clouddata = cloudevent.get_data()
        notifier.notify(clouddata, self.handle_send_failure_portal,self.handle_send_success_portal)

    def handle_send_failure_portal(self, notifier):
        cloudevent = notifier.cloudevent
        target_peer = notifier.peer
        self.message('Unable to send alarm events to portal=%s ' % (target_peer),msglog.types.WARN)

    def handle_send_success_portal(self,notifier):
        cloudevent = notifier.cloudevent
        target_peer = notifier.peer
        self.message('Succesfully sent alarm events to portal=%s ' % (target_peer))



    def handle_local_event(self, event, topics = []):
        cloudevent = CloudEvent(
            self, self.peer, self.target_formation, self.nformation.get_portal(),topics, event)
        self.propogate(cloudevent)
    
    def is_peer_in_formation(self,peer,formation=None):
        if not formation:
            formation = self.get_formation()
        peer_ip=utils.get_ip_addr(peer)
        return any(utils.same_host(peer_ip, ip) for ip in formation)
    
    def is_host_the_portal(self,host):
        portal = self.nformation.get_portal()
        if not portal:
            return False
        return utils.same_host(portal, host)
    
    def is_host_in_formation(self, host):
        if self.is_host_the_portal(host):
            return True
        if self.is_peer_in_formation(host):
            return True
        return False

    def handle_formation_update(self, cloudevent):
        '''
        Don't take any action like updating Cloud formation or Portal etc, 
        if you have got this event as a portal. The alarms are shown in the event manager
        by a different mechanism. 
        '''
        if((cloudevent.portal != None ) and (utils.same_host(self.peer,cloudevent.portal))):
            self.message('Received the event as a Portal, so not going to take any action %s' % str(cloudevent))
            self.message('handle_formation_update doing nothing, no change.')
            return
        
        formation = cloudevent()
        if (self.is_peer_in_formation(self.peer,formation) == False):
            formation = [self.peer]
            self.message('Setting Cloud Formation to self.peer; no longer in Cloud.',msglog.types.INFO)
        
        self._setup_formation(formation,cloudevent.portal)

    
    def _setup_formation(self, formation,portal):
        scheduled, self._scheduled = self._scheduled, None
        if scheduled is not None:
            try: scheduled.cancel()
            except: pass
            else: self.message('Canceled pending dispatch of formation update.')
        self.nformation.set_portal(portal)
        self.nformation.set_formation(formation)
        self.target_formation = self.nformation.compute_targets()
        self.message('Resetting unreachables during Cloud setup.')
        self.reset_unreachables()
        (dispatch,delay)=self.nformation.compute_dispatch_info()
        if (dispatch):
            self._scheduled = scheduler.after(delay, self.dispatcher.dispatch, (FormationUpdated(self),))
            self.message('Scheduled dispatch in %s seconds.' % delay)
        else: self.message('Formation of one peer, no Updated event generated.')
        
        # Save the PDO, if the formation or portal has changed
        if((self._pdo.formation != formation) or (self._pdo.portal != portal) or (self._pdo.peer != self.peer)):
            self.message('New formation/portal found , hence pickling. New Formation is :%s portal is %s' %(str(formation),portal))
            self._pdo.formation=formation[:]
            self._pdo.portal=portal
            self._pdo.peer=self.peer
            tstart = time.time()
            self._pdo.save()
            tend = time.time()
            self.message('New formation pickled and saved in %s seconds.' % (tend - tstart))
        else:
            self.message('Formation/Portal has not changed. Not pickling it. ' )

    
    def update_formation(self, new_formation,portal):
        (no_of_excluded_peers,excludes)=self.nformation.compute_excludes(new_formation)
        if no_of_excluded_peers:
            self.message( 'Notifying removed participants: %s' % (excludes,))
            excludedevent = CloudEvent(self, self.peer, excludes,self.nformation.get_portal(),['CloudFormation'], new_formation)
            self.propogate(excludedevent)
        else: 
            self.message( 'All current Cloud member in new Cloud Formation.')
        self._setup_formation(new_formation,portal)
        self.handle_local_event(new_formation, ['CloudFormation'])

    def handle_propogation_failure(self, notifier):
        cloudevent = notifier.cloudevent
        target_peer = notifier.peer
        # TODO: generate comm failure error to propogate as well.
        # Progpogate event to Cloud Managers target_peer would have notified.
        
        '''
        The target_peer can be portal or a peer.
        If it is a portal then we will not put it in unreachables and also 
        we do not propogate the event.
        Log if we are not connecting to the portal 
        '''
        portal=self.nformation.get_portal()
        if((portal != None ) and (utils.same_host(target_peer,portal))):
            msg='Portal %s is not reachable .' % portal
            self.message(msg)
            return
            
        
        scheduled = self.unreachable.get(target_peer)
        if scheduled is not None:
            scheduled.cancel()
            self.message('Host %s already listed unreachable, reset scheduled retry.' % target_peer)
        self.unreachable[target_peer] = scheduler.after(5 * 60, self._remove_from_unreachable, (target_peer,))
        self.message('Host %s added to list of unreachable peers.' % target_peer)
        self.propogate(cloudevent, target_peer)

    def _remove_from_unreachable(self, peer):
        if self.unreachable.has_key(peer):
            del(self.unreachable[peer])
            self.message('Removed "%s" from unreachable to retry.' % peer)
        else: self.message('Host "%s" not in unreachable, ignoring remove.' % peer)

    def reset_unreachables(self):
        message = 'Resetting unreachables:\n'
        unreachables = self.unreachable.items()
        self.unreachable.clear()
        for peer, entry in unreachables:
            entry.cancel()
            message += '\t- removed "%s" from unreachables;\n' % peer
        message += '\t%s peers cleared from unreachables.' % len(unreachables)
        self.message(message)
        return len(unreachables)

    def add_listener(self, callback, topic):
        return self.dispatcher.register_for_topic(callback, topic)

    def remove_listener(self, guid):
        return self.dispatcher.unregister(guid)

    def propogate(self, cloudevent, from_peer = None):
        '''
        No Changes - Just make sure ...
        '''
        if not isinstance(cloudevent, CloudEvent):
            raise TypeError('Argument must be instance of CloudEvent')
        if from_peer is None: from_peer = self.peer
        self.message('Propogating as %s:\n\t%s...' % (from_peer, str(cloudevent)))
        target_formation = cloudevent.targets

        notifiers = []
        targets = self.nformation.get_targets(target_formation, from_peer)
        for target in targets:
            if not target.strip():
                self.message('Not notifying "%s" because not valid, adding its targets.' % target)
                targets.extend(self.nformation.get_targets(target_formation, target))
            elif not self.unreachable.has_key(target):
                protocol = "https" if self.secure_http else "http"
                notifier = CloudNotifier(self.channel_monitor, target, 
                                         protocol, '/cloud', self.debug)
                notifier.cloudevent = cloudevent
                notifiers.append(notifier)
            else:
                self.message('Host "%s" unreachable, adding its targets.' % target)
                targets.extend(self.nformation.get_targets(target_formation, target))
        if not cloudevent.has_data():
            cloudevent.set_data(cPickle.dumps(IPickles(cloudevent)))
        clouddata = cloudevent.get_data()
        notified = []
        for notifier in notifiers:
            notifier.notify(clouddata, self.handle_propogation_failure)
            notified.append(notifier.peer)
        if(len(notified) > 0 ):
            self.message('Propogate notified: %s' % (notified,))
        return notified

    

    def message(self, message, mtype = msglog.types.DB):
        if mtype != msglog.types.DB or self.debug:
            message = 'CloudManager(%s) - %s' % (self.peer, message)
            msglog.log('broadway', mtype, message)

    security.protect('add_peer', 'Configure')
    def add_peer(self,peer):
        formation=self.nformation.get_formation()
        formation.append(peer)
        portal=self.nformation.get_portal()
        self.update_formation(formation,portal)
        return

    def get_formation(self):
        formation=self.nformation.get_formation()
        return(formation)
    
    def get_portal(self):
        portal=self.nformation.get_portal()
        return(portal)

    security.protect('set_portal', 'Configure')
    def set_portal(self,portal):
        formation=self.nformation.get_formation()
        self.update_formation(formation,portal)

    security.protect('remove_peer', 'Configure')
    def remove_peer(self,peer):
        formation = self.nformation.get_formation()
        formation.remove(peer)
        portal=self.nformation.get_portal()
        self.update_formation(formation,portal)
    
    def start(self):
        # Bad self IP Address 
        if(self.peer == '127.0.0.1' ):
            msg='Cloud facility will not function properly because of local IP address being 127.0.0.1'
            self.message(msg,msglog.types.WARN)
            return 
        if not self.channel_monitor.is_running():
            self.channel_monitor.start_monitor()
        self._pdo=PersistentDataObject(self)
        self.message('The Cloud Manager Persistent Object is in the file :%s' %str(self._pdo.filename()),msglog.types.INFO)
        migration=False
        if(os.path.exists(self._pdo.filename())):
            # Already Migrated
            self._pdo.formation=[self.peer]
            self._pdo.portal=None
            self._pdo.peer=self.peer
            self._pdo.load()
        else:
            # We save a 'default' formation and expect the Cloud Configurator to 
            # update the _pdo.formation via update_information API.
            # The _setup_formation gets called internally from update_information
            self._pdo.portal=None
            self._pdo.formation=[self.peer]
            self._pdo.peer=self.peer
            self._pdo.save()
            self._pdo.load()
            migration=True
        
        #Bad formation/peer in the PDO
        if( not self._pdo.peer in self._pdo.formation ):
            #Bad formation/peer
            self.message('The Cloud Manager PDO in the file :%s is corrupted. Defaulting to safe configuration' %str(self._pdo.filename()),msglog.types.WARN)
            self._pdo.portal=None
            self._pdo.formation=[self.peer]
            self._pdo.peer=self.peer
            self._pdo.save()
            self._pdo.load()
        
        self.message('Hosts are :%s portal=%s self=%s' %(str(self._pdo.formation),self._pdo.portal,self._pdo.peer),msglog.types.INFO)
        self.nformation=NFormation(self._pdo.formation,self.peer)
        self.nformation.set_portal(self._pdo.portal)
        
        # IP Address Change Case
        if(not utils.same_host(self.peer,self._pdo.peer)):
            self.message('Self address change detected old=%s new=%s. Fixing the Cloud Formation accordingly' %(str(self._pdo.peer),self.peer),msglog.types.INFO)
            formation = self.nformation.get_formation()
            norm_form=self.nformation.normalize_formation(formation)
            # IP Address Swap
            self_index=norm_form.index(self._pdo.peer)
            formation.pop(self_index)
            formation.insert(0,self.peer)
            self.nformation.set_formation(formation)
               
        '''
        In the Case of Migration, the update_formation() API is called
        by the Cloud Configurator. In the already migrated case, we call the
        update_formation() with the PDO formation and Portal
        '''
        
        self.target_formation = self.nformation.compute_targets()
        
        if(migration == False):
            self.update_formation(self.nformation.get_formation(), self.nformation.get_portal())
        
        if self.subscription is None:
            self.subscription = self.add_listener(
                self.handle_formation_update, 'CloudFormation')

        # Send Cloud Event to all the Hosts for re-sending the alarm events 
        # over to the Portal again - if we are nbmm
        if(self.is_host_nbmm()):
            scheduler.after(10, self.request_for_resending_alarm_events)

        super(CloudManager, self).start()

    def is_host_nbmm(self):
        devices=as_node('/interfaces').children_names()
        if('relay1' in devices ):
            return(False)
        else:
            return(True)

    def get_hosts_list(self):
        hosts_list=[]
        all_hosts=as_node('/services/Host Manager').children_nodes()
        for h in all_hosts:
            hosts_list.append(h.host)
        return(hosts_list)

    def request_for_resending_alarm_events(self):
        hosts_list=self.get_hosts_list()
        for host in hosts_list:
            cloudevent = CloudEvent(self, self.peer, [host],None,['EventResend'],[host])
            cloudevent.set_data(cPickle.dumps(IPickles(cloudevent)))
            self.send_req_for_alarm_events(host,cloudevent)

    def handle_send_failure(self, notifier):
        cloudevent = notifier.cloudevent
        target_peer = notifier.peer
        self.message('Unable to notify %s to send alarm events again ' % (target_peer),msglog.types.WARN)

    def handle_send_success(self,notifier):
        cloudevent = notifier.cloudevent
        target_peer = notifier.peer
        self.message('succesfully notified %s to send alarm events again ' % (target_peer))

    def send_req_for_alarm_events(self,target,cloudevent):
        from_peer=self.peer
        protocol = "https" if self.secure_http else "http"
        notifier = CloudNotifier(self.channel_monitor,target, protocol,'/cloud', self.debug)
        notifier.cloudevent = cloudevent
        clouddata = cloudevent.get_data()
        notifier.notify(clouddata, self.handle_send_failure,self.handle_send_success)
Example #13
0
class OverridablePoint(object):
    adapts(ISettable)
    implements(IOverridable)
    active_overrides = {}

    def __new__(klass, node, urlbase=''):
        overridable = klass.active_overrides.get(node.url)
        if overridable is None:
            overridable = super(OverridablePoint,
                                klass).__new__(klass, node, urlbase)
        # Trickery intended to prevent race-conditions wherein an
        #   active override is cached after first line of this method.
        return klass.active_overrides.get(node.url, overridable)

    def __init__(self, node, urlbase=''):
        self.node = node
        self.__urlbase = urlbase
        self.__state_lock = Lock()
        self.__override = None
        self.__overridden_at = None
        self.__clears_at = None
        self._clearing_value = None
        self.__last_result = None
        self.__cov_registered = False
        self.__dispatcher = Dispatcher()
        self.__dispatcher.__consumers = weakref.WeakKeyDictionary()
        self.source = None
        super(OverridablePoint, self).__init__(node)

    def set_clearing_value(self, value):
        self._clearing_value = value

    def get_clearing_value(self):
        return self._clearing_value

    def override(self, value, seconds=None, *clearing_value):
        if len(clearing_value):
            self.set_clearing_value(clearing_value[0])
        self.__state_lock.acquire()
        try:
            self.__override = override = UUID()
            self.__overridden_at = time.time()
            self.__clears_at = None
            self.node.set(value)
            self.active_overrides.setdefault(self.node.url, self)
            if seconds is not None:
                self.__clears_at = self.__overridden_at + seconds
                scheduler.at(self.__clears_at, self.clear_override,
                             (override, ))
        finally:
            self.__state_lock.release()
        self.__notify_if_changed()
        return override

    def is_overridden(self):
        self.__state_lock.acquire()
        override = self.__override
        self.__state_lock.release()
        return override is not None

    def is_overridden_by(self, override_id):
        if override_id is None:
            raise ValueError('Provided "override_id" cannot be None.')
        return self.get_override_id() == override_id

    def get_override_id(self):
        self.__state_lock.acquire()
        override_id = self.__override
        self.__state_lock.release()
        return override_id

    def clear_override(self, override_id=None):
        self.__state_lock.acquire()
        try:
            current_id = self.__override
            if current_id is not None and override_id in (None, current_id):
                self.node.set(self.get_clearing_value())
                cleared_override = True
                self.__override = None
                self.__overridden_at = None
                self.__clears_at = None
                del (self.active_overrides[self.node.url])
            else:
                cleared_override = False
        finally:
            self.__state_lock.release()
        self.__notify_if_changed()
        return cleared_override

    def get_result(self, skip_cache=0):
        self.__state_lock.acquire()
        try:
            value = self.node.get()
            result = self.__build_result(value, False)
        finally:
            self.__state_lock.release()
        return result

    def __build_result(self, value, blocking=False):
        locked = self.__state_lock.acquire(blocking)
        try:
            override_id = self.__override
            overridden_at = self.__overridden_at
            clears_at = self.__clears_at
            timestamp = time.time()
        finally:
            if blocking or locked:
                self.__state_lock.release()
        overridden = int(override_id is not None)
        result = OverridablePointResult(value, timestamp, overridden,
                                        override_id, overridden_at, clears_at)
        return result

    def event_subscribe(self, consumer, event_type, *args, **kw):
        event_subscribe = getattr(self.node, 'event_subscribe')
        if issubclass(event_type, ChangeOfValueEvent):
            if getattr(self.node, 'has_cov', _CallableConstant(False))():
                self.__state_lock.acquire()
                try:
                    dispatcher = self.__dispatcher
                    handler = consumer.event_handler
                    sid = dispatcher.register_for_type(handler, event_type)
                    dispatcher.__consumers[consumer] = sid
                    if not self.__cov_registered:
                        self.__cov_registered = True
                        try:
                            event_subscribe(self, event_type, *args, **kw)
                        except:
                            self.__cov_registered = False
                            raise
                finally:
                    self.__state_lock.release()
        else:
            event_subscribe(consumer, event_type, *args, **kw)
        result = self.get_result()
        self.__dispatch_cov(self.__last_result, result)
        self.__last_result = result

    def event_unsubscribe(self, consumer, event_type, *args, **kw):
        event_unsubscribe = getattr(self.node, 'event_unsubscribe')
        if issubclass(event_type, ChangeOfValueEvent):
            self.__state_lock.acquire()
            try:
                dispatcher = self.__dispatcher
                sid = dispatcher.__consumers.get(consumer)
                if sid is None:
                    print 'Unsubscribe has no matching consumer, ignoring.'
                    return
                else:
                    dispatcher.unregister(sid)
                    del (dispatcher.__consumers[consumer])
                if self.__cov_registered and not len(dispatcher.__consumers):
                    event_unsubscribe(self, event_type, *args, **kw)
                    self.__cov_registered = False
            finally:
                self.__state_lock.release()
        else:
            event_unsubscribe(consumer, event_type, *args, **kw)

    def __event_handler(self, event, *args, **kw):
        result = self.__build_result(event.value)
        return self.__notify_if_changed(result)

    def __notify_if_changed(self, result=None):
        if not self.__cov_registered:
            self.__last_result = None
            return
        last_result = self.__last_result
        if result is None:
            result = self.get_result()
        self.__last_result = result
        if not result.equals(last_result):
            self.__dispatch_cov(last_result, result)
            return

    def __dispatch_cov(self, last_result, result):
        cov = ChangeOfValueEvent(self, last_result, result, result.timestamp)
        return self.__dispatcher.dispatch(cov)

    def __getattr__(self, name):
        if name == 'event_handler' and self.__cov_registered:
            return self.__event_handler
        return getattr(self.node, name)

    def __eq__(self, other):
        return self.url == other.url

    def __get_url(self):
        return self.__urlbase + self.node.url

    url = property(__get_url)
Example #14
0
class AlarmManager(CompositeNode):
    implements(IAlarmManager)
    security = SecurityInformation.from_default()
    secured_by(security)

    def __init__(self,*args,**kw):
        super(AlarmManager, self).__init__(*args, **kw)
        self.dispatcher = Dispatcher('Alarm Manager')
        self.cloud = None
        self.max_raised = 5
        self.max_cleared = 5
        self.max_accepted = 5
        self.use_https = False
        self.remote_events = {}
    security.protect('add_alarm', 'Configure')
    def add_alarm(self, alarm):
        self.add_child(alarm)
    security.protect('remove_alarm', 'Configure')
    def remove_alarm(self, name):
        self.get_alarm(name).prune()
    def get_alarm(self, name):
        return self.get_child(name)
    def get_alarms(self):
        return self.children_nodes()
    def get_alarm_names(self):
        return self.children_names()
    def get_alarm_dictionary(self):
        return self.children
    def get_remote_events(self):
        return self.remote_events.values()
    def get_local_events(self):
        events = []
        alarms = self.get_alarms()
        eventlists = map(Alarm.get_events, alarms)
        map(events.extend, eventlists)
        return events
    def get_all_events(self):
        return self.get_local_events() + self.get_remote_events()
    def get_event_dictionary(self, order_by = 'state', source = 'all'):
        try: events = getattr(self, 'get_' + source + '_events')()
        except AttributeError:
            raise ValueError('"%s" invalid value for source.' % source)
        eventdict = {}
        if order_by == 'state':
            for event in events:
                eventdict.setdefault(event.state, []).append(event)
        elif order_by == 'GUID' or order_by == 'guid':
            for event in events:
                eventdict[event.GUID] = event
        else:
            raise ValueError('"%s" invalid value for order_by' % order_by)
        return eventdict
    def get_events_by_state(self, state, source = 'all'):
        eventdict = self.get_event_dictionary('state', source)
        return eventdict.get(state.upper(), [])
    def handle_event_resend(self, cloudevent):
        self.message('Received Event Resend event %s' %(cloudevent))
        self.send_alarm_events_to_portal(cloudevent.origin)

    def send_alarm_events_to_portal(self,target):
        count = 0
        for alarm in self.get_alarms():
            for event in alarm.get_events():
                self.cloud.send_event_to_portal(event,['Alarm Manager'],target)
                count += 1
        self.message( 'Dispatched %s events because of Event Resend Request' % count)
        return count

    def handle_cloud_event(self, cloudevent):
        event = cloudevent()
    def dispatch(self, event, *args, **kw):
        result = self.dispatcher.timed_dispatch(event, *args, **kw)
        if isinstance(event, StateEvent):
            alarmevent = event.get_alarm_event()
            if alarmevent.is_local():
                self.cloud.handle_local_event(alarmevent, ['Alarm Manager'])
            else:
                guid = alarmevent.GUID
                if not self.remote_events.has_key(guid):
                    self.remote_events[guid] = alarmevent
                if isinstance(event, AlarmEventClosed):
                    del(self.remote_events[guid])
        return result
    def handle_cloud_change(self, event):
        count = 0
        for alarm in self.get_alarms():
            for event in alarm.get_events():
                self.cloud.handle_local_event(event, ['Alarm Manager'])
                count += 1
        self.message( 'Dispatched %s events because Cloud Change.' % count)
        self.dispatch(event)
        return count
    def register_for_type(self, *args, **kw):
        return self.dispatcher.register_for_type(*args, **kw)
    def configure(self, config):
        set_attribute(self, 'use_https', self.use_https, config, as_boolean)
        set_attribute(self, 'max_raised', 5, config, int)
        set_attribute(self, 'max_cleared', 5, config, int)
        set_attribute(self, 'max_accepted', 5, config, int)        
        return super(AlarmManager, self).configure(config)
    def configuration(self):
        config = super(AlarmManager, self).configuration()
        get_attribute(self, 'use_https', config, str)
        get_attribute(self, 'max_raised', config, str)
        get_attribute(self, 'max_cleared', config, str)
        get_attribute(self, 'max_accepted', config, str)
        return config
    def start(self):
        self.message('Alarm Manager starting.')
        server = self.nodespace.as_node('/services/network/http_server')
        if not server.is_enabled() or self.use_https:
            server = self.nodespace.as_node('/services/network/https_server')
        config = {'parent': server, 'enabled': 1,
                  'secured': True, 'debug': self.debug}
        syndic_handler_config = config.copy()
        config_handler_config = config.copy()
        cloud_handler_config = config.copy()
        cloud_config_handler_config = config.copy()
        exporter_handler_config = config.copy()
        trigger_handler_config = config.copy()
        syndic_handler_config['name'] = 'Syndication Viewer'
        syndic_handler_config['path'] = '/syndication'
        config_handler_config['name'] = 'Alarm Configurator'
        config_handler_config['path'] = '/alarmconfig'
        cloud_handler_config['name'] = 'Cloud Handler'
        cloud_handler_config['path'] = '/cloud'
        cloud_config_handler_config['name'] = 'Cloud Configurator'
        cloud_config_handler_config['path'] = '/cloudconfig'
        exporter_handler_config['name'] = 'Exporter Configurator'
        exporter_handler_config['path'] = '/exportconfig'
        trigger_handler_config['name'] = 'Trigger Configurator'
        trigger_handler_config['path'] = '/triggerconfig'

        ##
        # Frist create and setup Cloud Manager so events produced by
        #   startup of configurators can be propogated properly.
        startlist = []
        from mpx.service.cloud.manager import CloudManager
        cloud_manager = self.nodespace.create_node(CloudManager)
        cloud_manager.configure({'name': 'Cloud Manager',
                                 'parent': '/services',
                                 'debug': self.debug})
        self.cloud = cloud_manager
        startlist.append(cloud_manager)

        from mpx.service.cloud import request_handler
        cloud_handler_config['manager'] = '/services/Cloud Manager'
        cloud_handler = self.nodespace.create_node(request_handler.CloudHandler)
        cloud_handler.configure(cloud_handler_config)
        del request_handler
        startlist.insert(0, cloud_handler)

        from mpx.service.cloud.xhtml.configuration import request_handler
        cloud_config_handler_config['manager'] = '/services/Cloud Manager'
        cloud_config_handler = self.nodespace.create_node(request_handler.CloudConfigurator)
        cloud_config_handler.configure(cloud_config_handler_config)
        del request_handler
        startlist.append(cloud_config_handler)

        for cloudservice in startlist:
            cloudservice.start()
        self.message('Alarm Manager configured and started Cloud Manager, Handler, and Configurator.')

        ##
        # Syndication Handler is idempotent and so can be started anytime.
        from mpx.service.alarms2.presentation.syndication.http import request_handler
        syndic_handler = request_handler.SyndicationViewer()
        syndic_handler.configure(syndic_handler_config)
        del request_handler
        syndic_handler.start()
        self.message('Alarm Manager configured and started Syndication Handler.')

        ##
        # Startup Alarm Manager's configurator so that pickled Alarm Events may be
        #   recreated.
        from mpx.service.alarms2.presentation.xhtml.configuration import request_handler
        config_handler = self.nodespace.create_node(request_handler.AlarmConfigurator)
        config_handler.configure(config_handler_config)
        del request_handler
        config_handler.start()
        self.message('Alarm Manager created and started Alarm Configurator.')

        ##
        # Now that old Alarm Events have been recreated, configure and
        #   startup Exporters.
        from mpx.service.alarms2.export import exporter
        container = self.nodespace.create_node(exporter.ExporterContainer)
        container.configure({'name': 'Alarm Exporters',
                             'parent': '/services',
                             'debug': self.debug})
        export = self.nodespace.create_node(exporter.AlarmExporter)
        export.configure({'name': 'Alarm Logger',
                          'parent': container,
                          'debug': self.debug})
        formatter = self.nodespace.create_node(exporter.AlarmDictionaryFormatter)
        formatter.configure({'name': 'Log Formatter',
                             'parent': export,
                             'debug': self.debug})
        transporter = self.nodespace.create_node(exporter.LoggingTransporter)
        transporter.configure({'name': 'Alarm Logger',
                               'log': '/services/logger/Alarm Log',
                               'parent': export,
                               'debug': self.debug})
        export.add_source(self, StateEvent)
        container.start()
        self.message('Created and started alarm exporters and logger.')

        from mpx.service.alarms2.export.xhtml.configuration import request_handler
        export_config_handler = self.nodespace.create_node(request_handler.ExportersConfigurator)
        export_config_handler.configure(exporter_handler_config)
        del request_handler
        export_config_handler.start()
        self.message('Alarm Manager created and started Exporter Configurator.')


        self.cloud.add_listener(self.handle_cloud_event, 'Alarm Manager')
        self.cloud.add_listener(self.handle_event_resend, 'EventResend')
        from mpx.service.cloud.manager import FormationUpdated
        self.cloud.dispatcher.register_for_type(
            self.handle_cloud_change, FormationUpdated)
        self.message('Alarm Manager added itself as listender for Cloud Events.')


        ##
        # With all supporting infrastructure started, start triggers which may
        #   immediately generate alarms.
        from mpx.service.alarms2.trigger import triggermanager
        trigger_manager = self.nodespace.create_node(triggermanager.TriggerManager)
        trigger_manager.configure({'name': 'Trigger Manager',
                                   'parent': '/services',
                                   'debug': self.debug})
        del triggermanager
        trigger_manager.start()
        self.message('Alarm Manager created and started Trigger Manager.')

        from mpx.service.alarms2.trigger.xhtml.configuration import request_handler
        trigger_config_handler = self.nodespace.create_node(request_handler.TriggersConfigurator)
        trigger_config_handler.configure(trigger_handler_config)
        del request_handler
        self.message('Alarm Manager created and started Trigger Configurator.')
        trigger_config_handler.start()
        try:
            store = as_node("/services/Event Store")
        except KeyError:
            msglog.inform("Alarm Manager creating Event Store.")
            from mpx.service.alarms2 import store
            estore = store.EventStore()
            estore.configure({"name": "Event Store", "parent": "/services"})
            estore.start()
            msglog.inform("Alarm Manager setup and started Event Store.")
        else:
            msglog.inform("Alarm Manager found existing Event Store.")
        super(AlarmManager, self).start()
        self.message('Alarm Manager startup complete.')

    def message(self, message, mtype = msglog.types.INFO):
        if (mtype != msglog.types.DB) or self.debug:
            msglog.log('broadway', mtype, message)
        return
Example #15
0
class User(ConfigurableNode):
    implements(IUser)
    security = SecurityInformation.from_default()
    secured_by(security)
    #security.protect('roles', 'Manage Users')
    security.make_private('readonly')

    def __init__(self, *args):
        self.dispatcher = Dispatcher()
        self._lock = threading.Lock()
        self.roles = []
        self.readonly = []
        self.homepage = '/'
        self.__password = ''
        self.description = ''
        super(User, self).__init__(*args)

    #security.protect('password', 'Manage Users')
    def __get_password(self):
        return self.__password

    def __set_password(self, password):
        previous = self.password
        self.__password = password
        if previous != self.password and self.parent is not None:
            event = UserPasswordModified(self, password, previous)
            self.dispatcher.dispatch(event)
        return

    password = property(__get_password, __set_password)

    security.protect('configure', 'View')

    def configure(self, config):
        for attrname in self.readonly:
            current = getattr(self, attrname, None)
            incoming = config.get(attrname)
            if None not in (current, incoming) and (current != incoming):
                message = 'Attribute "%s" is readonly for User "%s".  '
                message += 'Overriding new value %s with current value %s.'
                message = message % (attrname, self.name, incoming, current)
                msglog.log('broadway', msglog.types.WARN, message)
                config[attrname] = current
        self.description = config.get('description', self.description)
        self.homepage = config.get('homepage', self.homepage)
        # Ignoring password if all astericks.
        password = config.get('password', "")
        if config.has_key('old_password') and config.get('old_password') == '':
            raise Exception("Invalid Old Password")
        old_password = config.get('old_password', None)
        if password and (password != len(password) * '*'):
            system_users = PasswdFile()
            system_users.load()
            if old_password and config.get('name', '') in system_users:
                system_shadow = ShadowFile()
                system_shadow.load()
                shadowentry = system_shadow[config.get('name')]
                if not shadowentry.password_matches_crypt(old_password):
                    raise Exception("Invalid Old Password")
            self.__set_password(password)
            self.password = password
        super(User, self).configure(config)
        if config.has_key('roles'):
            self.set_roles(list(config.get('roles', self.roles)))

    def configuration(self):
        config = super(User, self).configuration()
        config['description'] = self.description
        config['homepage'] = self.homepage
        config['password'] = "******"
        config['roles'] = self.get_roles()
        return config

    def start(self):
        super(User, self).start()
        self._synchronize()

    def is_removable(self):
        return not len(self.readonly)

    def is_configurable(self):
        return True

    security.protect('prune', 'Manage Users')

    def prune(self):
        if not self.is_removable():
            error = '%s "%s" is not removable.'
            raise TypeError(error % (type(self).__name__, self.name))
        return super(User, self).prune()

    def _synchronize(self):
        self._lock.acquire()
        try:
            roles = self.roles[:]
            for role in roles:
                if not self.parent.role_manager.has_role(role):
                    message = 'User "%s" ' % self.url
                    message += 'removing role "%s".  ' % role
                    message += 'It does not exist.'
                    msglog.log('broadway', msglog.types.WARN, message)
                    self.roles.remove(role)
        finally:
            self._lock.release()

    security.protect('get_roles', 'View')

    def get_roles(self):
        return self.roles[:]

    security.protect('set_roles', 'Manage Users')

    def set_roles(self, *roles):
        # Allow roles to be list or tuple, or many params.
        if len(roles) == 1 and isinstance(roles[0], (list, tuple)):
            roles = roles[0][:]
        for role in roles:
            if not self.parent.parent.role_manager.has_role(role):
                raise ValueError('Role "%s" does not exist.' % role)
        rolenames = []
        for role in roles:
            if isinstance(role, str):
                rolenames.append(role)
            else:
                rolenames.append(role.name)

        if self.parent.anonymous is not self:
            authenticated = self.parent.role_manager.authenticated.name

        if self.parent.sysadmin is self:
            adminrole = self.parent.role_manager.administrator.name
            if adminrole not in rolenames:
                message = 'User "%s" is system admin.  Appending role "%s".'
                msglog.log('broadway', msglog.types.WARN,
                           message % (self.name, adminrole))
                rolenames.append(adminrole)
        elif self.parent.anonymous is self:
            unknownrole = self.parent.role_manager.unknown.name
            if unknownrole not in rolenames:
                message = 'User "%s" is anonymous.  Appending role "%s".'
                msglog.log('broadway', msglog.types.WARN,
                           message % (self.name, unknownrole))
                rolenames.append(unknownrole)
        self._lock.acquire()
        try:
            previous = self.roles
            if len(rolenames) == 0:
                unknownrole = self.parent.role_manager.unknown.name
                rolenames.append(unknownrole)
            self.roles = rolenames
        finally:
            self._lock.release()
        if self.roles != previous:
            event = UserRolesModified(self, self.roles, previous)
            self.dispatcher.dispatch(event)
        return
Example #16
0
class NeoAlarm(ConfigurableNode):
    implements(IAlarm)
    security = SecurityInformation.from_default()
    secured_by(security)
    security.make_private('events')
    def __init__(self, *args):
        self.events = {}
        self.max_raised = ""
        self.max_cleared = ""
        self.max_accepted = ""
        #CSCtf98046:changing default priority to P1
        self.priority = "P1"
        self.description = ""
        self.source = 'broadway'
        self.dispatcher = Dispatcher()
        super(NeoAlarm, self).__init__(*args)
    def configure(self,config):
        super(NeoAlarm, self).configure(config)
        self.setattr('source', config.get('source', self.source))
        priority = config.get("priority", self.priority)
        #CSCtf98046-changing all the blank priorities to P1. PH alarms have blank priority.
        if priority == "":
            priority = "P1"
        self.setattr('priority', priority)
        if "max_raised" in config:
            policy = config["max_raised"]
            if policy:
                try:
                    policy = int(policy)
                except ValueError:
                    raise ValueError('Value of field \'Max raised\' is not numeric')
            self.max_raised = policy
        if "max_cleared" in config:
            policy = config["max_cleared"]
            if policy:
                try:
                    policy = int(policy)
                except ValueError:
                    raise ValueError('Value of field \'Max cleared\' is not numeric')
            self.max_cleared = policy
        if "max_accepted" in config:
            policy = config["max_accepted"]
            if policy:
                try:
                    policy = int(policy)
                except ValueError:
                    raise ValueError('Value of field \'Max accepted\' is not numeric')
            self.max_accepted = policy
        description = config.get("description", self.description)
        self.setattr('description', description)
    def configuration(self):
        config = super(NeoAlarm, self).configuration()
        config['source'] = self.getattr('source')
        config['priority'] = self.getattr('priority')
        config["max_raised"] = self.getattr("max_raised", str)
        config["max_cleared"] = self.getattr("max_cleared", str)
        config["max_accepted"] = self.getattr("max_accepted", str)
        config['description'] = self.getattr('description')
        return config
    security.protect('trigger', 'Override')
    def trigger(self, source, timestamp, context, 
                information='', *args, **keywords):
        alarm_event = AlarmEvent(self)
        kwargs = {"message": information}
        triggered = AlarmTriggered(self, timestamp, source, context, **kwargs)
        self.dispatcher.dispatch(triggered)
    security.protect('clear', 'Override')
    def get_raised_policy(self):
        if isinstance(self.max_raised, int):
            policy = self.max_raised
        else:
            policy = self.parent.max_raised
        return policy
    def get_cleared_policy(self):
        if isinstance(self.max_cleared, int):
            policy = self.max_cleared
        else:
            policy = self.parent.max_cleared
        return policy
    def get_accepted_policy(self):
        if isinstance(self.max_accepted, int):
            policy = self.max_accepted
        else:
            policy = self.parent.max_accepted
        return policy
    def clear(self, source, timestamp, context, 
              information='', *args, **keywords):
        cleared = AlarmCleared(self, timestamp, source, context)
        self.dispatcher.dispatch(cleared)
    def prune(self, *args, **kw):
        events = self.get_events()
        self._terminate_events(events, "source alarm removed")
        return super(NeoAlarm, self).prune(*args, **kw)
    def _trim_backlog(self, state, limit):
        events = self.events_by_state(state)
        sortable = [(event.created(), event) for event in events]
        events = [event for ts,event in reversed(sorted(sortable))][limit:]
        return self._terminate_events(events, "trim %r event backlog" % state)
    def _terminate_events(self, events, reason):
        for event in events:
            try:
                event.terminate("Alarm %r" % self.name, reason)
            except:
                message = "Failed to terminate: %s."
                msglog.warn("Failed to terminate: %s." % event)
                msglog.exception(prefix="handled")
            else:
                message = "Alarm %r terminated event %s: %s."
                msglog.inform(message % (self.name, event, reason))
        return events
    def get_event(self, id): 
        return self.events[id]
    # Trick to make Framework's as_node work with AlarmEvents.
    get_child = get_event
    def get_events(self): 
        return self.events.values()
    def get_events_dictionary(self):
        states = {"raised": [], "accepted": [], "cleared": [], "closed": []}
        for event in self.get_events():
            states[event.state.lower()].append(event)
        return states
    def get_event_count(self):
        return len(self.get_events())
    def get_event_counts(self):
        states = self.get_events_dictionary()
        return dict([(st, len(evs)) for st,evs in states.items()])
    def events_by_state(self, state, negate=False):
        state = state.upper()
        events = self.get_events()
        if negate: 
            events = [event for event in events if event.state != state]
        else: 
            events = [event for event in events if event.state == state]
        return events
    def get_raised(self): 
        return self.events_by_state('raised')
    def get_accepted(self): 
        return self.events_by_state('accepted')
    def get_cleared(self): 
        return self.events_by_state('cleared')
    def get_closed(self): 
        return self.events_by_state('closed')
    def get_not_raised(self): 
        return self.events_by_state('raised', True)
    def get_not_accepted(self): 
        return self.events_by_state('accepted', True)
    def get_not_cleared(self): 
        return self.events_by_state('cleared', True)
    def get_not_closed(self): 
        return self.events_by_state('closed', True)
    def dispatch(self, event):
        if isinstance(event, AlarmEventRaised):
            self.events[event.source.GUID] = event.source
            self.dispatcher.dispatch(event.source)
            self.parent.dispatch(event.source)
        self.dispatcher.dispatch(event)
        result = self.parent.dispatch(event)
        if isinstance(event, AlarmEventRaised):
            policy = self.get_raised_policy()
            if policy > 0:
                self._trim_backlog("raised", policy)
        elif isinstance(event, AlarmEventAccepted):
            policy = self.get_accepted_policy()
            if policy > 0:
                self._trim_backlog("accepted", policy)
        elif isinstance(event, AlarmEventCleared):
            policy = self.get_cleared_policy()
            if policy > 0:
                self._trim_backlog("cleared", policy)
        elif isinstance(event, AlarmEventClosed):
            del(self.events[event.source.GUID])
        return result
    def __str__(self):
        typename = type(self).__name__
        return "%s(%r)" % (typename, self.as_node_url())
    def __repr__(self):
        return "<%s at %#x>" % (self, id(self))
Example #17
0
class TriggerManager(CompositeNode):
    implements(ITriggerManager)
    security = SecurityInformation.from_default()
    secured_by(security)

    def __init__(self, *args):
        self.dispatcher = None
        self._queue = None
        self._stopflag = None
        self._thread = None
        CompositeNode.__init__(self, *args)
    security.protect('get_trigger', 'View')
    def get_triggers(self):
        return self.children_nodes()
    security.protect('get_trigger', 'View')
    def get_trigger(self, name):
        return self.get_child(name)
    security.protect('add_trigger', 'Configure')
    def add_trigger(self, trigger):
        return self.add_child(trigger)
    security.protect('remove_trigger', 'Configure')
    def remove_trigger(self, trigger):
        return self.prune_child(trigger)
    security.protect('get_trigger_names', 'View')
    def get_trigger_names(self):
        return self.children_names()
    security.protect('get_active', 'View')
    def get_active(self):
        children = self.children_nodes()
        active = map(Trigger.is_active, children)
        return [child for child in children if child.is_active()]
    security.protect('get_inactive', 'View')
    def get_inactive(self):
        children = self.children_nodes()
        active = map(Trigger.is_active, children)
        return [child for child in children if not child.is_active()]
    def start(self):
        if self._thread is not None:
            raise Exception('Cannot call start on started '
                            'Manager without stopping.')
        if self.dispatcher is None:
            self.dispatcher = Dispatcher(self.url)
        self.triggersub = self.dispatcher.register_for_type(
            self.handle_triggered, TriggerActivated)
        self.clearsub = self.dispatcher.register_for_type(
            self.handle_cleared, TriggerCleared)
        self._startmanager()
        return super(TriggerManager, self).start()
    def stop(self):
        if self.triggersub: self.dispatcher.unregister(self.triggersub)
        if self.clearsub: self.dispatcher.unregister(self.clearsub)
        self.triggersub = self.clearsub = None
        self._stopmanager()
        return super(TriggerManager, self).stop()
    def _add_child(self, child): pass
    def _rename_child(self, *args): pass
    def queue_trigger(self, trigger):
        self._queue.put(trigger)
    def is_running(self):
        return not not (self._thread and self._thread.isAlive())
    security.protect('handle_triggered', 'Override')
    def handle_triggered(self, event):
        trigger = event.get_trigger()
        targets = trigger.get_targets()
        arguments = event.get_arguments()
        for target in targets: target.trigger(*arguments)
        return len(targets)
    security.protect('handle_cleared', 'Override')
    def handle_cleared(self, event):
        trigger = event.get_trigger()
        targets = trigger.get_targets()
        arguments = event.get_arguments()
        for target in targets: target.clear(*arguments)
        return len(targets)
    def _startmanager(self):
        self._queue = queue = Queue()
        self._stopflag = stopflag = Flag()
        self._thread = thread = ImmortalThread(
            name=self.url, target=self._runmanager, args = (stopflag, queue))
        thread.start()
    def _stopmanager(self):
        stopflag, self._stopflag = self._stopflag, None
        thread, self._thread = self._thread, None
        if not thread: return
        thread.should_die()
        stopflag.set()
        thread.join()
    def _runmanager(self, stopflag, queue):
        while not stopflag.isSet():
            trigger = queue.get(1)
            if trigger is not NOTHING:
                trigger()
        else:
            msglog.log('broadway', msglog.types.INFO,
                       'Trigger Manager exiting run.')
            print 'Trigger Manager run exiting.'
        return
Example #18
0
class TriggerManager(CompositeNode):
    implements(ITriggerManager)
    security = SecurityInformation.from_default()
    secured_by(security)

    def __init__(self, *args):
        self.dispatcher = None
        self._queue = None
        self._stopflag = None
        self._thread = None
        CompositeNode.__init__(self, *args)

    security.protect('get_trigger', 'View')

    def get_triggers(self):
        return self.children_nodes()

    security.protect('get_trigger', 'View')

    def get_trigger(self, name):
        return self.get_child(name)

    security.protect('add_trigger', 'Configure')

    def add_trigger(self, trigger):
        return self.add_child(trigger)

    security.protect('remove_trigger', 'Configure')

    def remove_trigger(self, trigger):
        return self.prune_child(trigger)

    security.protect('get_trigger_names', 'View')

    def get_trigger_names(self):
        return self.children_names()

    security.protect('get_active', 'View')

    def get_active(self):
        children = self.children_nodes()
        active = map(Trigger.is_active, children)
        return [child for child in children if child.is_active()]

    security.protect('get_inactive', 'View')

    def get_inactive(self):
        children = self.children_nodes()
        active = map(Trigger.is_active, children)
        return [child for child in children if not child.is_active()]

    def start(self):
        if self._thread is not None:
            raise Exception('Cannot call start on started '
                            'Manager without stopping.')
        if self.dispatcher is None:
            self.dispatcher = Dispatcher(self.url)
        self.triggersub = self.dispatcher.register_for_type(
            self.handle_triggered, TriggerActivated)
        self.clearsub = self.dispatcher.register_for_type(
            self.handle_cleared, TriggerCleared)
        self._startmanager()
        return super(TriggerManager, self).start()

    def stop(self):
        if self.triggersub: self.dispatcher.unregister(self.triggersub)
        if self.clearsub: self.dispatcher.unregister(self.clearsub)
        self.triggersub = self.clearsub = None
        self._stopmanager()
        return super(TriggerManager, self).stop()

    def _add_child(self, child):
        pass

    def _rename_child(self, *args):
        pass

    def queue_trigger(self, trigger):
        self._queue.put(trigger)

    def is_running(self):
        return not not (self._thread and self._thread.isAlive())

    security.protect('handle_triggered', 'Override')

    def handle_triggered(self, event):
        trigger = event.get_trigger()
        targets = trigger.get_targets()
        arguments = event.get_arguments()
        for target in targets:
            target.trigger(*arguments)
        return len(targets)

    security.protect('handle_cleared', 'Override')

    def handle_cleared(self, event):
        trigger = event.get_trigger()
        targets = trigger.get_targets()
        arguments = event.get_arguments()
        for target in targets:
            target.clear(*arguments)
        return len(targets)

    def _startmanager(self):
        self._queue = queue = Queue()
        self._stopflag = stopflag = Flag()
        self._thread = thread = ImmortalThread(name=self.url,
                                               target=self._runmanager,
                                               args=(stopflag, queue))
        thread.start()

    def _stopmanager(self):
        stopflag, self._stopflag = self._stopflag, None
        thread, self._thread = self._thread, None
        if not thread: return
        thread.should_die()
        stopflag.set()
        thread.join()

    def _runmanager(self, stopflag, queue):
        while not stopflag.isSet():
            trigger = queue.get(1)
            if trigger is not NOTHING:
                trigger()
        else:
            msglog.log('broadway', msglog.types.INFO,
                       'Trigger Manager exiting run.')
            print 'Trigger Manager run exiting.'
        return