cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
916
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)
Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the NSO Developer community: