def getMyCorbaRef(self): # pragma: NO COVER ''' Helper method which returns this Python objects underlying CORBA servant reference. This implementation implicityly activates the client using the default POA if it has not been activated before. Parameters: None Returns: a CORBA reference to this object Raises: CORBAProblemExImpl ''' #if this object has not already been activated as a CORBA object... if self.corbaRef == None: try: #...activate it using the default POA self.corbaRef = self._this() except Exception, e: self.logger.logWarning( 'Failed to activate self as a CORBA object: ' + str(e)) print_exc() raise CORBAProblemExImpl() #sanity check if self.corbaRef == None: # without a client, we can't go on self.logger.logWarning( 'Failed to activate self as a CORBA object: ' + str(e)) raise CORBAProblemExImpl() #OK to return at this point return self.corbaRef
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 managerLogin(self): ''' Login into the manager Parameters: None Returns: The token received from the manager Raises: CORBAProblemExImpl If the login failed ''' token = None try: if getManager() == None: raise CORBAProblemExImpl() with self.loggingIn: token = getManager().login(self.getMyCorbaRef()) self.loggedIn = True except Exception, e: #cannot go on if the login fails raise CORBAProblemExImpl(exception=e)
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 __activateOffShoot(self, comp_name, py_object): # pragma: NO COVER ''' A method designed to activate ACS::OffShoot IDL interfaces as CORBA objects. Parameters: - py_object is a Python object which implements an IDL interface derived from ACS::OffShoot Returns: a reference to the newly created CORBA object Raises: CORBAProblemExImpl ''' try: return py_object._this() except: print_exc() raise CORBAProblemExImpl()
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 __init__(self, name="Python Client"): ''' Initialize the client. Parameters: - name is what manager will refer to this client instance as Returns: Nothing Raises: CORBAProblemExImpl ''' #security token given to us by the manager self.token = None #name we will call ourself when contacting the manager self.name = str(name) #Logger used by container/components try: self.logger except: self.logger = getLogger(name) startPeriodicFlush(3) #List of components manager says are active self.managerComponents = [] #CORBA reference to ourself self.corbaRef = None #True if the client is logged in self.loggedIn = False # Ensure that login and logout are executed in mutual exclusion self.loggingIn = Lock() #get our token from manager self.token = self.managerLogin() #sanity check if self.token == None: # a nil token implies manager doesn't "like" this client raise CORBAProblemExImpl()
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 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)) ])
event_calback.eventSent(simple_data) #For HLA/ITS - to be removed later! if get_integration_logs(self.channelName) == 1: try: comp_name = self.component.getName() except: comp_name = "Unknown" self.logger.logNotice("Publisher:" + comp_name + ", Event Type:" + type_name) self.count = self.count + 1 except (CORBA.COMM_FAILURE, CORBA.TRANSIENT): #Notify Service is down if event_callback != None: event_calback.eventDropped(simple_data) except Exception, e: print_exc() raise CORBAProblemExImpl(nvSeq=[ NameValue("channelname", self.channelName), NameValue("exception", str(e)) ]) return #------------------------------------------------------------------------------ def reconnect(self, ecf): self.evtChan.set_qos(self.configQofS()) self.supplierAdmin.set_qos(self.configAdminProps())
]) #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: self.nt.putObject(self.combineChannelAndDomainName(),
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