cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2590
Views
0
Helpful
7
Replies

Unexpected deletion in static route list

Fantolino
Level 1
Level 1

Hi team!

 

I'm developing a service that add static routes in a routing instance on a Junos PE. The serivice has not exclusive access to the static route list: routes may be added manually before or after the service has run. In latter case if the service is run again (e.g. because other routes has to be added o just because of a re-deploy) the manually added routes are deleted.


I tried to cope with this unexpected deletion using the tag "merge" in the templates (though I understand it should be the default) with no success.

 

How can avoid that behaviour?

 

----------

cisco@ncs% show Prova03 r-xx22 VESTA
staticRoute 199.1.1.0/24 {
nextHop 99.1.1.1;
}
staticRoute 199.1.2.0/24 {
nextHop 99.1.2.1;
}
[ok][2021-08-27 11:35:21]

[edit]
cisco@ncs% show devices device r-xx22 config junos:configuration routing-instances instance VESTA routing-options static | display service-meta-data
/* Refcount: 1 */
/* Backpointer: [ /Prova03:Prova03[Prova03:pe='r-xx22'][Prova03:vrf='VESTA'] ] */
route 199.1.1.0/24 {
next-hop [ 99.1.1.1 ];
}
/* Refcount: 1 */
/* Backpointer: [ /Prova03:Prova03[Prova03:pe='r-xx22'][Prova03:vrf='VESTA'] ] */
route 199.1.2.0/24 {
next-hop [ 99.1.2.1 ];
}
route 100.1.1.0/24 {
next-hop [ 8.1.1.1 ];
}
[ok][2021-08-27 11:35:31]

[edit]
cisco@ncs% request Prova03 r-xx22 VESTA re-deploy dry-run
cli {
local-node {
data devices {
device r-xx22 {
config {
junos:configuration {
routing-instances {
instance VESTA {
routing-options {
static {
- route 100.1.1.0/24 {
- next-hop [ 8.1.1.1 ];
- }
}
}
}
}
}
}
}
}

}
}

1 Accepted Solution

Accepted Solutions

Yes you can do that, it doesn't necessarily have to be in post, you can also do in pre. Note that in the delete case (op == 2), pre and postmodification calls are called after the service is deleted, so you will have to extract the keys, device and vrf name frpm the kp parameter by string processing.

The effect would be that when you remove this service it removes the routing instance, except if  there were manually added static routes underneath in which case only the static routes it created are removed.

 

Other things you could do instead to achive different effects:

  • The service create has a pre-check that the vrf exists, so it will never create or remove routing instances, just static routes . This is useful if the service is a low level service and there is a higher level service that creates the routing instance. It also gives you a mechanism for removing the routing instance including all the manual static routes, which you probably need to do when you remove the higher level service.
  • Have an action that  queries the static routes from the config, and updates the service definition so they are taken into the intent. This is useful if you want the manual routes to be discovered into the service and be managed form within NSO. You could trigger this with a kicker looking at  the static routes

 

View solution in original post

7 Replies 7

GBiscardi
Level 1
Level 1

Hi, 

I suggest to try deleting tag "merge" (it's default as you said)  and adding tag "replace" only for route:

 

<config-template  xmlns="http://tail-f.com/ns/config/1.0">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device >
      <name>{$DEVICE}</name>
        <config >
          <configuration  xmlns="http://xml.juniper.net/xnm/1.1/xnm">
           <routing-instances>
             <instance>
               <name>{$VRF}</name>
               <routing-options >
                 <static  when="{$STATIC_NETWORK}">
                  <route tags="replace">
                    <name>{$STATIC_NETWORK}</name>
                    <next-hop when="{$NEXT_HOP_ADDRESS}">{$NEXT_HOP_ADDRESS}</next-hop>
                  </route>
                </static>
               </routing-options>
             </instance>
           </routing-instances>
         </configuration>
      </config>
    </device>
  </devices>
</config-template>

I tried with no success....

Hi,

Using the "commit dry-run | debut template" will help you checking NSO behavior.

In your case, I believe the problem is that you are using "replace" to high in the tree and NSO will replace everything that is below that tag (therefore all routes).

 

As the "route" is a list, I believe you need to be very specific that you want to replace that item next hop. I would try:

 

<config-template  xmlns="http://tail-f.com/ns/config/1.0">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device >
      <name>{$DEVICE}</name>
        <config >
          <configuration  xmlns="http://xml.juniper.net/xnm/1.1/xnm">
           <routing-instances>
             <instance>
               <name>{$VRF}</name>
               <routing-options >
                 <static  when="{$STATIC_NETWORK}">
                  <route>
                    <name>{$STATIC_NETWORK}</name>
                    <next-hop tags="replace" when="{$NEXT_HOP_ADDRESS}">{$NEXT_HOP_ADDRESS}</next-hop>
                  </route>
                </static>
               </routing-options>
             </instance>
           </routing-instances>
         </configuration>
      </config>
    </device>
  </devices>
</config-template>

 

 

 

 

Hi!

I did as you suggested and modified the template. The problem persists: it seems that NSO thinks the existing configuration of routing-instance "ATOS" does not... exists!

 

cisco@ncs> show configuration Prova03 r-xx22 ATOS
staticRoute 199.1.1.0/24 {
    nextHop 99.1.1.1;
}
[ok][2021-08-31 09:36:22]
cisco@ncs> show configuration devices device r-xx22 config junos:configuration routing-instances instance ATOS routing-options
    static {
        route 199.1.1.0/24 {
            next-hop [ 99.1.1.1 ];
        }
        route 88.1.1.0/24 {
            next-hop [ 8.8.8.1 ];
        }
    }
[ok][2021-08-31 09:36:26]
cisco@ncs> request Prova03 r-xx22 ATOS re-deploy dry-run | debug template
Evaluating "$DEVICE" (from file "Prova03-template.xml", line 4)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: "r-xx22"
Operation 'merge' on existing node: /devices/device[name='r-xx22'] (from file "Prova03-template.xml", line 4)
Evaluating "$VRF" (from file "Prova03-template.xml", line 9)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: "ATOS"
Operation 'merge' on non-existing node: /devices/device[name='r-xx22']/config/junos:configuration/routing-instances/instance[name='ATOS'] (from file "Prova03-template.xml", line 9)
Evaluating conditional expression "boolean($STATIC_NETWORK)" (from file "Prova03-template.xml", line 11)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: true - continuing
Evaluating "$STATIC_NETWORK" (from file "Prova03-template.xml", line 13)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: "199.1.1.0/24"
Operation 'merge' on non-existing node: /devices/device[name='r-xx22']/config/junos:configuration/routing-instances/instance[name='ATOS']/routing-options/static/route[name='199.1.1.0/24'] (from file "Prova03-template.xml", line 13)
Evaluating conditional expression "boolean($NEXT_HOP_ADDRESS)" (from file "Prova03-template.xml", line 14)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: true - continuing
Evaluating "$NEXT_HOP_ADDRESS" (from file "Prova03-template.xml", line 14)
Context node: /Prova03[pe='r-xx22'][vrf='ATOS']
Result: "99.1.1.1"
Operation 'replace' on node: /devices/device[name='r-xx22']/config/junos:configuration/routing-instances/instance[name='ATOS']/routing-options/static/route[name='199.1.1.0/24']/next-hop[.='99.1.1.1'] (from file "Prova03-template.xml", line 14)
cli {
    local-node {
        data devices {
            device r-xx22 {
                config {
                    junos:configuration {
                        routing-instances {
                            instance ATOS {
                                routing-options {
                                    static {
            -                           route 88.1.1.0/24 {
            -                               next-hop [ 8.8.8.1 ];
            -                           }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    }

}

 

The way that fastmap works is that in the local context of the transaction, it is doing a delete and recreate of the service.

The delete is automatically handed by the reverse diff that is stored with the service. I believe the service has created the ATOS routing instance, so that the routing instance and everything underneath is removed by the reverse diff.

Then your create code runs to recreate the service so at this point it is correct that it does not see the ATOS routing instance.

That also explains why the static routes added under the routing instance manually are disappearing, the reverse diff just removes the whole routing instance but you code only recreates the static routes it knows about.

For a quick test you could try to create an empty routing instance first, then create the service, then add some static routes then do a service redeploy.  During creation the only thing that was created are the static routes, because the routing instance was already created by hand, so the reverse diff only removes those routes, and not the manually created routes.

 

I'm not sure how to fix your service, because I'm not sure of the exact effect you want to achieve, but one proposal might be to create the the routing ionstance in the pre-modification callback, outside of the scope of fastmap, that would behave very much like the test where you manually create it beforehand. However do note that if you change things that way, when you remove the service the routing instance is not removed.

 

Thank you!

I understand the point and I verified as you suggested, that if I create the routing-instance before the creation of the service it is OK.

My purpose is to let operation people to modify/enhance the configuration of the VPN service e.g. for providing customized features. 

Your suggestion seems valuable: if in the premodification I just create the routing instance it should be not a problem on the route untill a new routing-instance with the same name is used.

Could be possible to delete the rouitng instance in  post-modification if I verify that non configuration is present?

 

Yes you can do that, it doesn't necessarily have to be in post, you can also do in pre. Note that in the delete case (op == 2), pre and postmodification calls are called after the service is deleted, so you will have to extract the keys, device and vrf name frpm the kp parameter by string processing.

The effect would be that when you remove this service it removes the routing instance, except if  there were manually added static routes underneath in which case only the static routes it created are removed.

 

Other things you could do instead to achive different effects:

  • The service create has a pre-check that the vrf exists, so it will never create or remove routing instances, just static routes . This is useful if the service is a low level service and there is a higher level service that creates the routing instance. It also gives you a mechanism for removing the routing instance including all the manual static routes, which you probably need to do when you remove the higher level service.
  • Have an action that  queries the static routes from the config, and updates the service definition so they are taken into the intent. This is useful if you want the manual routes to be discovered into the service and be managed form within NSO. You could trigger this with a kicker looking at  the static routes