ConfD User Community

How to get Container as an Object using Python API


#1

Hi Martin,

Which Maagic API function should i use that would return the entire container Object when we pass container’s Xpath to it.

Regards,
Harish P


made this topic public #2

#3

[How to] return the entire container Object when we pass container’s Xpath to it

If by “Xpath” you mean the confd’s keypath, then you can do something like maagic.cd(root, kpath). If you mean true xpath, you need to use xpat_eval (e.g. trans.xpath_eval(xpath, result, None, '/')) where result is your result callback function that processes the keypath argument. For xpath_eval there already are some examples.


#4

Hi Martin,

Let me explain with the example.

container Test
{
leaf a

leaf b

leaf c
}

and i have a local structure
struct test{
int a;
int b;
int c;
}

i have subscribed to container’s absolute path.

Now , when I get notification about update of container, I want an API to read the container using absolute xpath,
and get key-value pairs of leaves in it, so I can populate them accordingly in my structure .


#5

Let’s step back for a while: the title indicates that you are using Python API, and I understand now that you want to read data in the context of a CDB subscription. Is that both true? If so, ignore pretty much everything what I have written about maagic API, this is not a good use-case for that; have a look at the very first introductory Python example instead, it does exactly what you want - examining CDB contents using cdb.get, cdb.cd and so on. It does not allow the “container as an object” approach though, this API is too low-level for that and you are on your own here.


#6

Sorry for Misleading. Thanks Martin Its clear now.


#7

Have you looked at:

get_modifications(...)
get_modifications(sock, subid, flags, path) -> list
 
The get_modifications() function can be called after reception of a
subscription notification to retrieve all the changes that caused the
subscription notification. The socket sock is the subscription socket. The
subscription id must also be provided. Optionally a path can be used to
limit what is returned further (only changes below the supplied path will
be returned), if this isn't needed path can be set to None.
 
Keyword arguments:
sock -- a previously connected CDB socket
subid -- subscription id
flags -- the flags
path -- a path in string format or None

I think, here, you can get the modified elements under your container in one call, but only the modified elements, but if you also want to get the non modified leafs, you will have to explicitly read those the way Martin suggested.


#8

Hi Nabil,

This get_modifications(sock, subid, flags, path) in python returns the below list which has only tag and namespace info which got changed. But how about the changed values ?

I am expecting the actual values of nodes got changes in a container as we get in C API.

[_confd.TagValue(tag=2049412155, ns=1946994318)]

Regards,
Harish P


#9

Here’s a cdb.get_modifications() two phase Python example you can use as a reference:

$  cat cdbl.py
from __future__ import print_function
import _confd
import _confd.cdb as cdb
import _confd.maapi as maapi

import socket
import random

ms = socket.socket()
maapi.connect(ms, '127.0.0.1', _confd.PORT)
maapi.load_schemas(ms)
ms.close

def print_modifications(mods):
    indent = 0
    for m in mods:
        tmp = ""
        ct = m.v.confd_type()
        if ct  == _confd.C_XMLBEGIN:
            tmp = "begin"
        elif ct == _confd.C_XMLBEGINDEL:
            tmp = "begin-deleted"
        elif ct == _confd.C_XMLEND:
            tmp = "end"
            indent = indent - 2
        elif ct == _confd.C_XMLTAG:
            tmp = "created"
        elif ct == _confd.C_NOEXISTS:
            tmp = "deleted"

        if tmp == "":
            print(indent * " ", _confd.hash2str(m.tag), m.v)
        else:
            print(indent * " ", m.v, tmp)
            
        if ct == _confd.C_XMLBEGIN or ct == _confd.C_XMLBEGINDEL:
            indent = indent + 2

def run():
    path = "/"
    cs = socket.socket()
    cdb.connect(cs, cdb.SUBSCRIPTION_SOCKET, '127.0.0.1', _confd.PORT)
    sid = cdb.subscribe2(cs, cdb.SUB_RUNNING_TWOPHASE, 0, 100, 0, path)
    cdb.subscribe_done(cs)

    try:
        while True:
            flags = cdb.GET_MODS_INCLUDE_LISTS
            (type, sub_flags, _) = cdb.read_subscription_socket2(cs)
            if type == cdb.SUB_COMMIT:
                mods = cdb.get_modifications(cs, sid, flags, path)
                if mods == []:
                    print('No modifications')
                else:
                    print('\n***Config updated --> Commit')
                    print_modifications(mods)
            if type == cdb.SUB_PREPARE:
                mods = cdb.get_modifications(cs, sid, flags, path)
                if mods == []:
                    print('No modifications')
                else:
                    print('\n***Config updated --> Prepare')
                    r = random.randrange(0,2)
                    if r == 1:
                        print('You are out of luck, random resource denied ' + str(r))
                        cdb.sub_abort_trans(cs, 1, 0, 0, 'You are out of random luck ' + str(r))
                        continue
                    print('Your are in luck ' + str(r))
                    print_modifications(mods)
            if type == cdb.SUB_ABORT:
                flags |= cdb.GET_MODS_REVERSE
                mods = cdb.get_modifications(cs, sid, flags, path)
                if mods == []:
                    print('No modifications')
                else:
                    print('\n***Config aborted')
                    print_modifications(mods)
            cdb.sync_subscription_socket(cs, cdb.DONE_PRIORITY)
    except KeyboardInterrupt:
        print("Got interrupt")
    finally:
        cdb.end_session(cs)
        cs.close()

if __name__ == "__main__":
    run()


#10

Hi Conny,

Is there a Python API to find a node is leaf or container by passing its Xpath?.
For example : is_leaf(xpath of leaf node)

Regards,
Harish P (Altiostar)


#11

I suggest you create a new topic for questions unrelated to this topic.