05-31-2022 02:15 PM
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
Solved! Go to Solution.
06-01-2022 09:22 AM - edited 06-01-2022 10:26 AM
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
06-16-2022 06:57 PM
Hello @douglasfir If it's answering your question . Can you mark it as solved ?
06-01-2022 09:22 AM - edited 06-01-2022 10:26 AM
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
06-16-2022 06:57 PM
Hello @douglasfir If it's answering your question . Can you mark it as solved ?
07-13-2022 08:54 AM
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!
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide