09-11-2023 09:21 AM
Here is my yang module:
module pydp {
namespace "http://tail-f.com/ns/example/pydp";
prefix pydp; yang-version 1.1;
import tailf-common {prefix tailf;}
import ietf-inet-types {prefix inet;}
list cont {
key name;
leaf name { type string; }
container brief {
tailf:callpoint mydp-cp-brief;
config false;
leaf status { type string; }
leaf up-time { type string; }
}
container capabilities {
tailf:callpoint mydp-cp-cap;
config false;
leaf test { type string; }
}
}
}
and my python:
import ncs
import _ncs
from ncs.experimental import DataCallbacks
def dcb_start(state):
dcb = DataCallbacks(state.log)
dcb.register('/mydp:cont', Handler())
_ncs.dp.register_data_cb(state.ctx, 'mydp-cp-brief', dcb)
_ncs.dp.register_data_cb(state.ctx, 'mydp-cp-cap', dcb)
return state
def dcb_stop(start_state):
pass
class Handler(object):
def get_object(self, tctx, kp, args):
cont_name = args.get("cont")
with ncs.maapi.single_read_trans(tctx.uinfo.username, "passwd") as t:
root = ncs.maagic.get_root(t)
key = root.cont[device_name]
....
return {
"brief": { 'status': 'value', 'up-time': 'value' }
}
def get_next(self, tctx, kp, args, next):
return None
def count(self):
return 0
class Main(ncs.application.Application):
def setup(self):
...
self.register_fun(dcb_start, dcb_stop)
def teardown(self):
pass
I was hoping when get_object() in Handler class gets called, I can use kp to differentiate if it's for brief container or capabilities, however, the kp was always /mydp:cont when I did "show cont brief" and "show cont capabilities".
Now I wonder if it is possible to register multiple callpoints with same DataCallbacks instance.
Solved! Go to Solution.
09-12-2023 12:27 AM
The low lever _ncs.X Python API documentation is not well documented. As a general comment i would recommend you to consult the c manual pages for the equivalent API functions https://developer.cisco.com/docs/nso/guides/#!ncs-man-pages-volume-3. The manpage states:
get_object()
...
The purpose of the callback is to return an entire object, i.e. a list entry, in one swoop. If the callback is not implemented, NSO will retrieve the whole object through a series of calls to get_elem().
...
By default, the callback will only be called for list entries - i.e. get_elem()
is still needed for leafs that are not defined in a list, but if there are no such leafs in the part of the data model covered by a given callpoint, the get_elem()
callback may be omitted when get_object()
is registered. This has the drawback that NSO will have to invoke get_object() even if only a single leaf in a list entry is needed though, e.g. for the existence test mentioned for get_elem()
.
However, if the CONFD_DAEMON_FLAG_BULK_GET_CONTAINER
flag is set via confd_set_daemon_flags()
, get_object()
will also be used for the toplevel ancestor container (if any) when no ancestor list node exists. I.e. in this case, get_elem()
is only needed for toplevel leafs - if there are any such leafs in the part of the data model covered by a given callpoint.
...
So try to set the _ncs.dp.DAEMON_FLAG_BULK_GET_CONTAINER flag to verify that your get_object() will be invoked.
-Tommy
09-12-2023 12:27 AM
The low lever _ncs.X Python API documentation is not well documented. As a general comment i would recommend you to consult the c manual pages for the equivalent API functions https://developer.cisco.com/docs/nso/guides/#!ncs-man-pages-volume-3. The manpage states:
get_object()
...
The purpose of the callback is to return an entire object, i.e. a list entry, in one swoop. If the callback is not implemented, NSO will retrieve the whole object through a series of calls to get_elem().
...
By default, the callback will only be called for list entries - i.e. get_elem()
is still needed for leafs that are not defined in a list, but if there are no such leafs in the part of the data model covered by a given callpoint, the get_elem()
callback may be omitted when get_object()
is registered. This has the drawback that NSO will have to invoke get_object() even if only a single leaf in a list entry is needed though, e.g. for the existence test mentioned for get_elem()
.
However, if the CONFD_DAEMON_FLAG_BULK_GET_CONTAINER
flag is set via confd_set_daemon_flags()
, get_object()
will also be used for the toplevel ancestor container (if any) when no ancestor list node exists. I.e. in this case, get_elem()
is only needed for toplevel leafs - if there are any such leafs in the part of the data model covered by a given callpoint.
...
So try to set the _ncs.dp.DAEMON_FLAG_BULK_GET_CONTAINER flag to verify that your get_object() will be invoked.
-Tommy
09-13-2023 07:15 AM
Thanks for the clarification. Really hope Cisco can update the Python API documentation.
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