cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
855
Views
0
Helpful
4
Replies

Conditionally referencing different object trees from the same object name

rslaski
Spotlight
Spotlight

Hello developers,

 

I'm coming back with the old problem of referencing different types of interfaces (ex. 'Ethernet' and 'GigabitEthernet' on devices. However in my current deployment I have the same interface type ('Ethernet') on different device types, served by different NEDs (Cisco Nexus and Arista, in my case), and for both I would like to get a list of available Ethernet interfaces.

 

So, if we apply the same type of solution as usually posted here (choice + condition), we end up with somethink like that:

 

 

container interface {
    tailf:cli-add-mode;

    choice choice_interface {
        case nexus {
            leaf-list NX_Ethernet {
                when "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:module[1]/ncs:name='tailf-ned-cisco-nx'";
                tailf:cli-list-syntax;
                type leafref {
                    path "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:config/nx:interface/nx:Ethernet/nx:name";
                }
            }
        }
        case arista {
            leaf-list AR_Ethernet {
                when "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:module[1]/ncs:name='tailf-ned-arista-dcs'";
                tailf:cli-list-syntax;
                type leafref {
                    path "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:config/dcs:interface/dcs:Ethernet/dcs:name";
                }
            } 
        }
    }
}

The code works pretty fine, exept the fact the interface names ('AR_Ethernet' and 'NX_Ethernet') do not reflect real interface names (which is 'Ethernet' in both cases), because we can't have the same object name at the same hierarchy level:

 

 

TMPL
 AC RSL_t4
  dc 20900
   ports
    access-leaf AR_LEAF131
     interface
      AR_Ethernet 3
     !
    !
   !
  !
  dc 24246
   ports
    access-leaf NX_LEAF111
     interface
      NX_Ethernet 1/1
     !
    !
   !
  !
 !
!

So another solution came to me: add another container hierarchy level, hide those objects with 'tailf:cli-drop-node-name', and insert 'Ethernet' leaf-lists below:

 

 

container interface {

    choice choice_interface {
        case nexus {
            container NX_Ethernet {
                tailf:cli-drop-node-name;
                when "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:module[1]/ncs:name='tailf-ned-cisco-nx'";
                leaf-list Ethernet {
                    tailf:cli-list-syntax;
                    type leafref {
                        path "/ncs:devices/ncs:device[ncs:name=current()/../../../node]/ncs:config/nx:interface/nx:Ethernet/nx:name";
                    }
                }
            }
        }
        case arista {
            container AR_Ethernet {
                tailf:cli-drop-node-name;
                when "/ncs:devices/ncs:device[ncs:name=current()/../../node]/ncs:module[1]/ncs:name='tailf-ned-arista-dcs'";
                leaf-list Ethernet {
                    tailf:cli-list-syntax;
                    type leafref {
                        path "/ncs:devices/ncs:device[ncs:name=current()/../../../node]/ncs:config/dcs:interface/dcs:Ethernet/dcs:name";
                    }
                }
            } 
        }
    }
}

This one allows to configure objects in a desired way (by just referencing 'interface Ethernet xxx' in both cases):

 

 

rslaski@ncs(config)# show conf
TMPL
 AC RSL_t4
  dc 20900
   ports
    access-leaf AR_LEAF131
     interface Ethernet 3
    !
   !
  !
  dc 24246
   ports
    access-leaf NX_LEAF111
     interface Ethernet 1/1
    !
   !
  !
 !
!

However inside the xpath we have those intermediate objects ('AR_Ethernet', and 'NX_Ethernet') visible, so I have to change a lot with all the code I have written so far:

rslaski@ncs(config)# show full-configuration TMPL AC RSL_t4 | display xpath 
/TMPL/AC[name='RSL_t4']/dc[dc-id='20900']/ports/access-leaf[node='AR_LEAF131']/interface/AR_Ethernet/Ethernet [ 3 ]
/TMPL/AC[name='RSL_t4']/dc[dc-id='24246']/ports/access-leaf[node='NX_LEAF111']/interface/NX_Ethernet/Ethernet [ 1/1 ]

So my question: is there another, more elegant solution to this problem?

 

thanks,
robert

 

 

4 Replies 4

rslaski
Spotlight
Spotlight
No ideas, guys?

No super good ideas.

 

One thing that might be interesting, if you use a lot of xpath, is the | operator that joins two node-sets - so if you have two alternatives you can merge them together. Depending on what you do that may simplify your logic.

mvolf
Cisco Employee
Cisco Employee

You may try to move your restriction deeper into the leaf-list. One option may be to make the leaf-list type a union of leafrefs; but that requires YANG 1.1 plus I am not sure how much it is supported by NSO.

Another option, if you are willing to give up leafref, is to type the leaf-list as plain string and then validate it; for validation you can use a bit complex must statement like

      leaf-list interface {
        type string;
        must "deref(../node)/../ncs:config/nx:interface/nx:Ethernet[nx:name = current()]" +
          "or deref(../node)/../ncs:config/dcs:interface/dcs:Ethernet[dcs:name = current()]";
      }

I’m not sure about the performance though, especially if the leaf-list may have many instances. If that becomes a problem, you may resort to custom validation callbacks.

@mvolf
Unfortunately, leafref inside union cannot be used with NSO 5.2:
yang/TMPL.yang:590: error: the type leafref (defined at yang/TMPL.yang:590) cannot be part of a union
yang/TMPL.yang:593: error: the type leafref (defined at yang/TMPL.yang:593) cannot be part of a union

The second option is tempting, however we loose all nice helpers displaying list of available interfaces.

As for now, the solution with additional container level hidden with 'tailf:cli-drop-node-name' seems to be the most convenient for us.

thanks,