Blog Viewer

Scripting How-To: Use the toggle-interface script between two GRE endpoints

By Erdem posted 08-14-2015 16:23

  

Use the toggle-interface Script Between Two GRE Endpoints

 

For SLAX version 1.0 and higher, you can use a combined commit and event script that pings between two GRE endpoints and toggles the GRE interface status.

 

The toggle-interface script uses RPM to monitor each GRE interface. The ping probes run and check if the SA and DA pair can be pinged. If not, an error is sent to the syslog daemon. Based on the event log configuration, the toggle-interface.slax file is called. The GRE interface is set to disable. The probe runs again and if the SA+DA pair are reachable, the toggle-interface.slax file is called to delete the disable parameter.

 

Source Code and GitHub Links

 

The source code below is also available from the following GitHub locations:

 

Example Configuration

01 Here are the instructions.
02  
03 1. Put the attached toggle-interface.slax file into /var/db/scripts/op
04  
05 2. Put the attached create-rpms.slax file into /var/db/scripts/commit
06  
07 3. Merge the configuration in the config-changes.txt file into the router configuration
08  
09 It works like this:
10  
11 1. create-rpms.slax runs every time there is a commit done.
12 It looks for all GRE interfaces on the router and creates a RPM pim probe tests for each GRE interface. The GRE source and destination addresses are used as the probe source and destinations of the test
13  
14 2. The change is made as a transient change, so can't be seen in the configuration unless you pipe show configuration | display commit-scripts. This is done because it lets that part of the config be dynamically created based on configuration of the GRE interfaces
15  
16 3. The probe name has the name name as the GRE interface.
17  
18 4. Every 15 seconds, the ping probes run and check if the SA and DA pair can be pinged. If not, an erroris sent to the syslog daemon. Based on the event log configuration, the toggle-interface.slax file iscalled. The GRE interface is set to disable.
19  
20 5. The probe runs again and if the SA+DA pair are reachable, toggle-interface.slax file is called to delete the disable parameter.
21  
22 6. In every RPM probe test, even if the SA+DA pair continue to be reachable, the toggle-interface.slax script is still called to read the configuration and check if the interface is enabled or disabled. Thisis done because there isn't any state kept between script runs.
23  
24  
25  
26 system {
27     scripts {
28         commit {
29             allow-transients;
30             file create-rpms.slax;
31         }
32         op {
33             file ping-test.slax;
34             file toggle-interface.slax;
35         }
36     }
37 }
38 event-options {
39     policy disable-interface-on-ping-failure {
40         events ping_test_failed;
41         attributes-match {
42             ping_test_failed.test-owner matches .*script.*;
43         }
44         then {
45             event-script toggle-interface.slax {
46                 arguments {
47                     silent 2;
48                     interface "{$$.test-name}";
49                     new_intf_state disable;
50                 }
51             }
52         }
53     }
54     policy enable-interface-on-ping-success {
55         events ping_test_completed;
56         attributes-match {
57             ping_test_completed.test-owner matches .*script.*;
58         }          
59         then {     
60             event-script toggle-interface.slax {
61                 arguments {
62                     silent 2;
63                     interface "{$$.test-name}";
64                     new_intf_state enable;
65                 }  
66             }     
67         }          
68     }              
69 }                 

SLAX Script Contents

 
001 version 1.0; 

002   

003 ns junos = "http://xml.juniper.net/junos/*/junos"; 

004 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; 

005 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; 

006   

007 import "../import/junos.xsl"; 

008   

009 /* 

010 * Version: 1.0 

011 * Author: Juniper Networks 

012 */ 

013   

014 /* 

015 * Script toggles interface up or down based on passed args. 

016 * It's designed to work with RPM scripts and be called as part 

017 * of a JUNOS event on RPM failure or sucess. No state is 

018 * kept between RPM probes on interface state, so script 

019 * needs to read config for each time a probe passes or failes 

020 * to check current interface state and new one passed in arg list 

021 * 

022 */ 

023   

024 var $arguments = { 

025    <argument> { 

026       <name> "silent"; 

027       <description> "Decides where the output will go, 0 -> stdout, 1 -> syslog, 2 -> none"; 

028    } 

029    <argument> { 

030       <name> "interface"; 

031       <description> "Interface to deactivate"; 

032    } 

033    <argument> { 

034       <name> "new_intf_state"; 

035       <description> "New state of the interface disable -> disable interface, 1 -> enable interface"; 

036    } 

037   

038 } 

039   

040   

041 match / { 

042   

043    /* 

044     * Parse interface to get IFD and IFL 

045     */ 

046    var $split = jcs:split("\\.", $interface); 

047    var $ifd = $split[1]; 

048    var $unit = $split[2]; 

049   

050    var $rpc-config-req = <get-configuration database="committed" inherit="inherit">; 

051    var $configuration = jcs:invoke($rpc-config-req); 

052    if ($new_intf_state == "enable") { 

053       /* 

054        * If interface is already disabled and new interface state is enable, 

055        * populate the $xml var below to enable interface 

056        */ 

057       if ($configuration/interfaces/interface[name=$ifd]/unit[name=$unit]/disable) { 

058          var $xml = { 

059             <configuration> { 

060                <interfaces> { 

061                   <interface> { 

062                      <name> $ifd; 

063                      <unit> { 

064                         <name> $unit; 

065                         <disable delete="disable">; 

066                      } /* end unit */ 

067                   }  /* end <interface> */ 

068                } /* end <interfaces> */ 

069             } /* end <configuration> */ 

070          } /* end var $xml */ 

071   

072          call doConfigChange($xml); 

073       } 

074    } else if ($new_intf_state == "disable") { 

075       /* 

076        * If interface is enabled and new interface state is disable, 

077        * populate the $xml var below to disable interface 

078        */ 

079       if (not($configuration/interfaces/interface[name=$ifd]/unit[name=$unit]/disable)) { 

080          var $xml = { 

081             <configuration> { 

082                <interfaces> { 

083                   <interface> { 

084                      <name> $ifd; 

085                      <unit> { 

086                         <name> $unit; 

087                         <disable>; 

088                      } /* end unit */ 

089                   }  /* end <interface> */ 

090                } /* end <interfaces> */ 

091             } /* end <configuration> */ 

092          } /* end var $xml */ 

093   

094          call doConfigChange($xml); 

095       } 

096    } else { 

097       /* 

098        * unrecognised new interface state. 

099        */ 

100        call emit-error($message = "unrecognised new intf state"); 

101    } 

102 } 

103   

104 template doConfigChange($xml) { 

105    /* 

106     * Open connection with mgd 

107     */ 

108     var $con = jcs:open(); 

109   

110     if (not($con)) { 

111        call emit-error($message = "Not able to connect to local mgd"); 

112     } 

113     var $config-private = <open-configuration> { 

114        <private>; 

115     } 

116     var $private-results = jcs:execute($con, $config-private); 

117   

118     var $load-configuration = <load-configuration> { 

119        copy-of $xml; 

120     } 

121   

122    var $load-results = jcs:execute($con, $load-configuration); 

123   /* 

124    * Use load-configuration template defined in junos.xsl to load and 

125    * commit the configuration 

126    */ 

127   

128    var $commit-configuration = <commit-configuration>; 

129   

130    var $commit-results = jcs:execute($con, $commit-configuration); 

131   

132    var $close-private = <close-configuration>; 

133   

134    var $close-configuration-results = jcs:execute($con, $close-private); 

135    var $close-results = jcs:close($con); 

136   

137    /* 

138     * Emit warnings 

139     */ 

140    for-each ($commit-results//xnm:warning) { 

141       call emit-warn($message = message); 

142    } 

143   

144    if ($commit-results//xnm:error) { 

145       for-each ($results//xnm:error) { 

146          call emit-error($message = message); 

147       } 

148    } else { 

149       call emit-success($message = "Deactivated interface"); 

150    } 

151   

152    if (not($silent)) { 

153       <op-script-results> { 

154          copy-of $results; 

155       } 

156    } 

157 } 

