def removeSubscription (self, name): ''' remove a subscription type. Parameters: name is the actual Python class for the IDL struct. Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #assume it's the class for the IDL struct if not isinstance(name, str): name = str(name.__name__) self.logger.logInfo(name) try: self.consumerAdmin.subscription_change([], [CosNotification.EventType(self.getChannelDomain(), name)]) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("exception", str(e))])
def mockCreate(): e = NotifyMonitoringExt.NameAlreadyUsed() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.nc.channelName), NameValue("reason", "Unable to create channel"), NameValue("exception", str(e)) ])
def createNotificationChannel(self): ''' Creates the notification channel. Only to be called if it does not already exist. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get at the Notification Service first. try: self.channel_factory = self.nt.getObject( self.getNotificationFactoryName(), "") self.channel_factory = self.channel_factory._narrow( NotifyMonitoringExt.EventChannelFactory) except Exception, e: if not self.autoreconnect: # Only print the exception when autoreconnect is disabled print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Unable to get Notification Service"), NameValue("exception", str(e)) ])
def initCORBA(self): ''' Handles all the CORBA involved in creating a Consumer. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get admin object. try: # get admin object for the consumer and the proxy supplier from # admin (self.consumerAdmin, adminid) = self.evtChan.new_for_consumers( CosNotifyChannelAdmin.AND_OP) (self.spps, pid) = self.consumerAdmin.obtain_notification_push_supplier( CosNotifyChannelAdmin.STRUCTURED_EVENT) #unfortunately this HAS to be narrowed. self.spps = self.spps._narrow( CosNotifyChannelAdmin.StructuredProxyPushSupplier) # to make NRI happy pid = 0 adminid = 0 except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Bad proxy or admin"), NameValue("exception", str(e)) ])
def addFilter(self, type_of_event, filter_exp): ''' add a filter. Parameters: - type_of_event is the actual Python class for the IDL struct. - filter_exp is an EXTENDED_TCL string. Returns: The ID of the newly created filter (positive integer?) Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #assume it's the class for the IDL struct if not isinstance(type_of_event, str): eventtype = str(type_of_event.__name__) else: eventtype = type_of_event try: t_filter_factory = self.evtChan._get_default_filter_factory() #create the filter t_filter = t_filter_factory.create_filter(self.getFilterLanguage()) t_event_type = [CosNotification.EventType(self.getChannelDomain(), str(eventtype))] t_cexp = [CosNotifyFilter.ConstraintExp(t_event_type, str(filter_exp))] t_filter.add_constraints(t_cexp) return self.spps.add_filter(t_filter) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("exception", str(e))])
def publishEvent(self, simple_data=None, event_callback=None, type_name=None, event_name="", se=None, supplier_name=None): ''' publishEvent is the one method developers have to use. publishEvent() is designed so Supplier does not have to be subclassed. Params: - simple_data is a user-defined IDL struct. If this parameter is not specified by the developer, se MUST be used. 99% of the time developers should specify the simple_data parameter and NOTHING ELSE! - event_callback is a reference to the user implemented eventProcessCallback the user must implements: eventSent(self, simple_data), eventDropped(self, simple_data) and eventStoredInQueue(self, simple_data) methods. - type_name is literally the type_name field of a structured event. This is an optional parameter and should not be specified under normal circumstances. If unspecified, the name of the simple_data object is used. - event_name is the event_name field of the structured event. Not really useful. - se is a fully-defined structured event. If this parameter is specified, all other parameters will be completely ignored. A check is made to ensure that this object is really what it claims to be. This parameter is reserved for ACS internal usage. - suppier_name is the name of the supplier publishing the event. This parameter is reserved for ACS internal usage. Returns: Nothing Raises: - ACSErrTypeCommonImpl.CORBAProblemExImpl - ACSErrTypeCommonImpl.CouldntPerformActionExImpl - ACSErrTypeCommonImpl.TypeNotSupportedExImpl ''' #Whoah, user passed in the entire structured event...I'm impressed. if se != None: #check to make sure it's a structured event first. if isinstance(se, CosNotification.StructuredEvent): #publish it try: self.sppc.push_structured_event(se) return except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ]) else: raise TypeNotSupportedExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Not a structured event") ])
def consumerReady(self): ''' Consumer can now begin receiving events after invoking consumerReady. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' try: self.spps.connect_structured_push_consumer(self._this()) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ])
def resume(self): ''' Resume receiving structured events. All events queued by the Supplier will be forwarded to this Consumer instance. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' try: self.spps.resume_connection() except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ])
def addSubscription (self, name, handler_function=None): ''' add a subscription to a given type. Parameters - name is the actual Python class for the IDL struct. - handler_function If a structured event is received and the registerHandler method has been defined on that SEs type_name, the handler_function must be able to process filterable_data[0].value.value(). In other words every time an event of this nature is received, the Consumer object will first try to invoke the handler_function using the REAL object extracted from the CORBA Any in the structured event located at the the first position of the filterable_data list. IF THIS FAILS, the Consumer simply passes the event to the processEvent(...) method which will have hopefully been overriden by the developer. Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #two cases here...either they're passing a string or the Python IDL #struct class handle both regardles. if not isinstance(name, str): #assume it's the class for the IDL struct name = str(name.__name__) #save the handler for future use if handler_function != None: self.handlers[name] = handler_function self.logger.logInfo(name) try: self.consumerAdmin.subscription_change([CosNotification.EventType(self.getChannelDomain(), name)], []) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("exception", str(e))])
def suspend(self): ''' Stop receiving structured events. All events published on this channel will not be processed by this Consumer instance, but will be queued for later delivery by the Supplier. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' try: self.spps.suspend_connection() except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ])
def resume(self): ''' Resume receiving structured events. All events queued by the Supplier will be forwarded to this Consumer instance. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' self.lockAction.acquire() try: self.spps.resume_connection() self.suspended = False except CosNotifyChannelAdmin.ConnectionAlreadyActive: self.suspended = False except Exception, e: throw_ex = True if self.autoreconnect: nAttempts = 5 connected = False while not connected and nAttempts > 0: try: self.reinitConnection() connected = True except: time.sleep(1) nAttempts -= 1 if not connected: self.logger.logError("After 5 attempts the consumer couldn't reconnect to the channel '%s'"%(self.channelName)) else: throw_ex = False self.suspended = False if throw_ex: print_exc() raise CORBAProblemExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("exception", str(e))])
def initCORBA(self): ''' Handles all the CORBA involved in creating a CommonNC. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get orb stuff, and name service tree. #If any of this fails, must raise an exception because there's absolutely #nothing that can be done. try: self.nt = NameTree.nameTree(getORB()) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ])
def initCORBA(self): ''' Handles all the CORBA involved in creating a Supplier. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get admin object. try: (self.supplierAdmin, adminid) = self.evtChan.new_for_suppliers( CosNotifyChannelAdmin.AND_OP) #to make the NRI happy adminid = 0 except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Unable to obtain supplier admin"), NameValue("exception", str(e)) ])
class ArchiveSupplier (Supplier): #-------------------------------------------------------------------------- ''' ArchiveSupplier is a a Supplier-derived class designed solely for the purpose of sending notification channel structured events automatically by BACI ''' #-------------------------------------------------------------------------- def __init__ (self): ''' Constructor. Params: - handler Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' Supplier.__init__(self, acscommon.ARCHIVING_CHANNEL_NAME, None, acscommon.ACS_NC_DOMAIN_ARCHIVING) #-------------------------------------------------------------------------- def getChannelKind(self): ''' Overridden. Parameters: None Returns: pointer to a constant string. Raises: Nothing ''' return acscommon.NC_KIND #-------------------------------------------------------------------------- def getChannelDomain(self): ''' Overridden. Parameters: None Returns: pointer to a constant string. Raises: Nothing ''' return "*" #------------------------------------------------------------------------------ def getNotificationFactoryName(self): ''' Overridden. Parameters: None Returns: pointer to a constant string. Normally acscommon::ARCHIVE_NOTIFICATION_FACTORY_NAME Raises: Nothing ''' return acscommon.ARCHIVE_NOTIFICATION_FACTORY_NAME #-------------------------------------------------------------------------- def publishEvent (self, simple_data=None, type_name=None, event_name="", se=None, supplier_name=None): ''' publishEvent is the one method developers have to use. Params: - simple_data is a user-defined IDL struct. If this parameter is not specified by the developer, se MUST be used. 99% of the time developers should specify the simple_data parameter and NOTHING ELSE! - type_name is literally the type_name field of a structured event. This is an optional parameter and should not be specified under normal circumstances. If unspecified, the name of the simple_data object is used. - event_name is the event_name field of the structured event. Not really useful. - se is a fully-defined structured event. If this parameter is specified, all other parameters will be completely ignored. A check is made to ensure that this object is really what it claims to be. This parameter is reserved for ACS internal usage. - suppier_name is the name of the supplier publishing the event. This parameter is reserved for ACS internal usage. Returns: Nothing Raises: - ACSErrTypeCommonImpl.CORBAProblemExImpl - ACSErrTypeCommonImpl.CouldntPerformActionExImpl - ACSErrTypeCommonImpl.TypeNotSupportedExImpl ''' #Whoah, user passed in the entire structured event...I'm impressed. if se != None: Supplier.publishEvent(simple_data,type_name,event_name,se, supplier_name) #User didn't specify type_name. Assume it's the name of the #repository ID. If that doesn't work either, must be a simple #CORBA type. if (type_name == None) and (simple_data != None): try: type_name = str(simple_data.__class__.__name__) except Exception, e: self.logger.logWarning(str(e)) print_exc() type_name = str(CORBA.id(simple_data)) elif (simple_data == None): raise CouldntPerformActionExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("reason", "Empty data")])
class Supplier(CosNotifyComm__POA.StructuredPushSupplier, CommonNC): ''' Class Supplier is the implementation of a CORBA structured push supplier. It is provided to hide details of the CORBA Notificiation Service from the developer. Furthermore, one can reconfigure the quality of service properties and administrator properties for a given notification channel by overriding the correct methods in this class. ''' #-------------------------------------------------------------------------- def __init__(self, channelname, component=None, domain=None): ''' Constructor. Params: - channelName is the channel name - component is the component this supplier has been instantiated from (if applicable). This parameter is likely to become mandatory in future version of ACS - domain is the name of the domain of notification channels the channel belongs to Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Logger for this supplier self.logger = getLogger(str(channelname) + "-Supplier") #Call the super's constructor CommonNC.__init__(self, channelname, component, domain) #CORBA ref to the channels supplier admin self.supplierAdmin = None #CORBA ref to this suppliers structured proxy push consumer self.sppc = None #number of events sent so far self.count = 0 #Handle all of the CORBA stuff now CommonNC.initCORBA(self) self.initCORBA() #------------------------------------------------------------------------------ def initCORBA(self): ''' Handles all the CORBA involved in creating a Supplier. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get admin object. try: (self.supplierAdmin, adminid) = self.evtChan.new_for_suppliers( CosNotifyChannelAdmin.AND_OP) #to make the NRI happy adminid = 0 except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Unable to obtain supplier admin"), NameValue("exception", str(e)) ]) #Get proxy consumer; activate this supplier instance; try: (self.sppc, pid) = self.supplierAdmin.obtain_notification_push_consumer( CosNotifyChannelAdmin.STRUCTURED_EVENT) self.sppc = self.sppc._narrow( CosNotifyChannelAdmin.StructuredProxyPushConsumer) self.sppc.connect_structured_push_supplier(self._this()) self.connected = 1 #to make the NRI happy pid = 0 except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Bad proxy or admin"), NameValue("exception", str(e)) ])
#get the time the event is being sent time_stamp = getTimeStamp() #create the CORBA Any in the "normal" manner first. If this #fails, try omniORB's any helper module designed for simple types. try: corba_any = CORBA.Any(CORBA.TypeCode(CORBA.id(simple_data)), simple_data) corba_time = CORBA.Any(CORBA.TC_long, time_stamp.value) except Exception, e: self.logger.logTrace(str(e)) try: corba_any = any.to_any(simple_data) corba_time = any.to_any(time_stamp.value) except Exception, e: print_exc() raise TypeNotSupportedExImpl(nvSeq=[NameValue("channelname", self.channelName), NameValue("exception", str(e)), NameValue("reason", "Data not a CORBA type")]) #Create the real structured event. Look at CosNotification.idl to see these definitions fixed_header = CosNotification.FixedEventHeader(CosNotification.EventType(str(self.getChannelDomain()), str(type_name)), str(event_name)) header = CosNotification.EventHeader (fixed_header, []) # create list of Property to pass in the event new_list = [CosNotification.Property("time_stamp",corba_time), CosNotification.Property("value",corba_any)]
NameValue("reason", "Not a structured event") ]) #User didn't specify type_name. Assume it's the name of the #repository ID. If that doesn't work either, must be a simple #CORBA type. if (type_name == None) and (simple_data != None): try: type_name = str(simple_data.__class__.__name__) except Exception, e: self.logger.logWarning(str(e)) print_exc() type_name = str(CORBA.id(simple_data)) elif (simple_data == None): raise CouldntPerformActionExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Empty data") ]) #create the CORBA Any in the "normal" manner first. If this #fails, try omniORB's any helper module designed for simple types. try: corba_any = CORBA.Any(CORBA.TypeCode(CORBA.id(simple_data)), simple_data) except Exception, e: self.logger.logTrace(str(e)) try: corba_any = any.to_any(simple_data) except Exception, e: print_exc() raise TypeNotSupportedExImpl(nvSeq=[
class CommonNC(object): ''' Serves as a baseclass for notification channel objects. The notification channel is registered in the NamingService with the name: channelName+ NAMESERVICE_BINDING_NC_DOMAIN_SEPARATOR+domainName (see COMP-9338 for further details). If the domain name is not provided then the fault is used: NAMESERVICE_BINDING_NC_DOMAIN_DEFAULT ''' #-------------------------------------------------------------------------- def __init__(self, channelname, component, domainname=None): ''' Constructor. Params: - channelName is the channel name - component is the component this object resides within - domainName is the domain the channel belongs to Returns: Nothing Raises: Nothing. ''' #true means I need to disconnect later self.connected = 0 #name of the channel we'll be working with self.channelName = str(channelname) #domainname of the channel we'll be working with # # If the domain name is None then we assign a default here. # however for ACS NCs we do not have to register with a domain # so we override this default while building the channel name in # combineChannelAndDomainName if domainname is None: self.domainName = NAMESERVICE_BINDING_NC_DOMAIN_DEFAULT else: self.domainName = str(domainname) #CORBA ref to the channel self.evtChan = None #Python Naming Service helper class self.nt = None #component...use this to get the name. self.component = component #create the reconnection callback self.channel_factory = None self.callback = ReconnectionCallback(self) self.channelTimestamp = None #Autoreconnect when detecting that the connection to the channel has been lost self.autoreconnect = False #------------------------------------------------------------------------------ def combineChannelAndDomainName(self): return self.channelName + NAMESERVICE_BINDING_NC_DOMAIN_SEPARATOR + self.domainName #------------------------------------------------------------------------------ def configQofS(self): ''' Configures the quality of service properties for this channel. Only useful if the channel has not been created yet and this particular method is being overriden. Parameters: None Returns: A sequence of Quality of Service properties. Raises: Nothing ''' if cdb_channel_config_exists(self.channelName): self.logger.logDebug("Found Q of S properties in the CDB") return get_channel_qofs_props(self.channelName) else: return [] #------------------------------------------------------------------------------ def configAdminProps(self): ''' Configures the administrative properties for this channel. Only useful if the channel has not been created yet and this particular method is being overriden. Parameters: None Returns: A sequence of Administrative properties. Raises: Nothing ''' if cdb_channel_config_exists(self.channelName): self.logger.logDebug("Found admin properties in the CDB") return get_channel_admin_props(self.channelName) else: return [] #------------------------------------------------------------------------------ def getChannelKind(self): ''' This method returns a constant character pointer to the "kind" of notification channel as registered with the naming service (i.e., the kind field of a CosNaming.Name) which is normally equivalent to acscommon::NC_KIND. The sole reason this method is provided is to accomodate subclasses which subscribe/publish non-ICD style events (ACS archiving channel for example).In that case, the developer would override this method. Parameters: None Returns:a constant string. Raises: Nothing ''' return acscommon.NC_KIND #------------------------------------------------------------------------------ def getChannelDomain(self): ''' This method returns a constant character pointer to the notification channel domain which is normally equivalent to acscommon::ALMADOMAIN. The sole reason this method is provided is to accomodate subclasses which subscribe/publish non-ICD style events (ACS archiving channel for example). In that case, the developer would override this method. Parameters: None Returns: a constant string. Raises: Nothing ''' return acscommon.ALMADOMAIN #------------------------------------------------------------------------------ def getNotificationFactoryNameForChannel(self, channel, domain=None): ''' This method returns the name of the notification service for the channel or domain from the configuration information given in the CDB. Parameters: - channel is the channel name of the desired factory - domain is the domain of the desired factory Returns: string containing the factory name or None Raises: Nothing ''' temp = "" if channel is not None: crec = [ chan for chan in get_notification_service_mapping('Channel') if wildcharMatch(chan['Name'], channel) ] if crec != []: temp = crec[0]['NotificationService'] if len(temp) == 0 and (domain is not None): crec = [ chan for chan in get_notification_service_mapping('Domain') if wildcharMatch(chan['Name'], domain) ] if crec != []: temp = crec[0]['NotificationService'] if len(temp) == 0: crec = get_notification_service_mapping('Default') if crec != []: temp = crec[0]['DefaultNotificationService'] else: return None if not temp.endswith(acscommon.NOTIFICATION_FACTORY_NAME): return temp + acscommon.NOTIFICATION_FACTORY_NAME else: return temp #------------------------------------------------------------------------------ def getNotificationFactoryName(self): ''' This method returns the name of the notification service as registered with the CORBA Naming Service. Parameters: None Returns: pointer to a constant string. Normally acscommon::NOTIFICATION_FACTORY_NAME Raises: Nothing ''' return self.getNotificationFactoryNameForChannel( self.channelName, self.domainName) or acscommon.NOTIFICATION_FACTORY_NAME #------------------------------------------------------------------------------ def initCORBA(self): ''' Handles all the CORBA involved in creating a CommonNC. Parameters: None Returns: Nothing Raises: ACSErrTypeCommonImpl.CORBAProblemExImpl on critical failures ''' #Get orb stuff, and name service tree. #If any of this fails, must raise an exception because there's absolutely #nothing that can be done. try: self.nt = NameTree.nameTree(getORB()) except Exception, e: if not self.autoreconnect: # Only print the exception when autoreconnect is disabled print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ]) if self.nt == None: raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Naming Service") ]) #First try to use the naming service to access the channel. If that fails, #try to create it. If this also fails, forget it...there's nothing that #can be done. try: self.channel_factory = self.nt.getObject( self.getNotificationFactoryName(), "") self.channel_factory = self.channel_factory._narrow( NotifyMonitoringExt.EventChannelFactory) obj = self.nt.getObject(self.combineChannelAndDomainName(), self.getChannelKind()) self.evtChan = obj._narrow(NotifyMonitoringExt.EventChannel) # The channel could be resolved so we get also the timestamp from the Naming Service self.iniChannelTimestamp() except: try: self.createNotificationChannel() self.logger.logInfo('Created new channel.') except CORBAProblemExImpl, e: if e.getData('exception') == [ 'NotifyMonitoringExt.NameAlreadyUsed()' ]: while True: try: obj = self.nt.getObject( self.combineChannelAndDomainName(), self.getChannelKind()) self.evtChan = obj._narrow( NotifyMonitoringExt.EventChannel) # The channel could be resolved so we get also the timestamp from the Naming Service self.iniChannelTimestamp() except: pass if self.evtChan is not None: break else: raise
NameValue("exception", str(e)) ]) #Create the actual channel. try: (self.evtChan, chan_id) = self.channel_factory.create_named_channel( self.configQofS(), self.configAdminProps(), self.channelName) #make the NRI happy chan_id = None except AttributeError, e: if not self.autoreconnect: # Only print the exception when autoreconnect is disabled print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Invalid channel factory"), NameValue("exception", str(e)) ]) except Exception, e: if not self.autoreconnect: # Only print the exception when autoreconnect is disabled print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("reason", "Unable to create channel"), NameValue("exception", str(e)) ]) # Register the new channel w/ the naming service under the names & # type. The event channel is now ready for action. try: