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 For the SRX platform, the JUNOScripted track-ip implmentation allows the user to
010 utilize this critical feature on the SRX platform. It allows for path and next
011 hop validation through the existing network infrastructure with the ICMP protocol.
012 Upon detection of a failure the script will execute a failover to the other node
013 in an attempt to prevent downtime.
014
015 Authors: Rob Cameron (robc@juniper.net) and Patricio Giecco (pgiecco@juniper.net)
016
017 */
018
019 /*
020 Things to do:
021 Add in more logging
022 */
023 ns junos = "http://xml.juniper.net/junos/*/junos";
024 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
025 ns ext = "http://xmlsoft.org/XSLT/namespace";
026 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
027
028 import "../import/junos.xsl";
029 /* srx-ha-lib.xsl file start */
030 /* use a global connection for all rpc connections */
031 var $connection = jcs:open();
032 /* Pull the chassis cluster status and use throughout the script */
033 var $get-cluster-status = <rpc> {
034 <command> "show chassis cluster status";
035 }
036 var $cluster-status-results = jcs:execute($connection, $get-cluster-status);
037 var $chassis-cluster-rg-rpc = <rpc> {
038 <get-configuration> {
039 <configuration> {
040 <chassis> {
041 <cluster>;
042 }
043 }
044 }
045 }
046 /* Pull the redundancy group information information out of the configuration, used throughout made global */
047 var $chassis-cluster-config = jcs:execute($connection, $chassis-cluster-rg-rpc);
048 /* use this as a global to determine the interface ownership by chassis model */
049 var $product-model = {
050 call get-product-model();
051 }
052 var $get-interface-ownership = {
053 if ($product-model == "srx5600") {
054 var $node0-max-interface = 5;
055 var $node0-min-interface = 0;
056 var $node1-max-interface = 11;
057 var $node1-min-interface = 6;
058 <max-interface-number> {
059 <node0-max> $node0-max-interface;
060 <node0-min> $node0-min-interface;
061 <node1-max> $node1-max-interface;
062 <node1-min> $node1-min-interface;
063 }
064
065 } else if ($product-model == "srx5800") {
066 var $node0-max-interface = 11;
067 var $node0-min-interface = 0;
068 var $node1-max-interface = 23;
069 var $node1-min-interface = 12;
070 <max-interface-number> {
071 <node0-max> $node0-max-interface;
072 <node0-min> $node0-min-interface;
073 <node1-max> $node1-max-interface;
074 <node1-min> $node1-min-interface;
075 }
076 }
077 }
078 var $chassis-interface-ownership = ext:node-set($get-interface-ownership);
079 /* end global section */
080 /* start template section */
081 /* Determine which interface are monitored */
082 template get-monitor-interface-current-weight ($redundancy-group) {
083 var $results-get-monitor-interface-weight = jcs:execute($connection, $chassis-cluster-rg-rpc);
084 var $interface-monitor-weight = $results-get-monitor-interface-weight/chassis/cluster/apply-macro[name == "failover-interface-monitor"]/data[name == "$redundancy-group"]/value;
085
086 if (boolean($interface-monitor-weight)) {
087 <text> $interface-monitor-weight;
088
089 } else {
090 <text> "0";
091 }
092 }
093
094 /* Determine current time */
095 template get-current-time () {
096 var $rpc-get-current-time = <rpc> {
097 <get-system-uptime-information>;
098 }
099 var $results-get-current-time = jcs:execute($connection, $rpc-get-current-time);
100
101 if ($results-get-current-time/multi-routing-engine-item) {
102 var $current-time = $results-get-current-time/multi-routing-engine-item[1]/system-uptime-information/current-time/date-time/@junos:seconds;
103 <text> $current-time;
104
105 } else {
106 var $current-time = $results-get-current-time/current-time/date-time/@junos:seconds;
107 <text> $current-time;
108 }
109 }
110
111 /* Check if RG0 is ready to failover */
112 template check-RG0-failback () {
113 var $rg0-last-failover = {
114 call get-rg0-last-failover();
115 }
116 var $current-time = {
117 call get-current-time();
118 }
119 var $local-node = {
120 call get-local-node();
121 }
122 var $rg0-master = {
123 call get-master() {
124 with $redundancy-group = {
125 expr "0";
126 }
127 }
128 }
129 var $rg1-master = {
130 call get-master() {
131 with $redundancy-group = {
132 expr "1";
133 }
134 }
135 }
136 var $rg0-primary-node = {
137 /* Check who is the primary and whether the cluster has not been failed over already */
138 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") {
139 /* failover RG to node0 */
140 <text> "0";
141
142 } 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") {
143 /* failover RG to node1 */
144 <text> "1";
145 }
146 }
147
148 if ($local-node == $rg0-master) {
149 if ($rg0-master != $rg1-master) {
150 if (($current-time) >($rg0-last-failover + 300)) {
151 call request-rg-failover($node = $rg0-primary-node) {
152 with $redundancy-group = {
153 expr "0";
154 }
155 }
156 }
157 }
158 }
159 }
160
161
162 /* Check to to see the manual failover flag needs to be reset, if it does then reset it for all of the rgs
163
164 */
165 template check-and-reset-manual-failover-flag () {
166 if (boolean($chassis-cluster-config/chassis/cluster/apply-macro[name == "monitoring-options"]/data[name == "clear-failover"])) {
167 var $rpc-check-manual-failover-flag = <rpc> {
168 <command> "show chassis cluster status";
169 }
170 var $result-check-manual-failover-flag = jcs:execute($connection, $rpc-check-manual-failover-flag);
171 var $result-check-manual-failover-flag-node-set = ext:node-set($result-check-manual-failover-flag);
172
173 for-each ($result-check-manual-failover-flag//redundancy-group) {
174 if (./device-stats/failover-mode[1] == "yes") {
175 call reset-failover-flag($redundancy-group = ./redundancy-group-id[1]);
176 }
177 }
178 }
179 }
180
181 /* Determine the minute in the configuration */
182 template get-rg0-last-failover () {
183 var $results-get-rg0-last-failover = jcs:execute($connection, $chassis-cluster-rg-rpc);
184 var $last-rg0-failover-time = $results-get-rg0-last-failover/chassis/cluster/apply-macro[name == "failover-monitoring"]/data[name == "last-failover"]/value;
185
186 if (boolean($last-rg0-failover-time)) {
187 <text> $last-rg0-failover-time;
188
189 } else {
190 <text> "0";
191 }
192 }
193
194 /* Insert the last minute into the configuration */
195 template set-rg0-last-failover () {
196 var $current-time = {
197 call get-current-time();
198 }
199 /* <xsl:value-of select="jcs:output(concat('Setting last failover time for RG0 to ', $current-time))"/> */
200 var $rpc-configure-private = <rpc> {
201 <open-configuration> {
202 <private>;
203 }
204 }
205
206 expr jcs:execute($connection, $rpc-configure-private);
207 var $rpc-set-rg0-last-failover = <rpc> {
208 <load-configuration> {
209 <configuration> {
210 <chassis> {
211 <cluster> {
212 <apply-macro> {
213 <name> "failover-monitoring";
214 <data> {
215 <name> "last-failover";
216 <value> $current-time;
217 }
218 }
219 }
220 }
221 }
222 }
223 }
224 expr jcs:execute($connection, $rpc-set-rg0-last-failover);
225 var $commit = <rpc> {
226 <commit-configuration>;
227 }
228 expr jcs:execute($connection, $commit);
229 }
230
231 /* Insert the last minute into the configuration */
232 template set-track-interface-last-weight ($weight = 0, $redundancy-group) {
233 var $current-weight = {
234 call get-monitor-interface-current-weight($redundancy-group);
235 }
236 var $total-weight = $weight + $current-weight;
237 /* <xsl:value-of select="jcs:output(concat('Setting track interface weight to ', $weight, ' for RG ', $redundancy-group))"/> */
238 /* <xsl:value-of select="jcs:output(concat('Setting last failover time for RG0 to ', $current-time))"/> */
239 var $rpc-configure-private = <rpc> {
240 <open-configuration> {
241 <private>;
242 }
243 }
244
245 expr jcs:execute($connection, $rpc-configure-private);
246 var $rpc-set-track-interface-last-weight = <rpc> {
247 <load-configuration> {
248 <configuration> {
249 <chassis> {
250 <cluster> {
251 <apply-macro> {
252 <name> "failover-interface-monitor";
253 <data> {
254 <name> $redundancy-group;
255 <value> $total-weight;
256 }
257 }
258 }
259 }
260 }
261 }
262 }
263 expr jcs:execute($connection, $rpc-set-track-interface-last-weight);
264 var $commit = <rpc> {
265 <commit-configuration>;
266 }
267 expr jcs:execute($connection, $commit);
268 }
269
270 /* abstract the actual failover command outside of request failover */
271 template request-rg-failover ($node, $redundancy-group) {
272
273 if ($redundancy-group != "") {
274 /* rpc command for failover */
275 var $rpc-failover = <rpc> {
276 <command> {
277 expr "request chassis cluster failover node ";
278 expr $node;
279 expr " redundancy-group ";
280 expr $redundancy-group;
281 }
282 }
283
284 expr jcs:execute($connection, $rpc-failover);
285 }
286 /* added to allow command take effect */
287 expr jcs:sleep(0, 500);
288 }
289
290
291 /*
292 request-failover :: Chassis failover
293 This template performs an rg failover of the requested group
294
295 @param redundancy-group specifies the redundancy group to failover, defaults to 1
296 @param reset-flag specifies the manual failover flag should be cleared, defaults to false
297 @param fullfailover-flag specifies if both redundancy groups should be failed over, defaults to faulse
298 @param rg0-failover-check specifies if the failover time should be checked, defaults to true
299 */
300 template request-failover () {
301 param $redundancy-group = {
302 expr "1";
303 }
304 param $reset-flag = {
305 expr false();
306 }
307 param $fullfailover-flag = {
308 expr "0";
309 }
310 param $rg0-failover-check = {
311 expr "1";
312 }
313 /* Define which RG to failover */
314 /* force the selection of a parameter disable the default */
315 /* Chosing this forces both RGs to failover */
316 /* Verify if its safe to failover RG0 */
317 /* determite the other RG that would need to failover in a full failover */
318 var $other-redundancy-group = {
319 if ($redundancy-group == 0) {
320 <text> "1";
321
322 } else if ($redundancy-group == 1) {
323 <text> "0";
324 }
325 }
326 /* used to determine if we should fully failover */
327 var $rg0-master = {
328 call get-master() {
329 with $redundancy-group = {
330 expr "0";
331 }
332 }
333 }
334 var $rg1-master = {
335 call get-master() {
336 with $redundancy-group = {
337 expr "1";
338 }
339 }
340 }
341 var $rg0-last-failover = {
342 call get-rg0-last-failover();
343 }
344 var $current-time = {
345 call get-current-time();
346 }
347
348 /* <xsl:variable name="local-node">
349 <xsl:call-template name="get-local-node"/>
350 </xsl:variable> */
351 var $rg-primary-node = {
352 /* Check who is the primary and whether the cluster has not been failed over already */
353 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") {
354 /* failover RG to node0 */
355 <text> "0";
356
357 } 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") {
358 /* failover RG to node1 */
359 <text> "1";
360 }
361 }
362 var $rg0-primary-node = {
363 /* Check who is the primary and whether the cluster has not been failed over already */
364 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") {
365 /* failover RG to node0 */
366 <text> "0";
367
368 } 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") {
369 /* failover RG to node1 */
370 <text> "1";
371 }
372 }
373
374 /*
375 Execute the failover to the other chassis
376 */
377 if (boolean($rg0-failover-check == 1)) {
378 if (boolean($rg-primary-node != "")) {
379 if (boolean($fullfailover-flag &&((($rg0-master == "node0") &&($rg1-master == "node0")) ||(($rg0-master == "node1") &&($rg1-master == "node1"))))) {
380 if (($current-time) >($rg0-last-failover + 300)) {
381 var $time-diff = $current-time - $rg0-last-failover;
382
383 expr jcs:syslog(146, concat($time-diff, " seconds since last failover of RG0. Failing over RG0 to node", $rg-primary-node));
384 /* <xsl:value-of select="jcs:output(concat($time-diff, ' seconds since last failover of RG0. Failing over RG0.'))"/> */
385 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
386 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
387 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
388 /* full failover matched requesting RG0 failover */
389 call request-rg-failover($node = $rg0-primary-node, $redundancy-group = $other-redundancy-group);
390 call set-rg0-last-failover();
391
392 } else {
393 var $time-diff = $current-time - $rg0-last-failover;
394
395 expr jcs:syslog(146, concat("Not enough time has passed to failover RG0 only ", $time-diff, " seconds have passed on node", $rg0-primary-node));
396 /* <xsl:value-of select="jcs:output(concat('Not enough time has passed to failover RG0 only ', $time-diff, ' seconds have passed'))"/> */
397 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
398 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
399 call request-rg-failover($node = $rg-primary-node) {
400 with $redundancy-group = {
401 expr "1";
402 }
403 }
404 }
405
406 } else if ($redundancy-group == 0) {
407 if ($current-time >($rg0-last-failover + 300)) {
408 var $time-diff = $current-time - $rg0-last-failover;
409 /* <xsl:value-of select="jcs:output(concat($time-diff, ' seconds since last failover of RG0. Failing over RG0.'))"/> */
410 expr jcs:syslog(146, concat($time-diff, " seconds since last failover of RG0. Failing over RG0 to node", $rg-primary-node));
411 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
412 call set-rg0-last-failover();
413
414 } else {
415 var $time-diff = $current-time - $rg0-last-failover;
416 /* <xsl:value-of select="jcs:output(concat('Not enough time has passed to failover RG0 over ', $time-diff, ' seconds have passed'))"/> */
417 expr jcs:syslog(146, concat("Not enough time has passed to failover RG0 only ", $time-diff, " seconds have passed on node", $rg0-primary-node));
418 }
419
420 } else if ($redundancy-group == 1) {
421 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
422 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
423 }
424 }
425
426 } else {
427 if (boolean($rpc-failover != "")) {
428 if (boolean($fullfailover-flag)) {
429 /* <xsl:value-of select="jcs:output('Requesting full failover for both RG0 and RG1')"/> */
430 expr jcs:syslog(146, concat("Requesting failover for RG0 and RG1 to node", $rg-primary-node));
431 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
432 /* full failover matched requesting RG0 failover */
433 call request-rg-failover($node = $rg0-primary-node, $redundancy-group = $other-redundancy-group);
434 call set-rg0-last-failover();
435
436 } else if ($redundancy-group == 0) {
437 /* <xsl:value-of select="jcs:output('Requesting failover for RG0')"/> */
438 expr jcs:syslog(146, concat("Requesting failover for RG0 to node", $rg0-primary-node));
439 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
440 call set-rg0-last-failover();
441
442 } else if ($redundancy-group == 1) {
443 /* <xsl:value-of select="jcs:output('Requesting failover for RG1')"/> */
444 expr jcs:syslog(146, concat("Requesting failover for RG1 to node", $rg-primary-node));
445 call request-rg-failover($node = $rg-primary-node, $redundancy-group);
446 }
447 }
448 }
449
450 /*
451 Clear the failover status if requested
452 */
453 if (boolean($reset-flag)) {
454 if (boolean($fullfailover-flag)) {
455 call reset-failover-flag($redundancy-group);
456 call reset-failover-flag($redundancy-group = $other-redundancy-group);
457
458 } else {
459 call reset-failover-flag($redundancy-group);
460 }
461 }
462 }
463
464
465 /*
466 reset-failover-flag :: Get Master
467 This template is used to reset the failover flag
468
469 @param redundancy-group specifies the redundancy group to failover, 1 is the default
470 */
471 template reset-failover-flag () {
472 param $redundancy-group = {
473 expr "1";
474 }
475 var $rpc-clear-failover-flag = <rpc> {
476 <command> {
477 expr "request chassis cluster failover reset redundancy-group ";
478 expr $redundancy-group;
479 }
480 }
481
482 /* <xsl:value-of
483 select="jcs:output(concat('Reseting manual failover for redundancy group ', $redundancy-group))"/> */
484 expr jcs:syslog(146, concat("Reseting manual failover for redundancy group ", $redundancy-group));
485 expr jcs:execute($connection, $rpc-clear-failover-flag);
486 expr jcs:sleep(0, 500);
487 }
488
489
490 /*
491 get-master :: Get Master
492 This template is used to determine device is master of a redundancy group (RG0 by default).
493
494 @param redundancy-group specifies the redundancy group to check master default is 0
495 */
496 template get-master () {
497 param $redundancy-group = {
498 expr "0";
499 }
500 /* Determine the master of the chassis cluster */
501 var $rg-node0-priority = $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[1];
502 var $rg-node1-priority = $cluster-status-results/redundancy-group[$redundancy-group + 1]/device-stats/redundancy-group-status[2];
503
504 if (not($rg-node0-priority) || not($rg-node1-priority)) {
505 /* One Device is not communicating to the other the test will not run */
506
507 /* <xsl:value-of
508 select="jcs:output('Only one cluster member has been found. Check connectivity to the other cluster member.')"
509 /> */
510
511 } else if ($rg-node0-priority == "primary" && $rg-node1-priority != "primary") {
512 /* Node0 is the primary returning Node0 */
513 /* <xsl:value-of select="jcs:output(concat('Node0 is the master for redundancy group: ', $redundancy-group))"/> */
514 <text> "node0";
515
516 } else if ($rg-node0-priority != "primary" && $rg-node1-priority == "primary") {
517 /* Node1 is the primary returning Node1 */
518 /* <xsl:value-of select="jcs:output(concat('Node1 is the master for redundancy group: ', $redundancy-group))"/> */
519 <text> "node1";
520
521 } else {
522 /* priorities are the same */
523 /* <xsl:value-of select="jcs:output('An unexpected result has occured while checking the node status.')" /> */
524 }
525 }
526
527 /* Return the local node value */
528 template get-local-node () {
529 var $get-local-RE = <rpc> {
530 <command> "show chassis routing-engine node local";
531 }
532 /* Get the local RE node */
533 var $local-check-results = jcs:execute($connection, $get-local-RE);
534 <text> $local-check-results/multi-routing-engine-item/re-name;
535 }
536
537
538 /*
539 get-manual-failover-flag :: Get manual failover flag
540 This template is used to determine if the failover flag is set
541
542 @param redundancy-group specifies the redundancy group to check master default is 0
543 */
544 template get-manual-failover-flag ($redundancy-group) {
545 var $rpc-check-manual-failover-flag = <rpc> {
546 <command> "show chassis cluster status";
547 }
548 var $result-check-manual-failover-flag = jcs:execute($connection, $rpc-check-manual-failover-flag);
549 <text> $result-check-manual-failover-flag/redundancy-group[$redundancy-group + 1]/device-stats/failover-mode[1];
550 }
551
552 /* determine and return the current product model */
553 template get-product-model () {
554 var $rpc-product-model = <rpc> {
555 <command> "show version";
556 }
557 var $results-product-model = jcs:execute($connection, $rpc-product-model);
558
559 if ($results-product-model/multi-routing-engine-item) {
560 <text> $results-product-model/multi-routing-engine-item[1]/software-information/product-model;
561
562 } else {
563 expr $results-product-model/software-information/product-model;
564 }
565 }
566
567 /* end template section */
568 /* srx-ha-lib.xsl file end */
569 /* Global variables */
570 var $local-node-name = {
571 call get-local-node();
572 }
573 /* Determine the master for RG0 */
574 var $master-node-name = {
575 call get-master() {
576 with $redundancy-group = {
577 expr "0";
578 }
579 }
580 }
581 var $master-RG1 = {
582 call get-master() {
583 with $redundancy-group = {
584 expr "1";
585 }
586 }
587 }
588 var $node-regex = "(node)([0-9]+)";
589 var $local-node-number = jcs:regex($node-regex, $local-node-name);
590 var $rg1-node-number = jcs:regex($node-regex, $master-RG1);
591
592 /*
593 ping-server :: Ping server
594 This template returns the status of the server by using
595 the ping rpc provided by JUNOS
596
597 @param host: the IP address or hostname of the system
598 @param interval: the time between ping attempts 1 second is the default
599 @param count: the total number of ping attempts 3 attepmts is the default
600 */
601 template ping-server ($host, $interval, $count, $wait, $routing-instance) {
602 /* Optimize template to provide defaults for params */
603 /* This variable is the JUNOScript RPC call to execute the ping */
604 var $rpc-ping = <rpc> {
605 <ping> {
606 <host> $host;
607 if (boolean($interval)) {
608 <interval> $interval;
609
610 } else {
611 <interval> "0.1";
612 }
613 if (boolean($count)) {
614 <count> $count;
615
616 } else {
617 <count> "3";
618 }
619 if (boolean($wait)) {
620 <wait> $wait;
621
622 } else {
623 <wait> "1";
624 }
625 if (boolean($routing-instance)) {
626 <routing-instance> $routing-instance;
627 }
628 <verbose>;
629 }
630 }
631 /* contains the results from the ping test */
632 var $ping-results = jcs:execute($connection, $rpc-ping);
633 /* counts the number of successful pings */
634 var $ping-ok = count($ping-results/probe-result/probe-success);
635 /* <xsl:value-of select="jcs:output(concat('SUCCESS COUNT ', $ping-ok))"/> */
636 if ($ping-ok != 0) {
637 expr "ok";
638
639 } else {
640 expr "nok";
641 }
642 }
643
644
645 /*
646 main :: The starting point and main template for track ip
647 This is the main loop for the test.
648 It executes the ping tests and then will failover the cluster if there is an issue.
649
650 @param count the specified number of times this loop should run
651 */
652 template main ($count) {
653 /* check to see if we need to ruin through the loop again */
654 if ($count > 0) {
655 /* Log the iteration number */
656 /* <xsl:value-of select="jcs:output(concat('checking servers ',$count,' iterations to go'))"/> */
657 /* This variable stores the list of RGs that need to be failed over */
658 var $ping-test-results = <redundancy-groups> {
659
660 for-each ($chassis-cluster-config//cluster/redundancy-group) {
661 var $rg = ./name;
662 <redundancy-group> {
663 <name> $rg;
664
665 /* Loop through the apply-macro track-* statements and check each server
666 adds a server node to the redundancy group for each host tracked */
667
668 for-each (./apply-macro[starts-with(name, "track-")]) {
669 var $server-status = {
670 /* Ping with the user specified ping count */
671 call ping-server($host = ./data[name == "server"]/value, $count = ./data[name == "count"]/value, $wait = ./data[name == "wait"]/value, $interval = ./data[name == "interval"]/value, $routing-instance = ./data[name == "routing-instance"]/value);
672 }
673
674 if ($server-status == "nok") {
675 <server> {
676 <name> name;
677 <weight> ./data[name == "weight"]/value;
678 }
679
680 } else if ($server-status == "ok") {
681 /* Do nothing */
682 }
683 }
684 }
685 }
686 }
687 var $rg-ping-results = ext:node-set($ping-test-results);
688
689 if ($rg-ping-results/redundancy-groups/redundancy-group[sum(server/weight) > 254]) {
690 expr jcs:output($ping-test-results);
691 /* failover each redundancy group that exceeds 254 */
692
693 for-each ($rg-ping-results/redundancy-groups/redundancy-group[sum(server/weight) > 254]) {
694 /* <xsl:value-of select="jcs:output(concat('RG:', name ,' needs to be failed over'))"/> */
695 call request-failover($redundancy-group = name, $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"]));
696 call set-rg0-last-failover();
697 }
698
699 } else {
700 /* <xsl:value-of select="jcs:output('Tested servers are ok')"/> */
701 call main($count = $count - 1);
702 }
703
704 } else {
705 /* No more interations to run */
706 /* determine if RG0 should follow the leader RG1 */
707 call check-RG0-failback();
708 }
709 }
710
711 match / {
712 <op-script-results> {
713 /* In here we loop through the Track-ip statements and execute pings against them */
714 if (($local-node-name == $master-node-name) && $cluster-status-results/redundancy-group[2]/device-stats[1]/device-priority[$rg1-node-number[3] + 1] != 0) {
715 /* <xsl:value-of select="jcs:output('Node is the master of RG0, cheking tracked objects')"/> */
716 /* Figure out how long it takes to check all the servers */
717 var $runtimes = <exec-time> {
718
719 for-each ($chassis-cluster-config//cluster/redundancy-group) {
720
721 for-each (./apply-macro[starts-with(name, "track-")]) {
722 <time> {
723 var $count = {
724 if (boolean(./data[name == "count"]/value)) {
725 expr ./data[name == "count"]/value;
726
727 } else {
728 expr "3";
729 }
730 }
731 var $interval = {
732 if (boolean(./data[name == "interval"]/value)) {
733 expr ./data[name == "interval"]/value;
734
735 } else {
736 expr "0.1";
737 }
738 }
739 var $wait = {
740 if (boolean(./data[name == "wait"]/value)) {
741 expr ./data[name == "wait"]/value;
742
743 } else {
744 expr "1";
745 }
746 }
747
748 expr (($count * $interval) +($wait - 1)) * 0.668;
749 }
750 }
751 }
752 }
753 var $total-runtime = sum(ext:node-set($runtimes)//time);
754
755 /* <xsl:value-of
756 select="jcs:output(concat('It will take at most ',$total-runtime, ' seconds to run each iteration'))"/> */
757 var $execute-iterations = ceiling(60 div $total-runtime);
758
759 call main($count = $execute-iterations);
760
761 } else if ($cluster-status-results/redundancy-group[2]/device-stats[1]/device-priority[$rg1-node-number[3] + 1] == 0) {
762
763 /* <xsl:value-of
764 select="jcs:output('Node is the maser of RG0. RG1 master in priority 0 state. Nothing to do!')"/> */
765
766 } else {
767 /* This note is not master so it shouldn't ping as it will fail */
768
769 /* <xsl:value-of
770 select="jcs:output('Node is not the maser of RG0. Nothing to do!')"/> */
771 }
772 }
773 }
XML Script Contents
01 <?xml version="1.0"?>
02 <script>
03 <author>rcameron</author>
04 <title>track-ip.slax</title>
05 <synopsis>
06 This event script implements the Track-IP feature on the SRX platforms.
07 </synopsis>
08 <coe>event</coe>
09 <type>HA</type>
10
11 <description>
12 For the SRX platform, the Track-IP feature allows for path and next hop validation through the existing network infrastructure with the ICMP protocol. Upon the detection of a failure the script will execute a failover to the other node in an attempt to prevent downtime
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>