Contents
This tutorial is intended for application developers who need more fine-grained control over the connections made between onePK applications and network elements.
In onePK, a session represents an authenticated channel of communication between an application and a network element. This tutorial demonstrates how to configure a session, get the properties and statistics of a session.
The code used in this tutorial is located under <SDK Location>/python/tutorials/session/.
This tutorial assumes the application can connect properly to a network element. Please see the Connecting to a Network Element tutorial for information on how to make the initial connection.
NOTE: You are recommended to use TLS (Transport Layer Security) to enable secure communications between your applications and connected devices. For information about configuring TLS on your connected network element and enabling onePK TLS communication, see onePK Security in the Getting Started with onePK guide.
When connecting to a network element, the caller may optionally provide a SessionConfig that contains the required configuration for the resulting session. When creating the SessionConfig, the only required attribute is the transport mode.
For detailed information about setting up TLS communication, see onePK Security in the Getting Started with onePK Guide.
In case of TLS verification failure, pinning can be used to proceed with connection. Pinning is the process by which certain hosts can be whitelisted for TLS verification. If the presented certificate matches the known certificate for that host in the pinning file/DB, that connection proceeds even if the certificate fails the customary TLS verification. Using a handler for unverified TLS hosts, an application may present a fingerprint of the unknown host to a user for manual verification. User can setTLSPinning on the config to make use of pinning feature.
All other attributes are optional, and will take on their default values if not explicitly set. To demonstrate reconnecting to the session, the reconnect timer will be set to one minute.
# Construct a SessionConfig instance with the given transport mode. config = SessionConfig(mode) # Set the reconnect timer to one minute. config.reconnectTimer = 60 # The session attributes below this point are set to their default # values. # # Set the port to connect to on the network element. # TLS 15002 # TIPC N/A # if mode.lower() == "tls": config.port = config.DEFAULT_PORT config.transportMode = SessionConfig.SessionTransportMode.TLS config.ca_certs = tutorial.root_cert_path config.keyfile = tutorial.client_key_path config.certfile = tutorial.client_cert_path else: # Not required for TIPC. pass # Set the event queue size of the session. config.eventQueueSize = config.DEFAULT_EVENT_QUEUE_SIZE # Set the event thread pool size of the session. config.eventThreadPool = config.DEFAULT_THREADPOOL_SIZE # Set the event drop mode of the session. config.eventDropMode = config.DEFAULT_EVENT_DROP_MODE # Set the keepalive attributes of the session. # Idle time in seconds config.keepAliveIdleTime = config.DEFAULT_KEEPALIVE_IDLE_TIME # Interval between keepalives in seconds config.keepAliveInterval = config.DEFAULT_KEEPALIVE_INTERVAL # Number of keepalives config.keepAliveRetryCount = config.DEFAULT_KEEPALIVE_RETRY_COUNT
Connect to the element using the given session configuration. If no configuration is specified by the caller (i.e. null is used), the session will take on the default values.
handle = networkElement.connect(tutorial.get_username(), tutorial.get_password(), config)
Upon receipt of a certificate which could not be verified, this handler asks the application whether to accept the connection and/or whether to add the host to the pinning database. By default, the connection will be terminated and the pinning db will remain unchanged. See a sample handler in below code snippet.
if changed: msg = "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" msg +="WARNING: THE CERTIFICATE PRESENTED BY REMOTE HOST '%s'\n IS DIFFERENT FROM THE ONE PREVIOUSLY ACCEPTED" %(host) msg +="\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" else: msg = "WARNING: Certificate presented by remote host '%s' is not verified."%(host) msg += "\n\nThe %s fingerprint sent by the remote host(%s) is:\n%s" %(hashtype, host, finger_print) msg += "\n\nYou MUST verify the certificate on remote host before proceeding! \n" msg += "\nChoose from following options:" if self.pinning_file: prompt = "\nAccept and Pin (p), Accept Once (o), Reject (r) (default) :" else: prompt = "\nAccept Once (o), Reject (r) (default) :" sys.stdout.write(msg) self.decision = raw_input(prompt) while True: if not self.decision or self.decision.lower() == 'r': return tlspinning.DecisionType.REJECT elif self.decision.lower() == 'p' and self.pinning_file: return tlspinning.DecisionType.ACCEPT_AND_PIN elif self.decision.lower() == 'o': return tlspinning.DecisionType.ACCEPT_ONCE else: self.decision = raw_input(prompt)
Upon a successful connection, a session is established and a handle is returned in the form of a SessionHandle. When a session is in the connected state, its configuration cannot be modified. The session handle may be used to query information about the session. Here, we use it to get the session's ID, which will be needed when we want to reconnect to the session.
log = logging.getLogger('onep:SessionTutorial') log.setLevel(logging.INFO) retry = 3 app_terminate = False def handle_event(self, event, data): self.log.info("\n********* CONNECT LISTENER *******") self.log.info('Received connection event %s', event.elem.OnepSessionState.enumval(event.state)) if self.app_terminate: self.log.info("\n********* TUTORIAL TERMINATED *******") return if event.state == event.elem.OnepSessionState.ONEP_STATE_DISCONNECTED: if not self.retry: self.log.info("\n********* RECONNECT RETRY MAX FOR %d *******" % data['id']) event.elem.set_connection_listener(None, None) return try: self.log.info("\n********* RECONNECT SESSION %d *******" % data['id']) event.elem.reconnect(data['user'], data['pwd'], data['id'], data['sess']) except Exception as e: self.retry -= 1 self.log.info("\n********* RECONNECT FAILED SESSION %d*******" %data['id']) self.log.info("\n********* %s *******" % str(e))
Build a listener class to react to application connection events. The connection listener will be registered directly to the instantiated NetworkElement class.
In this example we have setup a log to send messages to the application logger. We have also added a maximum reconnect retry count and a flag to tell the listener when the application wants to exit without a reconnect attempt.
sessionID = originalSessionHandle._id
The session handle can also be used to get properties of the session and statistics about the session. Here, we just print them out.
# Get the property instance for this session using the # session handle. # property = handle.sessionProp # Get the port number the session is connected on. logger.info("Port: " + str(property.port)) # Get the event queue size of the session. logger.info("EventQueueSize: " + str(property.eventQueueSize)) # Get the event thread pool size of the session. logger.info("EventThreadPool: " + str(property.eventThreadPool)) # Get the event drop mode of the session. logger.info("EventDropMode: " + str(property.eventDropMode)) # Get the reconnect timer of the session in seconds. logger.info("ReconnectTimer: " + str(property.reconnectTimer)) # Get the transport mode of the session. logger.info("TransportMode: " + str(property.transportMode))
# Get the statistics instance for this session using the # session handle. # statistics = handle.sessionStat # Get the count of events received and dropped. logger.info("Events Total: %s", statistics.eventTotalCount) logger.info("\nEvents Dropped: %s", statistics.eventDropCount)
con_listener = TutorialReconnectListener() tutorial.get_network_element().set_connection_listener(con_listener, {'user': tutorial.get_username(), 'pwd': tutorial.get_password(), 'id': sessionID, 'sess' : config})
Register your connection listener to the network element.
Congratulations! You have configured a session, read the properties and statistics of a session, and reconnected to a session.
To try out this tutorial code by compiling and running it, you can find the code located at: <SDK Location>/python/tutorials/session/.