158   

159 template emit-success($message) { 

160   

161    if ($silent == 0) { 

162       expr jcs:output($message); 

163    } else if ($silent == 1) { 

164       expr jcs:syslog("user.info","toggle-interface.slax[Success]: ", $message); 

165    } 

166 } 

167    

168 template emit-error($message) { 

169   

170    if ($silent == 0) { 

171       expr jcs:output($message); 

172    } else if ($silent == 1) { 

173       expr jcs:syslog("user.error", "disable-interface.slax[Error]: ", $message); 

174   } 

175 } 

176   

177 template emit-warn($message) { 

178   

179    if ($silent == 0) { 

180       expr jcs:output($message); 

181    } else if ($silent == 1) { 

182       expr jcs:syslog("user.warning", "disable-interface.slax[Warning]: ", $message); 

183    } 

184 } 

XML Script Contents

01 <?xml version="1.0"?>
02 <script>
03 <title>toggle-interface.slax</title>
04 <author>chellberg</author>
05 <synopsis>
06 A combined commit and event script that pings between two GRE endpoints and toggle the GRE interface status
07 </synopsis>
08 <coe>event</coe>
09 <type>interfaces</type>
10  
11 <description>
12 This script uses RPM to monitor each GRE interface. The ping probes run and check if the SA and DA pair can be pinged. If not, an error is sent to the syslog daemon. Based on the event log configuration, the toggle-interface.slax file is called. The GRE interface is set to disable. The probe runs again and if the SA+DA pair are reachable, toggle-interface.slax file is called to delete the disable parameter.
13 </description>
14  
15  <example>
16  <title>Example</title>
17  <config>example-1.conf</config>
18  </example>
19  
20 <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
21 src="../../../../../web/leaf.js"
22 type="text/javascript"/>
23 </script>

Required Utility Script


   
01 version 1.0; 

02   

03 ns junos = "http://xml.juniper.net/junos/*/junos"; 

04 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; 

05 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; 

06   

07 import "../import/junos.xsl"; 

08   

09 version 1.0; 

10   

11 ns junos = "http://xml.juniper.net/junos/*/junos"; 

12 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; 

13 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; 

14   

15 import "../import/junos.xsl"; 

16   

17 /* Version: 1.0   

18 * Author: Juniper Networks 

19 */ 

20   

21 /* This script parses the configuration for any GRE interfaces. 

22 * It extracts the source and destination  addresses from the tunnels 

23 * and creates RPM probe interfaces with a test interval of 15s. 

24 * The owner of all probes is "script" and all test names are the 

25 * same as the GRE interface. Changing these values should be 

26 * avoided because they are referenced in other OP scripts 

27 */ 

28   

29 match configuration { 

30    var $top = .; 

31    for-each (interfaces/interface[starts-with(name, "gr-")]) { 

32       var $ifd = name; 

33       for-each (unit) { 

34          var $unit = name; 

35          var $t_source_ip = tunnel/source; 

36          var $t_dest_ip = tunnel/destination; 

37          if ($t_source_ip && $t_dest_ip) { 

38             <transient-change> { 

39                <services> { 

40                   <rpm> { 

41                      <probe> { 

42                         <name> "script"; 

43                         <test>  { 

44                            <name> $ifd _ "." _ $unit; 

45                            <probe-type> 

46                               "icmp-ping"; 

47                               <target> { 

48                                  <address> $t_dest_ip; 

49                                } 

50                                <test-interval> 15; 

51                                <source-address> $t_source_ip; 

52                         } /* end test */ 

53                      } /* end probe type */ 

54                   } /* end rpm */ 

55                } /* end services */ 

56             }  /* end transient change */ 

57          } /* ensure SA and DA are present */ 

58       } /* end for-each unit loop */ 

59    } /* end for-each IFD loop */ 

60 } /* match configuration */ 

#SLAX
#GRE
#JUNOScriptorium
#eventscript
#ScriptingHow-To
#commitscript

Permalink