cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2691
Views
10
Helpful
11
Replies

Pushing the hole configuration of an element in python action

igotni
Level 1
Level 1

Hi everyone,

 

I have to retieve configuration from a device and push it to another device in a python action :

So I used the mappi library in writing mode :

with ncs.maapi.Maapi() as m:
   with ncs.maapi.Session(m, 'admin', 'python'):
     with m.start_write_trans() as t:
       root = ncs.maagic.get_root(t)
then I retrieved port confiiguration from device1 :
port_1 = root.devices.device[_input.device1].config.alu__port['2/3/14']
 
and finnaly I tried to push the port configuration of device 1 to another device 2 :
 
root.devices.device[_input.device2].config.alu__port['2/2/2'] = port_1
 
But unfortunately , I had the following error :
Must use create() method to create list items
 
Do you have any idea to resolve this problem ?
Do you have examples how to push hole configuration of an element in python action ?
 
PS : Pushing element by elemnt works fine (see the example below)
root.devices.device[_input.device1].config.alu__port[2/2/2].description = port_1.description
But the goal of my post is to push the hole port configuration
 
Thanks in advance.
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 Accepted Solution

Accepted Solutions

You can find it documented in the $INSTALL_DIR/doc/api/python/_ncs.maapi.html.

There are no examples for python though. This is the definition:

copy_tree(sock, thandle, frompath, topath) -> None

sock will be handled when calling the function on existing maapi session, thandle is the transaction handler of type int, you can get it from the th attribute of your transaction, frompath and topath will be string values in the format of keypath.

So for these 2 values you either construct a string as in the example I posted previously, or you can get the keypath out of the Node object using _path attribute. E.g.

with ncs.maapi.Maapi() as m:
        with ncs.maapi.Session(m, 'admin', 'python'):
            with m.start_write_trans() as t:
                root = ncs.maagic.get_root(t)
                port_1 = root.devices.device[_input.device1].config.alu__port['2/3/14']
                port_2 = root.devices.device[_input.device2].config.alu__port['2/2/2']
                
                m.copy_tree(t.th, port_1._path, port_2._path)
                t.apply()

I tried it out and it works, on my machine :)

 

 

View solution in original post

11 Replies 11

sspehar
Level 1
Level 1

Hi,

 

the error you got is telling you that the ListElement with key value 2/2/2 that you're referencing, doesn't exist in the CDB.

You could go and create it beforehand with create() method

root.devices.device[_input.device1].config.alu__port[2/2/2].create()

and then you could use it the way you tried without receiving that error because now the resource will exist. But this unfotunately will not copy all the values from port1 to port2 as you might think. You would have to go through all elements on the first interface and apply them to the second E.g. port2.ip = port1.ip etc.

Luckily there is an easier way to copy entire subtree of a Node with the copy_tree() method

with ncs.maapi.Maapi() as m:
with ncs.maapi.Session(m, 'admin', 'python'): with m.start_write_trans() as t: port1 = "/devices/device{{0}}/config/alu:port{{1}}".format(_input.device1, "2/3/14")
port2 = "/devices/device{{0}}/config/alu:port{{1}}".format(_input.device1, "2/2/2") m.copy_tree(t.th, port1, port2) t.apply()

As you see you have to use keypath strings as arguments from where to where you want to copy, so there will be some string manipulation. But there might even be an option to get keypath out of the Node object if necessary :)

 

Hope it helps!

 

thanks sspehar for your reply.

 

In fact the key value 2/2/2 exist in the CDB.

 

I tried the solution that you suggested (the copy_tree() method), but unfortunately when I applied it, any changes had ocuured to the CDB (the configuration of port 2 had not changed).

2 things come to my mind, maybe the keypath string is not correct, try printing it out and examine if it's correct, or the transaction wasn't applied E.g. t.apply() ?

The transaction is applied, I will verify the keypath string.

Two things that I see in your code snippets:

 

1. You mention "device 2", but your code seems to point to "device 1" in both to and from line.

 

2. The IDs that you're using for the ports. I imagine those need to be strings. In your code, it seems to me that they might be numbers (1/1/1 [=1?], should be '1/1/1'). Might it be that this makes your code try and copy the data to another path than the one you expect?

Thanks yfherzoa for your reply,

My code respect this two things that you mentioned, sorry for the error in the post.

Yes exactly i want to copy data from one path (device1) to another path (device2)

 

 

 

 

In the documentation, I foundd that the source path of copy_tree() method should be formatted, Do you have any example to do this ?

 

Documentation bellow :

int maapi_copy_tree(int sock, int thandle, const char *from, const char *tofmt, ...);

 

This function copies the entire configuration tree rooted at from to tofmt. List entries are created accordingly. If the destination already exists, from is copied on top of the destination. This function is typically used inside actions where we for example could use maapi_copy_tree() to copy a template configuration into a new list entry. The from path must be pre-formatted, e.g. using confd_format_keypath(), whereas the destination path is formatted by this function.

You can find it documented in the $INSTALL_DIR/doc/api/python/_ncs.maapi.html.

There are no examples for python though. This is the definition:

copy_tree(sock, thandle, frompath, topath) -> None

sock will be handled when calling the function on existing maapi session, thandle is the transaction handler of type int, you can get it from the th attribute of your transaction, frompath and topath will be string values in the format of keypath.

So for these 2 values you either construct a string as in the example I posted previously, or you can get the keypath out of the Node object using _path attribute. E.g.

with ncs.maapi.Maapi() as m:
        with ncs.maapi.Session(m, 'admin', 'python'):
            with m.start_write_trans() as t:
                root = ncs.maagic.get_root(t)
                port_1 = root.devices.device[_input.device1].config.alu__port['2/3/14']
                port_2 = root.devices.device[_input.device2].config.alu__port['2/2/2']
                
                m.copy_tree(t.th, port_1._path, port_2._path)
                t.apply()

I tried it out and it works, on my machine :)

 

 

Thanks for your reply

I got the following error when testing the same example :

Error: badly formatted or nonexistent path (8): Data model mismatch

@sspehar I liked the easy way of coping but my second XPath does not exist due to its new entry. do I need to call the following code before XPath

root.devices.device[_input.device1].config.alu__port[2/2/2].create()

code:

with ncs.maapi.Maapi() as m:
    with ncs.maapi.Session(m, tctx.username, tctx.context):
        with m.start_write_trans() as t:
            root = ncs.maagic.get_root(t)
            root.devices.device[each_vlan.neighbor_name].config.junos__configuration.protocols.l2circuit.neighbor[target_device_ipv4].create()
            neighbor1 = "/devices/device{{0}}/config/junos:configuration/protocols/l2circuit/neighbor{{1}}".format(each_vlan.neighbor_name, source_device_ipv4)
            neighbor2 = "/devices/device{{0}}/config/junos:configuration/protocols/l2circuit/neighbor{{1}}".format(each_vlan.neighbor_name, target_device_ipv4)
            m.copy_tree(t.th, neighbor1, neighbor2)
            t.apply()

In my case it's 

root.devices.device[each_vlan.neighbor_name].config.junos__configuration.protocols.l2circuit.neighbor[target_device_ipv4].create()

I am getting key error on neighbor2

KeyError: '{10.0.0.1} not in /ncs:devices/device{juniper-pe20}/config/junos:configuration/protocols/l2circuit/neighbor'

To test I have given existing neigbor2 key then, error on create

AttributeError: 'ListElement' object has no attribute 'create'

When I commented on create part of the existing neighbor2 then error on badly formated or nonexisting path 

<ERROR> 23-Mar-2020::10:14:57.876 vpws-migration ncs-dp-15537-vpws-migration:main-1-th-28744: - badly formatted or nonexistent path (8):
<ERROR> 23-Mar-2020::10:14:57.877 vpws-migration ncs-dp-15537-vpws-migration:main-1-th-28744: - Traceback (most recent call last):
  File "/opt/ncs/ncs-5.3.0.1/src/ncs/pyapi/ncs/application.py", line 401, in wrapper
    pl = fn(self, tctx, root, service, proplist)
  File "/var/opt/ncs/state/packages-in-use/1/vpws-migration/python/vpws_migration/main.py", line 88, in cb_create
    m.copy_tree(t.th, neighbor1, neighbor2)
  File "/opt/ncs/ncs-5.3.0.1/src/ncs/pyapi/ncs/maapi.py", line 273, in proxy
    return real(self2.msock, *args, **kwargs)
_ncs.error.Error: badly formatted or nonexistent path (8):

You need to run create on the list, rather than on the list element and provide the element key(s) as create() args.

 

new_entry = my_list.create(new_entry_key)