12-04-2019 09:07 AM
I need to populate a template with a list of data in teh XML-template. I know How to do when apply the yang to the XML as in this case
YANG DEFINTION
...
augment /ncs:services {
list LF3 {
description "Provo la lisa di policy";
...
leaf-list nbarCat {
type enumeration {
...
XML TEMPLATE
<category>
<category-type>{/nbarCat}</category-type>
</category>
I'd like to use a variable to be manipulated in my Pyton code. I tried to use a list but it seems it does not work. How can I do?
Solved! Go to Solution.
12-04-2019 10:25 PM
Hi,
In most cases, if you want to manipulate the list elements in python, you'd then have to apply the template for each list element (the template engine doesn't process python objects in the same way it processes data model references)
Something like:
for entry in service.nbarCat: vars.add('FOO', foo(entry)) template.apply('my-template', vars)
<category> <category-type>{$FOO}</category-type> </category>
Hope that answers your question!
02-02-2020 12:41 AM
You can use multiple templates.
Have your list-related configs in one template, which you apply iteratively, and have your other configs on a separate template which you apply only once.
(In most cases, applying the same configs over and over again as part of the same service should not generate any issues)
12-04-2019 10:25 PM
Hi,
In most cases, if you want to manipulate the list elements in python, you'd then have to apply the template for each list element (the template engine doesn't process python objects in the same way it processes data model references)
Something like:
for entry in service.nbarCat: vars.add('FOO', foo(entry)) template.apply('my-template', vars)
<category> <category-type>{$FOO}</category-type> </category>
Hope that answers your question!
01-31-2020 11:48 PM
Hi,
Sorry for posting to such an old thread, but what I have a similar case to this one, but I think my question is quite related to this one.
Like the OP, I want to manipulate elements of a list in python, but in the same service I use variables that are not part of a list. Applying the template in each loop iteration, messes all my service.
What should I do in these cases?
02-02-2020 12:41 AM
You can use multiple templates.
Have your list-related configs in one template, which you apply iteratively, and have your other configs on a separate template which you apply only once.
(In most cases, applying the same configs over and over again as part of the same service should not generate any issues)
02-02-2020 10:31 AM
Thanks for your reply. After struggling for several hours I think the problem is not related to what I thought.
I have the following yang (simplified):
list cr-art { key DEVICE; leaf DEVICE { ... } list ROUTER_VECINO { key NOMBRE; leaf NOMBRE { ... } list INT_AGREGADO_CONEXION { key NOMBRE_INT_AGREGADO; leaf NOMBRE_INT_AGREGADO { ... } list PUERTO_LOCAL { key NOMBRE; leaf NOMBRE { ... } leaf PUERTO_REMOTO { ... } } } } }
The template has a part where I have to fill the variable $MIN_LINKS with some python calculations.
<interface> <name>{/ROUTER_VECINO/INT_AGREGADO_CONEXION/NOMBRE_INT_AGREGADO}</name> <description>Conexion con {../NOMBRE} {INT_AGREGADO_REMOTO}</description> <minimum-links>{$MIN_LINKS}</minimum-links> |
The python code is similar to this:
for rv in service.ROUTER_VECINO:
for iac in rv.INT_AGREGADO_CONEXION:
num_puertos=len(iac.PUERTO_LOCAL)
vars.add('MIN_LINKS',min_links)
template.apply('cr-art-template',vars)
But this always returns MIN_LINKS as the number of the last aggregated interface that the code processes. That is logical, since the 'for' statements go through all the aggregated interfaces, not the one that is being processed at that moment in the template. It would be easy if somehow I could access the value of the current aggregated interface being processed each time, but nothing like the following seem to work (I get errors like "Error: Python cb_create error. 'List' object has no attribute 'NOMBRE'"):
service.ROUTER_VECINO.NOMBRE
service.ROUTER_VECINO[NOMBRE]
...
Any hint?
Thanks.
Fran
02-02-2020 11:03 AM
So in the loop you can do rv.NOMBRE and iac.NOMBRE_INT_AGREGADO, since that points to the current instance.
02-02-2020 12:17 PM
I throws an error if I add the following print statement to the code:
for rv in service.ROUTER_VECINO:
print(rv.NOMBRE)
for iac in rv.INT_AGREGADO_CONEXION:
...
admin@ncs(config-cr-art-artfran1-01)# re-deploy Error: Python cb_create error. 'List' object has no attribute 'NOMBRE'
02-02-2020 12:47 PM
I must be misunderstanding the model or the code, because rv shouldn't be a list. Try printing rv._path, and try making sure in the logs that it isn't some other line giving you the error.
02-02-2020 12:55 PM - edited 02-02-2020 11:19 PM
Sorry, you are correct, it was another line which was triggering the error.
However, it looks like in the loop, rv.NOMBRE is not pointing to the current instance. Instead, the for loop goes through all instances of the service.
The service config looks like this:
cr-art artfran1-01 ROUTER_VECINO Prueba INT_AGREGADO_CONEXION ae1 PUERTO_LOCAL ge-0/0/2 PUERTO_LOCAL ge-0/0/3 ROUTER_VECINO artlaur1-01 INT_AGREGADO_CONEXION ae3 PUERTO_LOCAL ge-0/0/5
I have put some print statements in the code:
for rv in service.ROUTER_VECINO: print(rv.NOMBRE) for iac in rv.INT_AGREGADO_CONEXION: num_puertos=len(iac.PUERTO_LOCAL) print(num_puertos)
What I get in the logs is:
<INFO> 2-Feb-2020::21:43:44.882 cisco ncs[3724]: cr-art :: Prueba <INFO> 2-Feb-2020::21:43:44.883 cisco ncs[3724]: cr-art :: 2 <INFO> 2-Feb-2020::21:43:45.149 cisco ncs[3724]: cr-art :: artlaur1-01 <INFO> 2-Feb-2020::21:43:45.151 cisco ncs[3724]: cr-art :: 1
That is correct, but when I look at the config of the router artfran1-01, the value for MIN_LINKS is "1" for both aggregated interfaces.
What can I do to have "2" for ae1 and "1" fora ae3?
02-03-2020 06:25 AM
I'm still struggling with this. I have divided the original template into two different templates. The debug shows that the second template is being applied twice, but I do not quite understand the results. First calculation for MIN_LINKS results in "2" for both aggregate interfaces, even though the second aggregate only has one port. The second pass returns MIN_LINKS="1" for both aggregates, although the first aggregate only has one port.
2020-02-03T15:12:58.070 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae3']/NOMBRE_INT_AGREGADO 2020-02-03T15:12:58.070 xpath: template agregados-template: result: 2 nodes [0.001 sec] 2020-02-03T15:12:58.070 xpath: template agregados-template: evaluating: ../NOMBRE 2020-02-03T15:12:58.071 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='Prueba']/NOMBRE 2020-02-03T15:12:58.071 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.071 xpath: template agregados-template: evaluating: INT_AGREGADO_REMOTO 2020-02-03T15:12:58.071 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='Prueba']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae1']/INT_AGREGADO_REMOTO: ae2 2020-02-03T15:12:58.071 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.072 xpath: template agregados-template: evaluating: string($MIN_LINKS) 2020-02-03T15:12:58.072 xpath: template agregados-template: result: 2 [0.000 sec] 2020-02-03T15:12:58.073 xpath: template agregados-template: evaluating: ../NOMBRE 2020-02-03T15:12:58.073 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/NOMBRE 2020-02-03T15:12:58.073 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.073 xpath: template agregados-template: evaluating: INT_AGREGADO_REMOTO 2020-02-03T15:12:58.073 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae3']/INT_AGREGADO_REMOTO: ae1 2020-02-03T15:12:58.074 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.074 xpath: template agregados-template: evaluating: string($MIN_LINKS) 2020-02-03T15:12:58.074 xpath: template agregados-template: result: 2 [0.000 sec] 2020-02-03T15:12:58.079 xpath: template agregados-template: evaluating: /DEVICE 2020-02-03T15:12:58.079 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/DEVICE 2020-02-03T15:12:58.080 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.081 xpath: template agregados-template: evaluating: ROUTER_VECINO/INT_AGREGADO_CONEXION/NOMBRE_INT_AGREGADO 2020-02-03T15:12:58.081 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='Prueba']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae1']/NOMBRE_INT_AGREGADO 2020-02-03T15:12:58.082 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae3']/NOMBRE_INT_AGREGADO 2020-02-03T15:12:58.082 xpath: template agregados-template: result: 2 nodes [0.001 sec] 2020-02-03T15:12:58.082 xpath: template agregados-template: evaluating: ../NOMBRE 2020-02-03T15:12:58.082 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='Prueba']/NOMBRE 2020-02-03T15:12:58.083 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.083 xpath: template agregados-template: evaluating: INT_AGREGADO_REMOTO 2020-02-03T15:12:58.083 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='Prueba']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae1']/INT_AGREGADO_REMOTO: ae2 2020-02-03T15:12:58.083 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.084 xpath: template agregados-template: evaluating: string($MIN_LINKS) 2020-02-03T15:12:58.084 xpath: template agregados-template: result: 1 [0.000 sec] 2020-02-03T15:12:58.084 xpath: template agregados-template: evaluating: ../NOMBRE 2020-02-03T15:12:58.085 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/NOMBRE 2020-02-03T15:12:58.085 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.085 xpath: template agregados-template: evaluating: INT_AGREGADO_REMOTO 2020-02-03T15:12:58.085 xpath: template agregados-template: match: /cr-art[DEVICE='artfran1-01']/ROUTER_VECINO[NOMBRE='artlaur1-01']/INT_AGREGADO_CONEXION[NOMBRE_INT_AGREGADO='ae3']/INT_AGREGADO_REMOTO: ae1 2020-02-03T15:12:58.085 xpath: template agregados-template: result: one node [0.000 sec] 2020-02-03T15:12:58.086 xpath: template agregados-template: evaluating: string($MIN_LINKS) 2020-02-03T15:12:58.086 xpath: template agregados-template: result: 1 [0.000 sec]
This is driving me crazy. Any hint would be greatly appreciated.
02-03-2020 11:02 PM
Can you post the template for which you see unexpected debug output?
One thing to have in mind is that the template engine supports some sort of iteration capability as well.
If your template contains path to lists in your service model, then NSO will iterate the list entries and apply the same structure of the XML for each entry. Looking at XML snippets you shared earlier, I suspect that might be happening.
02-03-2020 11:29 PM - edited 02-03-2020 11:30 PM
This is the relevant piece of the template:
<interface> <name>{/ROUTER_VECINO/INT_AGREGADO_CONEXION/NOMBRE_INT_AGREGADO}</name> <description>Conexion con {../NOMBRE} {INT_AGREGADO_REMOTO}</description> <aggregated-ether-options> <minimum-links>{$MIN_LINKS}</minimum-links> </aggregated-ether-options> <unit> <name>0</name> <family> <inet> <address> <name>{IP-MASK}</name> </address> </inet> </family> </unit> </interface>
02-04-2020 12:23 AM
ok.
So, both ROUTER_VECINO and INT_AGREGADO_CONEXION, so your XML template is also doing some sort of iteration on those lists.
I'd say, try to limit your logic to iterate either on python or on XML.
Suppose that you go with python here, have your python code fetch the values of NOMBRE_INT_AGREGADO, NOMBRE, INT_AGREGADO_REMOTO and IP-MASK and populate them in template variables.
02-04-2020 01:02 AM
I have explored the other way, the template one, and it works!!
Just in case it might help someone, this is my template:
<interfaces> <interface> <name>{/ROUTER_VECINO/INT_AGREGADO_CONEXION/NOMBRE_INT_AGREGADO}</name> <description>Conexion con {../NOMBRE} {INT_AGREGADO_REMOTO}</description> <aggregated-ether-options> <?if {contains(OPCIONES,'ROBUSTO')}?> <minimum-links>{count(PUERTO_LOCAL)}</minimum-links> <?else?> <minimum-links>{ceiling(count(PUERTO_LOCAL) div 2)}</minimum-links> <?end?> </aggregated-ether-options> </interface> </interfaces>
If I have time, I will also try the python approach later.
Thanks again for your help.
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