cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1563
Views
10
Helpful
3
Replies

Issue with XML Template not applying configuration to the Device I select

Andrew Melsom
Level 1
Level 1

Hi All

 

New to NSO so please forgive me.

 

I have run into this issue multiple times and understand I am doing something wrong, and not understanding the logic behind this.

 

Whenever I want to apply a configuration to multiple devices and that configuration differs, It will try and concatenate both configurations to both devices.

 

In this ecample I have configured a simple L2VPN service that should add the interface "GIgabitEthernet0/0/0/2" to XR1 and "GIgabitEthernet0/0/0/3" to XR7, but as you can see it trys to add it to both devices.

 

admin@ncs(config-device-XR7-Poole)# commit dry-run outformat native 
native {
    device {
        name XR1-Edingborough
        data l2vpn
              xconnect group APPLE
               p2p 200
                interface gigabitethernet0/0/0/2
                interface gigabitethernet0/0/0/3
                neighbor evpn evi 200 target 1 source 1
                 !
               exit
              exit
             exit
    }
    device {
        name XR7-Poole
        data l2vpn
              xconnect group APPLE
               p2p 200
                interface gigabitethernet0/0/0/2
                interface gigabitethernet0/0/0/3
                neighbor evpn evi 200 target 1 source 1
                 !
               exit
              exit
             exit
    }
}

Yang Model

module l2vpn {

  namespace "http://example.com/l2vpn";
  prefix l2vpn;

  import ietf-inet-types {
    prefix inet;
  }
  import tailf-common {
    prefix tailf;
  }
  import tailf-ncs {
    prefix ncs;
  }

  description
    "L2VPN Service";

  revision 2020-01-05 {
    description
      "Initial revision.";
  }

  list l2vpn {
    description "This is a L2VPN EVPN Service";

    key customer;
    leaf customer {
      type string;
    }

    uses ncs:service-data;
    ncs:servicepoint l2vpn-servicepoint;

    list device {
      key device;

      leaf device {
      type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
        }      
      }

      leaf circuit {
        type string;
      }

      leaf evi {
        type string;
      }

      leaf ac-interface-name {
        type string;
      }
    }      
  }
}

XML Template

<config-template xmlns="http://tail-f.com/ns/config/1.0">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <name>{/device}</name>
        <config>        
          <l2vpn xmlns="http://tail-f.com/ned/cisco-ios-xr" tags="merge">
            <xconnect>
              <group>
                <name>{/customer}</name>
                <p2p>
                  <name>{/device/circuit}</name>
                  <interface>
                    <name>{/device/ac-interface-name}</name>
                  </interface>
                  <neighbor-evpn>
                    <neighbor>
                      <evpn>
                        <evi>{/device/evi}</evi>
                        <target>1</target>
                        <source>1</source>
                      </evpn>
                    </neighbor>
                  </neighbor-evpn>
                </p2p>
              </group>
            </xconnect>
          </l2vpn>
        </config>
    </device>
  </devices>
</config-template>

Any help would be greatly appreciated, and if anyone knows any good training resources that could help me with this would be amazing.

 

Thanks

1 Accepted Solution

Accepted Solutions

Andrew Melsom
Level 1
Level 1

Thanks for the comments, I have resolved this by adding Python logic to my service and utilising a for loop to iterate through each device.

 

        circ = service.circuits
        
        for c in circ:
            circuit = c.circuitid
            evi = c.evi
            devices = c.nodes

            vars = ncs.template.Variables()    

            vars.add('EVI', evi)
            vars.add('CIRCUIT', circuit)

            for device in devices:
                device_name = device.name
                interface = device.interface
                vlan = device.vlan
                disjointgroup = device.disjointgroup
                ip_loopback = self.get_loopback(root, service, device_name, 0)
                remote_ip_loopback = self.get_remote_loopback(root, service, device_name, devices)

                for remote_name, remote_ip in remote_ip_loopback.items():
                    vars.add('REMOTELOOPBACK', remote_ip)

                vars.add('CUSTOMER_NAME', service_name)
                vars.add('DEVICE_NAME', device_name)
                vars.add('INTERFACE', interface)
                vars.add('LOOPBACKIP', ip_loopback)
                vars.add('VLAN', vlan)
                vars.add('DISJOINTGROUP', disjointgroup)

View solution in original post

3 Replies 3

rogaglia
Cisco Employee
Cisco Employee

hi,

 

Two tips:

1) When you do a commit dry-run or a re-deploy dry-run, use the "debug template" option to see exactly what NSO is doing:

admin@ncs(config-device-XR7-Poole)# commit dry-run outformat native  | debug template

2) I believe your problem is that you are mixing absolute and relative paths. When you are expressing:

<name>{/device/circuit}</name>

To which device do you refer? Probably what you want to do is to refer to the circuit for "this device":

<name>{./circuit}</name>

 

3) What I mentioned in 2) may not work for you because you already changed the context when  setting the customer name.

A probable solution woudl be

 

<config-template xmlns="http://tail-f.com/ns/config/1.0">
<?set CUSTOMER={/customer}?> <devices xmlns="http://tail-f.com/ns/ncs"> <device> <name>{/device}</name> <config> <l2vpn xmlns="http://tail-f.com/ned/cisco-ios-xr" tags="merge"> <xconnect> <group> <name>{$CUSTOMER}</name> <p2p> <name>{circuit}</name> <interface> <name>{ac-interface-name}</name> </interface> <neighbor-evpn> <neighbor> <evpn> <evi>{evi}</evi> <target>1</target> <source>1</source> </evpn> </neighbor> </neighbor-evpn> </p2p> </group> </xconnect> </l2vpn> </config> </device> </devices> </config-template>

 

RichardD2
Level 1
Level 1

Hey Andrew,

A new NSO learning lab was released last month, its a good first step: Learn NSO the Easy Way

regards

Richard

Andrew Melsom
Level 1
Level 1

Thanks for the comments, I have resolved this by adding Python logic to my service and utilising a for loop to iterate through each device.

 

        circ = service.circuits
        
        for c in circ:
            circuit = c.circuitid
            evi = c.evi
            devices = c.nodes

            vars = ncs.template.Variables()    

            vars.add('EVI', evi)
            vars.add('CIRCUIT', circuit)

            for device in devices:
                device_name = device.name
                interface = device.interface
                vlan = device.vlan
                disjointgroup = device.disjointgroup
                ip_loopback = self.get_loopback(root, service, device_name, 0)
                remote_ip_loopback = self.get_remote_loopback(root, service, device_name, devices)

                for remote_name, remote_ip in remote_ip_loopback.items():
                    vars.add('REMOTELOOPBACK', remote_ip)

                vars.add('CUSTOMER_NAME', service_name)
                vars.add('DEVICE_NAME', device_name)
                vars.add('INTERFACE', interface)
                vars.add('LOOPBACKIP', ip_loopback)
                vars.add('VLAN', vlan)
                vars.add('DISJOINTGROUP', disjointgroup)
Polls
AI-powered tools for network troubleshooting are likely to be part of everyone’s workflow sooner or later. What is the single biggest challenge or concern you see with adopting these tools in your organization?