cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1027
Views
0
Helpful
4
Replies

Can subscribers be multi threaded

tsiemers1
Spotlight
Spotlight

Currently running a subscriber that is watching an action. The subscriber works and kicks off when the registered path is updated. If I make multiple changes to the registered path it will wait until it is done with the first notification then on to the next one. Is it possible for the subscriber to run with multiple threads.

 

The path the subscriber is registered takes devices names as input, then the subscriber runs some code on each device.

 

Thanks,

1 Accepted Solution

Accepted Solutions

I think this is more a generic python question rather than NSO. As far as I know, there is nothing stopping you running your handler in a seperate thread. Check out the python threading library.

 

If you're anticipating there will be many of these long running threads executing in parallel, it's a good idea to minimise the number of transactions you keep open. For example, if your IOS upgrade takes 10 minutes, don't start a write transaction at the start, if you only need to write the result at the end. Also remember actions (like ios exec) don't need an open transaction. Check out "Example 81: Action request without transaction" in the Python API section of the Development Guide.

 

View solution in original post

4 Replies 4

lmanor
Cisco Employee
Cisco Employee

From the short description below, it looks like you are trying to build the same functionality that is already provide by 'Services' in NSO... provide some info, map the request to device configuration using templates or create code...

 

To understand when the subscriber runs you'll need to understand the transactional processing of NSO.

There is a presentation here that goes into details about the transactional processing...there is an associate video to go along with it, but unfortunately I cannot locate it: 

https://community.cisco.com/t5/nso-developer-hub-documents/nso-developer-days-performance-and-scaling-presentation/ta-p/3652827

Subscribers are informed of changes to elements in their target path during the 'notify' stage of each transaction that changes the target.  Each invocation of your action is likely a separate transaction thru NSO, and thus if each time the action is called the transaction changes the CDB in your subscriber's registered path, your subscriber will be triggered for that change.

If, however, you make multiple changes within the registered path branch in a single transaction the subscriber will only get called once, when the transaction is committed.

 

@lmanor 

Thanks, for the link to the transaction slides. The part I am stuck on is when the registered path is changed and the subscriber kicks off it will only handle one commit change at a time before moving on to the next one.

Say user A makes a commit to the registered path, it kicks off the subscriber, gets iterated and starts the post_iterate.

Then user B commits a change to the registered path a min later, subscriber sees the change and iterates the change, but waits to run post_iterate until user A's post_iterate is done.

What I am looking for is if the subscriber has the ability to run both users A request and user B request in post_iterate at the same time in different threads.

In the below user B's request makes it to the iterate function but will not be processed until user A has finished post_iterate function write_result.

Wondering if this isn't the right way to be kicking something like this off, the problem is it upgrades the router, reloads and waits for it to come back to do some post checks in the write_result function within post_iterate. Which causes user B's request to the /iosxe-upgrade/request/device to sit until post_iterate finishes the first one which could be 20-25 mins.

 

class IosxeUpgrade(Subscriber):
    def init(self):
        self.register('/iosxe-upgrade/request/device')

    def pre_iterate(self):
        return []

def iterate(self, kp, op, oldval, newval, state): if op is ncs.MOP_VALUE_SET: self.log.info('New IOS upgrade request: %s' % (str(kp[1:]))) state.append((newval, str(kp[1:]))) return ncs.ITER_RECURSE
def post_iterate(self, state): for request in state: self.write_result(ios_upgrade(self.log, request[0], request[1]), request[1])
def should_post_iterate(self, state): return state != []

I read over the API for subscriber but it's either not possible or I am missing something with getting post_iterate to run per request.

Thanks

 

I think this is more a generic python question rather than NSO. As far as I know, there is nothing stopping you running your handler in a seperate thread. Check out the python threading library.

 

If you're anticipating there will be many of these long running threads executing in parallel, it's a good idea to minimise the number of transactions you keep open. For example, if your IOS upgrade takes 10 minutes, don't start a write transaction at the start, if you only need to write the result at the end. Also remember actions (like ios exec) don't need an open transaction. Check out "Example 81: Action request without transaction" in the Python API section of the Development Guide.

 

Thanks, @Michael Maddern 

Was able to work over most of this during Live this year. I ended up changing it as you recommended above to close the transaction outside of the wait function. I do however think the right way to approach this is to use the example you referenced 'Action request without transaction', just tested and this way works and in my opinion is the correct way to handle the ios exec commands. All that said we ended up scraping this service and using CSM to do the upgrade of devices.

 

Thanks!