cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
929
Views
5
Helpful
3
Replies

Current service config from Python

douglasfir
Level 1
Level 1

Hello,

 

is it possible to check service configuration in CDB before service is updated from Python code?

For instance the following code gives me the new service parameters (that are to be applied), but I would like to check the service config in CDB before commit for that same service:

    @Service.pre_modification
    def cb_pre_modification(self, tctx, op, kp, root, proplist):
        if op != _ncs.dp.NCS_SERVICE_DELETE:
            service = ncs.maagic.cd(root, kp)

The reason behind this is that I am updating some data only if certain service parameter has new value (password change) and not if other service parameters are being changed, so I need to compare the new value (service update) with the old one (as seen in CDB).

 

Thanks!

Dragan

 

2 Accepted Solutions

Accepted Solutions

Nabsch
Spotlight
Spotlight

Hello,

 

 

Here Doc  for diff_iterate


As  you can see the oldv is always None . You will be able to detect that there’s a change but you cannot get the old value.

 

        def iter(keypath, operation, oldvalue, newvalue)
    
    Where arguments are:
    
    * keypath - the affected path (HKeypathRef)
    * operation - one of MOP_CREATED, MOP_DELETED, MOP_MODIFIED, MOP_VALUE_SET,
                  MOP_MOVED_AFTER, or MOP_ATTR_SET
    * oldvalue - always None
    * newvalue - see below
    
    The 'newvalue' argument may be set for operation MOP_VALUE_SET and is a
    Value object in that case. For MOP_MOVED_AFTER it may be set to a list of
    key values identifying an entry in the list - if it's None the list entry
    has been moved to the beginning of the list. For MOP_ATTR_SET it will be
    set to a 2-tuple of Value's where the first Value is the attribute set
    and the second Value is the value the attribute was set to. If the
    attribute has been deleted the second value is of type C_NOEXISTS
    
    The iter function should return one of:
    
    * ITER_STOP - Stop further iteration
    * ITER_RECURSE - Recurse further down the node children
    * ITER_CONTINUE - Ignore node children and continue with the node's siblings
    
    One could also define a class implementing the call function as:
    
        class DiffIterator(object):
            def __init__(self):
                self.count = 0
    
            def __call__(self, kp, op, oldv, newv):
                print('kp={0}, op={1}, oldv={2}, newv={3}'.format(
                    str(kp), str(op), str(oldv), str(newv)))
                self.count += 1
                return _confd.ITER_RECURSE
    
    Keyword arguments:
    
    * thandle -- transaction handle
    * iter -- iterator function, will be called for every diff in the transaction
    * flags -- bitmask of ITER_WANT_ATTR and ITER_WANT_P_CONTAINER

 

 

An example on how to get the modified leaf from the service modification

 

I define a  new class

 

 

OPER = {
    1: 'MOP_CREATED',
    2: 'MOP_DELETED',
    3: 'MOP_MODIFIED',
    4: 'MOP_VALUE_SET',
    5: 'MOP_MOVED_AFTER',
    6: 'MOP_ATTR_SET'
}

class DiffIterator(object):
 
    def __init__(self):
         self.count = 0
         self.changes = []
    def __call__(self, kp, op, oldv, newv):
        info = {
            "kp": str(kp),
            "op": OPER[op],
            "oldv": str(oldv),
            "newv": str(newv)
        }
        self.changes.append(info)
        self.count += 1
        return ncs.ITER_RECURSE

 

 

 

 

 

Then in the premod i did 

 

    @Service.pre_modification
    def cb_pre_modification(self, tctx, op, kp, root, proplist):
        self.log.info('Service premod(service=', kp, ')')
        self.log.info('Service premod(tctx=', tctx, ')')
        self.log.info('Service premod(op=', op, ')')
        self.log.info('Service premod(kp=', kp, ')')
        self.log.info('Service premod(proplist=', proplist, ')')
        maapi = ncs.maagic.get_maapi(root)   
        maapi.attach(tctx)
        diff = DiffIterator()
        #maapi.diff_iterate(tctx.th, self.iterate, 0)
        maapi.diff_iterate(tctx.th, diff, 0)
        self.log.info(f"Diff counts  {diff.count} Diff changes {diff.changes}")
        

 

Here the log generated when i change some leaf in my service 

 

<INFO> 01-Jun-2022::18:20:49.753 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(service=/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2})
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(tctx=_ncs.TransCtxRef : fd=9 : vfd=-1 : th=12727)
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(op=1)
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(kp=/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2})
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(proplist=[])
<INFO> 01-Jun-2022::18:20:49.755 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Diff counts  3 Diff changes [{'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}', 'op': 'MOP_MODIFIED', 'oldv': 'None', 'newv': 'None'}, {'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}/dummy', 'op': 'MOP_VALUE_SET', 'oldv': 'None', 'newv': '45006668'}, {'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}/c', 'op': 'MOP_VALUE_SET', 'oldv': 'None', 'newv': 'trot'}]


then you can iterate through diff.changes and check kp that contains the Key path with the  node(leaf) name 

 

 

View solution in original post

