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)
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 = {}
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 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 __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 __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 = {}
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 __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)
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)
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
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)
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)
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
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
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))
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
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