Overview
This script implements all of the features that are included on the SRX plus the ability to limit the failover of the control plane. This applies to SLAX version 1.0 and higher.
Description
Interface monitoring is an included feature on the platform but it may not meet all customer requirements. In some scenarios if the control plane is rapidly failed over it can cause instability. This implementation of interface monitoring accounts for this possibility and limits the user to monitoring only the data plane.
Source Code
GitHub Links
The source code below is also available from GitHub at the following locations:
01 Achieving High Availability with Interface Monitoring
02
03 Interface monitoring is a feature that is built into JUNOS on the SRX. The built in configuration can be utilized for both redundancy group zero and group one. However it may be possible that during rapid failover of redundancy group zero that instability can occur. For those who want redundancy group zero to failover in the event on an interface failure and are unable to prevent rapid failures this JUNOScript was created. The script operates just like the built in feature, however it prevents redundancy group zero from being rapidly failed over. To configure interface monitoring under any redundancy an administrator would create an "apply-macro monitor-interface" stanza and optionally specify its weight as shown below in figure three. If no weight is specified it is assumed it is 255 and would trigger a failover in the event the interface fails. If the weight is not great enough the intermediate weight is noted in the configuration under the stanza "apply macro failover-interface-monitor" in the chassis cluster section. When a failover occurs a syslog message will be generated as type external and level critical.
04
05 [Interface Monitoring configuration]
06
07 reth-count 4;
08 control-ports {
09 fpc 2 port 0;
10 fpc 14 port 0;
11 }
12 apply-macro failover-interface-monitor {
13 0 128;
14 }
15 redundancy-group 0 {
16 apply-macro monitor-interfaces {
17 xe-17/1/0;
18 xe-5/1/0 128;
19 xe-5/1/2 128;
20 }
21 node 0 priority 254;
22 node 1 priority 1;
23 }
24 redundancy-group 1 {
25 apply-macro track-host {
26 interval 0.5;
27 routing-instance BPSTest1;
28 server 1.0.11.11;
29 weight 255;
30 }
31 apply-macro monitor-interfaces {
32 xe-17/1/0;
33 xe-5/1/0;
34 xe-5/2/0;
35 }
36 node 0 priority 254;
37 node 1 priority 1;
38 }
39
40 To allow the interface monitoring take effect the event options stanza must be configured. This allows the interface monitoring intercept the message "SNMP_TRAP_LINK_DOWN" and allows the monitor-interface script act on the event. Using the configuration in figure four below will activate the script to act on the interface down messages.
41
42 [Interface Monitoring configuration]
43
44 event-options {
45 policy INTERFACE_MONITOR {
46 events SNMP_TRAP_LINK_DOWN;
47 then {
48 event-script monitor-interface.xsl {
49 arguments {
50 interface "{$$.interface-name}";
51 }
52 }
53 }
54 event-script {
55 file monitor-interface.xsl;
56 }
57 }
58
59 Validating the Interface Monitoring Configuration
60
61 The configuration options that begin with "apply macro" are all user created options. Because of this JUNOS does not validate these by default. To create custom validation options a commit script must be used. To validate the monitor interface configuration the commit script "srx-ha-validate.xsl" was created. The script must be placed in the /var/db/scripts/commit directory. Secondly it must be added to the JUNOS configuration by using the command "set system scripts commit file srx-ha-validate.xsl". Upon the committing of this configuration the options for monitor interface will be validated.
62 This prevents misspelling items like "interface" or giving numbers that are out of the range of the scripts capabilities. In the event that an option is not correctly con figured a warning will be emitted. This does notify the administrator that something is not right. It will not prevent the misconfiguration of monitor interface; it just creates a warning message. This was done to ensure interoperability with the Network and Security Manager platform (NSM). In the event that a warning message is received simply review the message and resolve the error by correcting the configuration mistake.
63
64 Global SRX High Availability Configuration Options
65
66 Under the chassis cluster configuration the macro "monitoring options" with the value of "clear failover" can be applied. If this is configured then after a fail over of the redundancy group occurs the manual fail over flag will be cleared. This setting is optional. If it is not configured the manual fail over will have to be cleared by the user. The second option that can be configured under the "monitoring-options" is the option "full failover". The full failover option triggers a full failover of all redundancy groups no matter which redundancy group failed its track IP checking. This option ensures that failed redundancy groups follow each other.
67
68 The design of the chassis cluster architecture is to allow the redundancy groups that pass data (redundancy group 1 and greater) to failover between the cluster members as fast as possible to support the various changing conditions of the network. The control plane redundancy group 0 has some unique limitations that do not allow for this to occur. The design of the control plane redundancy group 0 is that upon boot it will determine which chassis should be primary and stick to that chassis member until a failure occurs. The two routing engines that are used, one per chassis, synchronize using the graceful routing engine switchover (GRES) mechanism. The GRES design only allows the switching over of mastership between REs once per five minutes.
69
70 This is why RG0 is not meant to rapidly switchover between chassis and only in the event of a catastrophic failure. To prevent any GRES synchronization issues a timer has been implemented to stamp the last failover time for RG0. In configuration example two the time stamp is shown. The timestamp is in unix time (seconds since January 1st, 1970). The timestamp is set upon the first failover of RG0.
71
72 [Chassis Cluster Configuration Options]
73
74 chassis {
75 cluster {
76 apply-macro monitoring-options {
77 clear-failover;
78 full-failover;
79 }
80 apply-macro failover-monitoring {
81 last-failover 1228859971;
82 }
83 While the chassis cluster technology is very robust it is not always aligned with the operational procedures of organizations. Because of this the track ip JUNOScript accommodates these requests by also implementing the "follow the leader feature". This feature that is enabled by default forces RG0 to go where RG1 is located. This would have occurred if RG0 were unable to failover because it had been less then five minutes from the last failover. When difference between the last failover and then the current time is more then 300 seconds (five minutes) then RG0 will automatically fail over to the node where RG1 is located.
001 /* Machine Crafted with Care (tm) by slaxWriter */
002 version 1.0;
003
004
005 /*
006 Copyright Juniper Networks 2008
007 All rights reserved and owned by Juniper Networks
008
009 Interface monitoring is an included feature on the platform but it may not meet all
010 customer requirements. The script implments all of the feature that are included
011 on the SRX plus the ability to limit the failover of the control plane. In some
012 scenarios if the control plane is rapidly failed over it can cause instability.
013 This implementation of inteface monitoring accounts for this possibility and limits
014 the use to montoring only the data plane.
015
016 Author: Rob Cameron (robc@juniper.net)
017
018 */
019 ns junos = "http://xml.juniper.net/junos/*/junos";
020 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
021 ns ext = "http://xmlsoft.org/XSLT/namespace";
022 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
023
024 import "../import/junos.xsl";
025 /* Script Arguments */
026 var $arguments = <argument> {
027 <name> "interface";
028 <description> "specify the name of the interface that failed";
029 }
030 param $interface;
031 /* srx-ha-lib.xsl file start */
032 /* use a global connection for all rpc connections */
033 var $connection = jcs:open();
034 /* Pull the chassis cluster status and use throughout the script */
035 var $get-cluster-status = <rpc> {
036 <command> "show chassis cluster status";
037 }
038 var $cluster-status-results = jcs:execute($connection, $get-cluster-status);
039 var $chassis-cluster-rg-rpc = <rpc> {
040 <get-configuration> {
041 <configuration> {
042 <chassis> {
043 <cluster>;
044 }
045 }
046 }
047 }
048 /* Pull the redundancy group information information out of the configuration, used throughout made global */
049 var $chassis-cluster-config = jcs:execute($connection, $chassis-cluster-rg-rpc);
050 /* use this as a global to determine the interface ownership by chassis model */
051 var $product-model = {
052 call get-product-model();
053 }
054 var $get-interface-ownership = {
055 if ($product-model == "srx5600") {
056 var $node0-max-interface = 5;
057 var $node0-min-interface = 0;
058 var $node1-max-interface = 11;
059 var $node1-min-interface = 6;
060 <max-interface-number> {
061 <node0-max> $node0-max-interface;
062 <node0-min> $node0-min-interface;
063 <node1-max> $node1-max-interface;
064 <node1-min> $node1-min-interface;
065 }
066
067 } else if ($product-model == "srx5800") {
068 var $node0-max-interface = 11;
069 var $node0-min-interface = 0;
070 var $node1-max-interface = 23;
071 var $node1-min-interface = 12;
072 <max-interface-number> {
073 <node0-max> $node0-max-interface;
074 <node0-min> $node0-min-interface;
075 <node1-max> $node1-max-interface;
076 <node1-min> $node1-min-interface;
077 }
078 }
079 }
080 var $chassis-interface-ownership = ext:node-set($get-interface-ownership);
081 /* end global section */
082 /* start template section */
083 /* Determine which interface are monitored */
084 template get-monitor-interface-current-weight ($redundancy-group) {
085 var $results-get-monitor-interface-weight = jcs:execute($connection, $chassis-cluster-rg-rpc);
086 var $interface-monitor-weight = $results-get-monitor-interface-weight/chassis/cluster/apply-macro[name == "failover-interface-monitor"]/data[name == "$redundancy-group"]/value;
087
088 if (boolean($interface-monitor-weight)) {
089 <text> $interface-monitor-weight;
090
091 } else {
092 <text> "0";
093 }
094 }
095
096 /* Determine current time */
097 template get-current-time () {
098 var $rpc-get-current-time = <rpc> {
099 <get-system-uptime-information>;
100 }
101 var $results-get-current-time = jcs:execute($connection, $rpc-get-current-time);
102
103 if ($results-get-current-time/multi-routing-engine-item) {
104 var $current-time = $results-get-current-time/multi-routing-engine-item[1]/system-uptime-information/current-time/date-time/@junos:seconds;
105 <text> $current-time;
106
107 } else {
108 var $current-time = $results-get-current-time/current-time/date-time/@junos:seconds;
109 <text> $current-time;
110 }
111 }
112
113 /* Check if RG0 is ready to failover */
114 template check-RG0-failback () {
115 var $rg0-last-failover = {
116 call get-rg0-last-failover();
117 }
118 var $current-time = {
119 call get-current-time();
120 }
121 var $local-node = {
122 call get-local-node();
123 }
124 var $rg0-master = {
125 call get-master() {
126 with $redundancy-group = {
127 expr "0";
128 }
129 }
130 }
131 var $rg1-master = {
132 call get-master() {
133 with $redundancy-group = {
134 expr "1";
135 }
136 }
137 }
138 var $rg0-primary-node = {
139 /* Check who is the primary and whether the cluster has not been failed over already */
140 if ($cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[1] == "secondary" && $cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[2] == "primary" && $cluster-status-results/redundancy-group[1]/device-stats/failover-mode[2] == "no") {
141 /* failover RG to node0 */
142 <text> "0";
143
144 } else if ($cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[1] == "primary" && $cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[2] == "secondary" && $cluster-status-results/redundancy-group[1]/device-stats/failover-mode[1] == "no") {
145 /* failover RG to node1 */
146 <text> "1";
147 }
148 }
149
150 if ($local-node == $rg0-master) {
151 if ($rg0-master != $rg1-master) {
152 if (($current-time) >($rg0-last-failover + 300)) {
153 call request-rg-failover($node = $rg0-primary-node) {
154 with $redundancy-group = {
155 expr "0";
156 }
157 }
158 }
159 }
160 }
161 }
162
163
164 /* Check to to see the manual failover flag needs to be reset, if it does then reset it for all of the rgs
165
166 */
167 template check-and-reset-manual-failover-flag () {
168 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
169 var $rpc-check-manual-failover-flag = <rpc> {
170 <command> "show chassis cluster status";
171 }
172 var $result-check-manual-failover-flag = jcs:execute($connection, $rpc-check-manual-failover-flag);
173 var $result-check-manual-failover-flag-node-set = ext:node-set($result-check-manual-failover-flag);
174
175 for-each ($result-check-manual-failover-flag//redundancy-group) {
176 if (./device-stats/failover-mode[1] == "yes") {
177 call reset-failover-flag($redundancy-group = ./redundancy-group-id[1]);
178 }
179 }
180 }
181 }
182
183 /* Determine the minute in the configuration */
184 template get-rg0-last-failover () {
185 var $results-get-rg0-last-failover = jcs:execute($connection, $chassis-cluster-rg-rpc);
186 var $last-rg0-failover-time = $results-get-rg0-last-failover/chassis/cluster/apply-macro[name == "failover-monitoring"]/data[name == "last-failover"]/value;
187
188 if (boolean($last-rg0-failover-time)) {
189 <text> $last-rg0-failover-time;
190
191 } else {
192 <text> "0";
193 }
194 }
195
196 /* Insert the last minute into the configuration */
197 template set-rg0-last-failover () {
198 var $current-time = {
199 call get-current-time();
200 }
201 /* <xsl:value-of select="jcs:output(concat('Setting last failover time for RG0 to ', $current-time))"/> */
202 var $rpc-configure-private = <rpc> {
203 <open-configuration> {
204 <private>;
205 }
206 }
207
208 expr jcs:execute($connection, $rpc-configure-private);
209 var $rpc-set-rg0-last-failover = <rpc> {
210 <load-configuration> {
211 <configuration> {
212 <chassis> {
213 <cluster> {
214 <apply-macro> {
215 <name> "failover-monitoring";
216 <data> {
217 <name> "last-failover";
218 <value> $current-time;
219 }
220 }
221 }
222 }
223 }
224 }
225 }
226 expr jcs:execute($connection, $rpc-set-rg0-last-failover);
227 var $commit = <rpc> {
228 <commit-configuration>;
229 }
230 expr jcs:execute($connection, $commit);
231 }
232
233 /* Insert the last minute into the configuration */
234 template set-track-interface-last-weight ($weight = 0, $redundancy-group) {
235 var $current-weight = {
236 call get-monitor-interface-current-weight($redundancy-group);
237 }
238 var $total-weight = $weight + $current-weight;
239 /* <xsl:value-of select="jcs:output(concat('Setting track interface weight to ', $weight, ' for RG ', $redundancy-group))"/> */
240 /* <xsl:value-of select="jcs:output(concat('Setting last failover time for RG0 to ', $current-time))"/> */
241 var $rpc-configure-private = <rpc> {
242 <open-configuration> {
243 <private>;
244 }
245 }
246
247 expr jcs:execute($connection, $rpc-configure-private);
248 var $rpc-set-track-interface-last-weight = <rpc> {
249 <load-configuration> {
250 <configuration> {
251 <chassis> {
252 <cluster> {
253 <apply-macro> {
254 <name> "failover-interface-monitor";
255 <data> {
256 <name> $redundancy-group;
257 <value> $total-weight;
258 }
259 }
260 }
261 }
262 }
263 }
264 }
265 expr jcs:execute($connection, $rpc-set-track-interface-last-weight);
266 var $commit = <rpc> {
267 <commit-configuration>;
268 }
269 expr jcs:execute($connection, $commit);
270 }
271
272 /* abstract the actual failover command outside of request failover */
273 template request-rg-failover ($node, $redundancy-group) {
274
275 if ($redundancy-group != "") {
276 /* rpc command for failover */
277 var $rpc-failover = <rpc> {
278 <command> {
279 expr "request chassis cluster failover node ";
280 expr $node;
281 expr " redundancy-group ";
282 expr $redundancy-group;
283 }
284 }
285
286 expr jcs:execute($connection, $rpc-failover);
287 }
288 /* added to allow command take effect */
289 expr jcs:sleep(0, 500);
290 }
291
292
293 /*
294 request-failover :: Chassis failover
295 This template performs an rg failover of the requested group
296
297 @param redundancy-group specifies the redundancy group to failover, defaults to 1
298 @param reset-flag specifies the manual failover flag should be cleared, defaults to false
299 @param fullfailover-flag specifies if both redundancy groups should be failed over, defaults to faulse
300 @param rg0-failover-check specifies if the failover time should be checked, defaults to true
301 */
302 template request-failover () {
303 param $redundancy-group = {
304 expr "1";
305 }
306 param $reset-flag = {
307 expr false();
308 }
309 param $fullfailover-flag = {
310 expr "0";
311 }
312 param $rg0-failover-check = {
313 expr "1";
314 }
315 /* Define which RG to failover */
316 /* force the selection of a parameter disable the default */
317 /* Chosing this forces both RGs to failover */
318 /* Verify if its safe to failover RG0 */
319 /* determite the other RG that would need to failover in a full failover */
320 var $other-redundancy-group = {
321 if ($redundancy-group == 0) {
322 <text> "1";
323
324 } else if ($redundancy-group == 1) {
325 <text> "0";
326 }
327 }
328 /* used to determine if we should fully failover */
329 var $rg0-master = {
330 call get-master() {
331 with $redundancy-group = {
332 expr "0";
333 }
334 }
335 }
336 var $rg1-master = {
337 call get-master() {
338 with $redundancy-group = {
339 expr "1";
340 }
341 }
342 }
343 var $rg0-last-failover = {
344 call get-rg0-last-failover();
345 }
346 var $current-time = {
347 call get-current-time();
348 }
349
350 /* <xsl:variable name="local-node">
351 <xsl:call-template name="get-local-node"/>
352 </xsl:variable> */
353 var $rg-primary-node = {
354 /* Check who is the primary and whether the cluster has not been failed over already */
355 if ($cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[1] == "secondary" && $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[2] == "primary" && $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/failover-mode[2] == "no") {
356 /* failover RG to node0 */
357 <text> "0";
358
359 } else if ($cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[1] == "primary" && $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[2] == "secondary" && $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/failover-mode[1] == "no") {
360 /* failover RG to node1 */
361 <text> "1";
362 }
363 }
364 var $rg0-primary-node = {
365 /* Check who is the primary and whether the cluster has not been failed over already */
366 if ($cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[1] == "secondary" && $cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[2] == "primary" && $cluster-status-results/redundancy-group[1]/device-stats/failover-mode[2] == "no") {
367 /* failover RG to node0 */
368 <text> "0";
369
370 } else if ($cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[1] == "primary" && $cluster-status-results/redundancy-group[1]/device-stats/redundancy-group-status[2] == "secondary" && $cluster-status-results/redundancy-group[1]/device-stats/failover-mode[1] == "no") {
371 /* failover RG to node1 */
372 <text> "1";
373 }
374 }
375
376 /*
377 Execute the failover to the other chassis
378 */
379 if (boolean($rg0-failover-check == 1)) {
380 if (boolean($rg-primary-node != "")) {
381 if (boolean($fullfailover-flag &&((($rg0-master == "node0") &&($rg1-master == "node0")) ||(($rg0-master == "node1") &&($rg1-master == "node1"))))) {
382 if (($current-time) >($rg0-last-failover + 300)) {
383 var $time-diff = $current-time - $rg0-last-failover;
384
385 expr jcs:syslog(146, concat($time-diff, " seconds since last failover of RG0. Failing over RG0 to node", $rg-primary-node));
386 /* <xsl:value-of select="jcs:output(concat($time-diff, ' seconds since last failover of RG0. Failing over RG0.'))"/> */
387 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
388 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
389 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
390 /* full failover matched requesting RG0 failover */
391 call request-rg-failover($node = $rg0-primary-node, $redundancy-group = $other-redundancy-group);
392 call set-rg0-last-failover();
393
394 } else {
395 var $time-diff = $current-time - $rg0-last-failover;
396
397 expr jcs:syslog(146, concat("Not enough time has passed to failover RG0 only ", $time-diff, " seconds have passed on node", $rg0-primary-node));
398 /* <xsl:value-of select="jcs:output(concat('Not enough time has passed to failover RG0 only ', $time-diff, ' seconds have passed'))"/> */
399 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
400 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
401 call request-rg-failover($node = $rg-primary-node) {
402 with $redundancy-group = {
403 expr "1";
404 }
405 }
406 }
407
408 } else if ($redundancy-group == 0) {
409 if ($current-time >($rg0-last-failover + 300)) {
410 var $time-diff = $current-time - $rg0-last-failover;
411 /* <xsl:value-of select="jcs:output(concat($time-diff, ' seconds since last failover of RG0. Failing over RG0.'))"/> */
412 expr jcs:syslog(146, concat($time-diff, " seconds since last failover of RG0. Failing over RG0 to node", $rg-primary-node));
413 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
414 call set-rg0-last-failover();
415
416 } else {
417 var $time-diff = $current-time - $rg0-last-failover;
418 /* <xsl:value-of select="jcs:output(concat('Not enough time has passed to failover RG0 over ', $time-diff, ' seconds have passed'))"/> */
419 expr jcs:syslog(146, concat("Not enough time has passed to failover RG0 only ", $time-diff, " seconds have passed on node", $rg0-primary-node));
420 }
421
422 } else if ($redundancy-group == 1) {
423 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
424 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
425 }
426 }
427
428 } else {
429 if (boolean($rpc-failover != "")) {
430 if (boolean($fullfailover-flag)) {
431 /* <xsl:value-of select="jcs:output('Requesting full failover for both RG0 and RG1')"/> */
432 expr jcs:syslog(146, concat("Requesting failover for RG0 and RG1 to node", $rg-primary-node));
433 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
434 /* full failover matched requesting RG0 failover */
435 call request-rg-failover($node = $rg0-primary-node, $redundancy-group = $other-redundancy-group);
436 call set-rg0-last-failover();
437
438 } else if ($redundancy-group == 0) {
439 /* <xsl:value-of select="jcs:output('Requesting failover for RG0')"/> */
440 expr jcs:syslog(146, concat("Requesting failover for RG0 to node", $rg0-primary-node));
441 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
442 call set-rg0-last-failover();
443
444 } else if ($redundancy-group == 1) {
445 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
446 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
447 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
448 }
449 }
450 }
451
452 /*
453 Clear the failover status if requested
454 */
455 if (boolean($reset-flag)) {
456 if (boolean($fullfailover-flag)) {
457 call reset-failover-flag($redundancy-group);
458 call reset-failover-flag($redundancy-group = $other-redundancy-group);
459
460 } else {
461 call reset-failover-flag($redundancy-group);
462 }
463 }
464 }
465
466
467 /*
468 reset-failover-flag :: Get Master
469 This template is used to reset the failover flag
470
471 @param redundancy-group specifies the redundancy group to failover, 1 is the default
472 */
473 template reset-failover-flag () {
474 param $redundancy-group = {
475 expr "1";
476 }
477 var $rpc-clear-failover-flag = <rpc> {
478 <command> {
479 expr "request chassis cluster failover reset redundancy-group ";
480 expr $redundancy-group;
481 }
482 }
483
484 /* <xsl:value-of
485 select="jcs:output(concat('Reseting manual failover for redundancy group ', $redundancy-group))"/> */
486 expr jcs:syslog(146, concat("Reseting manual failover for redundancy group ", $redundancy-group));
487 expr jcs:execute($connection, $rpc-clear-failover-flag);
488 expr jcs:sleep(0, 500);
489 }
490
491
492 /*
493 get-master :: Get Master
494 This template is used to determine device is master of a redundancy group (RG0 by default).
495
496 @param redundancy-group specifies the redundancy group to check master default is 0
497 */
498 template get-master () {
499 param $redundancy-group = {
500 expr "0";
501 }
502 /* Determine the master of the chassis cluster */
503 var $rg-node0-priority = $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[1];
504 var $rg-node1-priority = $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[2];
505
506 if (not($rg-node0-priority) || not($rg-node1-priority)) {
507 /* One Device is not communicating to the other the test will not run */
508
509 /* <xsl:value-of
510 select="jcs:output('Only one cluster member has been found. Check connectivity to the other cluster member.')"
511 /> */
512
513 } else if ($rg-node0-priority == "primary" && $rg-node1-priority != "primary") {
514 /* Node0 is the primary returning Node0 */
515 /* <xsl:value-of select="jcs:output(concat('Node0 is the master for redundancy group: ', $redundancy-group))"/> */
516 <text> "node0";
517
518 } else if ($rg-node0-priority != "primary" && $rg-node1-priority == "primary") {
519 /* Node1 is the primary returning Node1 */
520 /* <xsl:value-of select="jcs:output(concat('Node1 is the master for redundancy group: ', $redundancy-group))"/> */
521 <text> "node1";
522
523 } else {
524 /* priorities are the same */
525 /* <xsl:value-of select="jcs:output('An unexpected result has occured while checking the node status.')" /> */
526 }
527 }
528
529 /* Return the local node value */
530 template get-local-node () {
531 var $get-local-RE = <rpc> {
532 <command> "show chassis routing-engine node local";
533 }
534 /* Get the local RE node */
535 var $local-check-results = jcs:execute($connection, $get-local-RE);
536 <text> $local-check-results/multi-routing-engine-item/re-name;
537 }
538
539
540 /*
541 get-manual-failover-flag :: Get manual failover flag
542 This template is used to determine if the failover flag is set
543
544 @param redundancy-group specifies the redundancy group to check master default is 0
545 */
546 template get-manual-failover-flag ($redundancy-group) {
547 var $rpc-check-manual-failover-flag = <rpc> {
548 <command> "show chassis cluster status";
549 }
550 var $result-check-manual-failover-flag = jcs:execute($connection, $rpc-check-manual-failover-flag);
551 <text> $result-check-manual-failover-flag/redundancy-group[$redundancy-group + 1]/device-stats/failover-mode[1];
552 }
553
554 /* determine and return the current product model */
555 template get-product-model () {
556 var $rpc-product-model = <rpc> {
557 <command> "show version";
558 }
559 var $results-product-model = jcs:execute($connection, $rpc-product-model);
560
561 if ($results-product-model/multi-routing-engine-item) {
562 <text> $results-product-model/multi-routing-engine-item[1]/software-information/product-model;
563
564 } else {
565 expr $results-product-model/software-information/product-model;
566 }
567 }
568
569 /* end template section */
570 /* srx-ha-lib.xsl file end */
571 template main () {
572 var $monitored-interfaces-results = <redundancy-groups> {
573
574 for-each ($chassis-cluster-config//cluster/redundancy-group) {
575 var $rg = ./name;
576 <redundancy-group> {
577 <name> $rg;
578
579 for-each (.//apply-macro[name == "monitor-interfaces"]/data) {
580 <monitored-interface> {
581 <name> ./name;
582 <weight> {
583 if (./value) {
584 expr ./value;
585
586 } else if (not(./monitored-interface/value)) {
587 expr "255";
588 }
589 }
590 }
591 }
592 }
593 }
594 }
595 var $rg0-master = {
596 call get-master() {
597 with $redundancy-group = {
598 expr "0";
599 }
600 }
601 }
602 var $rg1-master = {
603 call get-master() {
604 with $redundancy-group = {
605 expr "1";
606 }
607 }
608 }
609 var $local-node = {
610 call get-local-node();
611 }
612 var $int-parse-regex = "([a-zA-Z]+)-([0-9]+)/([0-9]+)/([0-9]+)";
613 var $monitored-interfaces = ext:node-set($monitored-interfaces-results);
614
615 for-each ($monitored-interfaces//redundancy-groups/redundancy-group) {
616 var $redundancy-group = ./name;
617 var $monitered-interface = ./monitored-interface/name;
618 var $weight = ./monitored-interface/weight;
619 var $RG-interface-monitor-weight = {
620 call get-monitor-interface-current-weight($redundancy-group);
621 }
622 var $total-weight = $RG-interface-monitor-weight + $weight;
623
624 if (($monitered-interface == translate($interface, " ", ""))) {
625 if (($monitered-interface == translate($interface, " ", "")) &&($total-weight > 254)) {
626 expr jcs:output(concat("found and testing ", translate($interface, " ", "")));
627 var $int-parse = jcs:regex($int-parse-regex, translate($interface, " ", ""));
628 var $media = $int-parse[2];
629 var $fpc = $int-parse[3];
630 var $pic = $int-parse[4];
631 var $port = $int-parse[5];
632 /* Determine which chassis owns the interface */
633 if (($fpc <= $chassis-interface-ownership/max-interface-number/node0-max) &&($fpc >= $chassis-interface-ownership/max-interface-number/node0-min)) {
634 /* node0 is the interface owner */
635 if ($redundancy-group == "0") {
636 if (($rg0-master == "node0") &&($rg1-master == "node0")) {
637 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"]), $fullfailover-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
638 with $redundancy-group = {
639 expr "0";
640 }
641 }
642
643 } else if (($rg0-master == "node0") && not($rg1-master == "node0")) {
644 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
645 with $redundancy-group = {
646 expr "0";
647 }
648 }
649
650 } else if (not($rg0-master == "node0") &&($rg1-master == "node0")) {
651 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
652 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
653 with $redundancy-group = {
654 expr "1";
655 }
656 }
657 }
658
659 } else if (not($rg0-master == "node0") && not($rg1-master == "node0")) {
660 /* do nothing chassis not a master for either RG */
661 }
662
663 } else if ($redundancy-group == "1") {
664 if (($rg0-master == "node0") &&($rg1-master == "node0")) {
665 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"]), $fullfailover-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
666 with $redundancy-group = {
667 expr "1";
668 }
669 }
670
671 } else if (($rg0-master == "node0") && not($rg1-master == "node0")) {
672 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
673 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
674 with $redundancy-group = {
675 expr "0";
676 }
677 }
678 }
679
680 } else if (not($rg0-master == "node0") &&($rg1-master == "node0")) {
681 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
682 with $redundancy-group = {
683 expr "1";
684 }
685 }
686
687 } else if (not($rg0-master == "node0") && not($rg1-master == "node0")) {
688 /* do nothing chassis not a master for either RG */
689 }
690 }
691
692 } else if (($fpc <= $chassis-interface-ownership/max-interface-number/node1-max) &&($fpc >= $chassis-interface-ownership/max-interface-number/node1-min)) {
693 /* node1 is the interface owner */
694 /* node0 processing */
695 if ($redundancy-group == "0") {
696 if (($rg0-master == "node1") &&($rg1-master == "node1")) {
697 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"]), $fullfailover-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
698 with $redundancy-group = {
699 expr "0";
700 }
701 }
702
703 } else if (($rg0-master == "node1") && not($rg1-master == "node1")) {
704 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
705 with $redundancy-group = {
706 expr "0";
707 }
708 }
709
710 } else if (not($rg0-master == "node1") &&($rg1-master == "node1")) {
711 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
712 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
713 with $redundancy-group = {
714 expr "1";
715 }
716 }
717 }
718
719 } else if (not($rg0-master == "node1") && not($rg1-master == "node1")) {
720 /* do nothing chassis not a master for either RG */
721 }
722
723 } else if ($redundancy-group == "1") {
724 if (($rg0-master == "node1") &&($rg1-master == "node1")) {
725 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"]), $fullfailover-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
726 with $redundancy-group = {
727 expr "1";
728 }
729 }
730
731 } else if (($rg0-master == "node1") && not($rg1-master == "node1")) {
732 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "full-failover"])) {
733 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
734 with $redundancy-group = {
735 expr "0";
736 }
737 }
738 }
739
740 } else if (not($rg0-master == "node1") &&($rg1-master == "node1")) {
741 call request-failover($reset-flag = boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
742 with $redundancy-group = {
743 expr "1";
744 }
745 }
746
747 } else if (not($rg0-master == "node1") && not($rg1-master == "node1")) {
748 /* do nothing chassis not a master for either RG */
749 }
750 }
751 }
752
753 } else {
754 call set-track-interface-last-weight($redundancy-group, $weight);
755 }
756
757 } else {
758 expr jcs:output(concat("The interface ", $interface, " is not monitored by RG", $redundancy-group));
759 }
760 }
761 }
762
763 match / {
764 <op-script-results> {
765 if (boolean($interface)) {
766 /* Determine the local node executing the script */
767 var $local-node-name = {
768 call get-local-node();
769 }
770 /* Determine the master for RG0 */
771 var $master-node-name = {
772 call get-master() {
773 with $redundancy-group = {
774 expr "0";
775 }
776 }
777 }
778
779 if ($local-node-name == $master-node-name) {
780 expr jcs:output("Node is the master of RG0, cheking tracked objects");
781 /* Run the interface monitoring */
782 expr jcs:output(concat("failed interface ", $interface));
783 call main();
784
785 } else {
786 /* This note is not master so it do anything */
787 expr jcs:output("Node is not the maser of RG0. Nothing to do!");
788 }
789
790 } else {
791 expr jcs:output("Please specify an interface name using the interface argument");
792 }
793 }
794 }
SLAX Script Contents
01 /* Machine Crafted with Care (tm) by slaxWriter */
02 version 1.0;
03
04
05 /*
06 - $Id: mpls-lsp.slax,v 1.1 2007/10/17 18:37:04 phil Exp $
07 -
08 - Copyright (c) 2004-2005, Juniper Networks, Inc.
09 - All rights reserved.
10 -
11 */
12 ns junos = "http://xml.juniper.net/junos/*/junos";
13 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
14 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
15
16 import "../import/junos.xsl";
17
18 /*
19 - This example turns a list of addresses into a list of MPLS LSPs.
20 - An apply-macro under [protocols mpls] is configured with a
21 - set of addresses and a 'color' parameter. Each address is
22 - turned into an LSP configuration, with the color as an admin-group.
23 */
24 match configuration {
25 var $mpls = protocols/mpls;
26
27 for-each ($mpls/apply-macro[data/name == "color"]) {
28 var $color = data[name == "color"]/value;
29 <transient-change> {
30 <protocols> {
31 <mpls> {
32
33 for-each (data[not(value)]/name) {
34 <label-switched-path> {
35 <name> $color _ "-lsp-" _ .;
36 <to> .;
37 <admin-group> {
38 <include> $color;
39 }
40 }
41 }
42 }
43 }
44 }
45 }
46 }
XML Script Contents
01 <?xml version="1.0"?>
02 <script>
03 <title>monitor-interface.slax</title>
04 <author>rcameron</author>
05 <synopsis>
06 This script implements all of the features that are included on the SRX plus the ability to limit the failover of the control plane.
07 </synopsis>
08 <coe>event</coe>
09 <type>HA</type>
10
11 <description>
12 Interface monitoring is an included feature on the platform but it may not meet all customer requirements. This implementation of interface monitoring limits the user to monitoring only the data plane.
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>