Hello @douglasfir  If it's answering your question . Can you mark it as solved ?

View solution in original post

3 Replies 3

Nabsch
Spotlight
Spotlight

Hello,

 

 

Here Doc  for diff_iterate


As  you can see the oldv is always None . You will be able to detect that there’s a change but you cannot get the old value.

 

        def iter(keypath, operation, oldvalue, newvalue)
    
    Where arguments are:
    
    * keypath - the affected path (HKeypathRef)
    * operation - one of MOP_CREATED, MOP_DELETED, MOP_MODIFIED, MOP_VALUE_SET,
                  MOP_MOVED_AFTER, or MOP_ATTR_SET
    * oldvalue - always None
    * newvalue - see below
    
    The 'newvalue' argument may be set for operation MOP_VALUE_SET and is a
    Value object in that case. For MOP_MOVED_AFTER it may be set to a list of
    key values identifying an entry in the list - if it's None the list entry
    has been moved to the beginning of the list. For MOP_ATTR_SET it will be
    set to a 2-tuple of Value's where the first Value is the attribute set
    and the second Value is the value the attribute was set to. If the
    attribute has been deleted the second value is of type C_NOEXISTS
    
    The iter function should return one of:
    
    * ITER_STOP - Stop further iteration
    * ITER_RECURSE - Recurse further down the node children
    * ITER_CONTINUE - Ignore node children and continue with the node's siblings
    
    One could also define a class implementing the call function as:
    
        class DiffIterator(object):
            def __init__(self):
                self.count = 0
    
            def __call__(self, kp, op, oldv, newv):
                print('kp={0}, op={1}, oldv={2}, newv={3}'.format(
                    str(kp), str(op), str(oldv), str(newv)))
                self.count += 1
                return _confd.ITER_RECURSE
    
    Keyword arguments:
    
    * thandle -- transaction handle
    * iter -- iterator function, will be called for every diff in the transaction
    * flags -- bitmask of ITER_WANT_ATTR and ITER_WANT_P_CONTAINER

 

 

An example on how to get the modified leaf from the service modification

 

I define a  new class

 

 

OPER = {
    1: 'MOP_CREATED',
    2: 'MOP_DELETED',
    3: 'MOP_MODIFIED',
    4: 'MOP_VALUE_SET',
    5: 'MOP_MOVED_AFTER',
    6: 'MOP_ATTR_SET'
}

class DiffIterator(object):
 
    def __init__(self):
         self.count = 0
         self.changes = []
    def __call__(self, kp, op, oldv, newv):
        info = {
            "kp": str(kp),
            "op": OPER[op],
            "oldv": str(oldv),
            "newv": str(newv)
        }
        self.changes.append(info)
        self.count += 1
        return ncs.ITER_RECURSE

 

 

 

 

 

Then in the premod i did 

 

    @Service.pre_modification
    def cb_pre_modification(self, tctx, op, kp, root, proplist):
        self.log.info('Service premod(service=', kp, ')')
        self.log.info('Service premod(tctx=', tctx, ')')
        self.log.info('Service premod(op=', op, ')')
        self.log.info('Service premod(kp=', kp, ')')
        self.log.info('Service premod(proplist=', proplist, ')')
        maapi = ncs.maagic.get_maapi(root)   
        maapi.attach(tctx)
        diff = DiffIterator()
        #maapi.diff_iterate(tctx.th, self.iterate, 0)
        maapi.diff_iterate(tctx.th, diff, 0)
        self.log.info(f"Diff counts  {diff.count} Diff changes {diff.changes}")
        

 

Here the log generated when i change some leaf in my service 

 

<INFO> 01-Jun-2022::18:20:49.753 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(service=/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2})
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(tctx=_ncs.TransCtxRef : fd=9 : vfd=-1 : th=12727)
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(op=1)
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(kp=/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2})
<INFO> 01-Jun-2022::18:20:49.754 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Service premod(proplist=[])
<INFO> 01-Jun-2022::18:20:49.755 TEST_PREMOD ncs-dp-19345-TEST_PREMOD:main-2-th-12727: - Diff counts  3 Diff changes [{'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}', 'op': 'MOP_MODIFIED', 'oldv': 'None', 'newv': 'None'}, {'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}/dummy', 'op': 'MOP_VALUE_SET', 'oldv': 'None', 'newv': '45006668'}, {'kp': '/TEST_PREMOD:TEST_PREMOD{TEST_PREMOD-TEST-AUTO-2}/c', 'op': 'MOP_VALUE_SET', 'oldv': 'None', 'newv': 'trot'}]


then you can iterate through diff.changes and check kp that contains the Key path with the  node(leaf) name 

 

 

Hello @douglasfir  If it's answering your question . Can you mark it as solved ?

douglasfir
Level 1
Level 1

Hi @Nabsch ,

first of all my apologies for the late response, I was away for several weeks. I made a workaround by introducing additional read-only field called "current_parameter" in the YANG model and then compared it to "parameter" inside cb_pre_modification() in case that it is not dry_run or dry_run_reverse.

However, your solution seems much more elegant and it works great! I have just tested it and put into the service instead of my workaround.

Thanks a lot!