summaryrefslogtreecommitdiff
path: root/scripts/keepalived
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/keepalived')
-rwxr-xr-xscripts/keepalived/VyattaKeepalived.pm181
-rwxr-xr-xscripts/keepalived/vyatta-keepalived.pl184
-rwxr-xr-xscripts/keepalived/vyatta-show-vrrp.pl158
-rwxr-xr-xscripts/keepalived/vyatta-vrrp-state.pl89
4 files changed, 612 insertions, 0 deletions
diff --git a/scripts/keepalived/VyattaKeepalived.pm b/scripts/keepalived/VyattaKeepalived.pm
new file mode 100755
index 00000000..c8d732d1
--- /dev/null
+++ b/scripts/keepalived/VyattaKeepalived.pm
@@ -0,0 +1,181 @@
+#!/usr/bin/perl
+#
+# Module: VyattaKeepalived.pm
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2007
+# Description: Common keepalived definitions/funcitions
+#
+# **** End License ****
+#
+package VyattaKeepalived;
+
+use VyattaConfig;
+use POSIX;
+
+use strict;
+use warnings;
+
+my $daemon = '/usr/sbin/keepalived';
+my $keepalived_conf = '/etc/keepalived/keepalived.conf';
+my $sbin_dir = '/opt/vyatta/sbin';
+my $state_transition = "$sbin_dir/vyatta-vrrp-state.pl";
+my $keepalived_pid = '/var/run/keepalived_vrrp.pid';
+my $state_dir = '/var/log/vrrpd';
+my $vrrp_log = "$state_dir/vrrp.log";
+
+
+sub vrrp_log {
+ my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime);
+ open my $fh, ">>", $vrrp_log;
+ print $fh "$timestamp: ", @_ , "\n";
+ close $fh;
+}
+
+sub is_running {
+ if (-f $keepalived_pid) {
+ my $pid = `cat $keepalived_pid`;
+ chomp $pid;
+ my $ps = `ps -p $pid -o comm=`;
+
+ if (defined($ps) && $ps ne "") {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub start_daemon {
+ my ($conf) = @_;
+
+ my $cmd = "$daemon --vrrp --log-facility 7 --log-detail --dump-conf --use-file $conf";
+ system($cmd);
+ vrrp_log("start_daemon");
+}
+
+sub stop_daemon {
+ if (is_running()) {
+ my $pid = `cat $keepalived_pid`;
+ system("kill $pid");
+ vrrp_log("stop_daemon");
+ } else {
+ vrrp_log("stop daemon called while not running");
+ }
+}
+
+sub restart_daemon {
+ my ($conf) = @_;
+
+ if (VyattaKeepalived::is_running()) {
+ my $pid = `cat $keepalived_pid`;
+ chomp $pid;
+ system("kill -1 $pid");
+ vrrp_log("restart_deamon");
+ } else {
+ start_daemon($conf);
+ }
+}
+
+sub get_conf_file {
+ return $keepalived_conf;
+}
+
+sub get_state_script {
+ return $state_transition;
+}
+
+sub get_state_file {
+ my ($vrrp_intf, $vrrp_group) = @_;
+
+ my $file = "$state_dir/vrrpd_" . "$vrrp_intf" . "_" . "$vrrp_group.state";
+ return $file;
+}
+
+sub get_master_file {
+ my ($vrrp_intf, $vrrp_group) = @_;
+
+ my $file = "$state_dir/vrrpd_" . "$vrrp_intf" . "_" . "$vrrp_group.master";
+ return $file;
+}
+
+sub get_state_files {
+ my $intf = shift;
+
+ # todo: fix sorting for ethX > 9
+ my @state_files;
+ open(my $LS, "ls $state_dir |grep '^vrrpd_$intf.*\.state\$' | sort |");
+ @state_files = <$LS>;
+ close($LS);
+ foreach my $i (0 .. $#state_files) {
+ $state_files[$i] = "$state_dir/$state_files[$i]";
+ }
+ chomp @state_files;
+ return @state_files;
+}
+
+sub vrrp_get_config {
+ my ($intf, $group) = @_;
+
+ my $config = new VyattaConfig;
+
+ $config->setLevel("interfaces ethernet $intf");
+ my $primary_addr = $config->returnOrigValue("address");
+ if ($primary_addr =~ m/(\d+\.\d+\.\d+\.\d+)\/\d+/) {
+ $primary_addr = $1;
+ }
+
+ $config->setLevel("interfaces ethernet $intf vrrp");
+ my $vip = $config->returnOrigValue("virtual-address");
+ my $priority = $config->returnOrigValue("priority");
+ if (!defined $priority) {
+ $priority = 1;
+ }
+ my $preempt = $config->returnOrigValue("preempt");
+ if (!defined $preempt) {
+ $preempt = "true";
+ }
+ my $advert_int = $config->returnOrigValue("advertise-interval");
+ if (!defined $advert_int) {
+ $advert_int = 1;
+ }
+ $config->setLevel("interfaces ethernet $intf vrrp authentication");
+ my $auth_type = $config->returnOrigValue("type");
+ if (!defined $auth_type) {
+ $auth_type = "none";
+ } else {
+ $auth_type = uc($auth_type);
+ }
+ return ($primary_addr, $vip, $priority, $preempt, $advert_int, $auth_type);
+}
+
+sub vrrp_state_parse {
+ my ($file) = @_;
+
+ if ( -f $file) {
+ my $line = `cat $file`;
+ chomp $line;
+ my ($start_time, $intf, $group, $state, $ltime) = split(' ', $line);
+ return ($start_time, $intf, $group, $state, $ltime);
+ } else {
+ return undef;
+ }
+}
+
+#end of file
diff --git a/scripts/keepalived/vyatta-keepalived.pl b/scripts/keepalived/vyatta-keepalived.pl
new file mode 100755
index 00000000..15346855
--- /dev/null
+++ b/scripts/keepalived/vyatta-keepalived.pl
@@ -0,0 +1,184 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-keepalived.pl
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2007
+# Description: Script to glue vyatta cli to keepalived daemon
+#
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5/";
+use VyattaConfig;
+use VyattaKeepalived;
+use Getopt::Long;
+
+use strict;
+use warnings;
+
+
+sub keepalived_get_values {
+ my ($intf) = @_;
+
+ my $output;
+ my $config = new VyattaConfig;
+
+ $config->setLevel("interfaces ethernet $intf vrrp");
+ my $group = $config->returnValue("vrrp-group");
+ if (!defined $group) {
+ $group = 1;
+ }
+ my $vip = $config->returnValue("virtual-address");
+ if (!defined $vip) {
+ print "must define a virtual-address for vrrp-group $group\n";
+ exit 1;
+ }
+ my $priority = $config->returnValue("priority");
+ if (!defined $priority) {
+ $priority = 1;
+ }
+ my $preempt = $config->returnValue("preempt");
+ if (!defined $preempt) {
+ $preempt = "true";
+ }
+ my $advert_int = $config->returnValue("advertise-interval");
+ if (!defined $advert_int) {
+ $advert_int = 1;
+ }
+ $config->setLevel("interfaces ethernet $intf vrrp authentication");
+ my $auth_type = $config->returnValue("type");
+ my $auth_pass;
+ if (defined $auth_type) {
+ $auth_type = uc($auth_type);
+ $auth_pass = $config->returnValue("password");
+ if (! defined $auth_pass) {
+ print "vrrp authentication password not set";
+ exit 1;
+ }
+ }
+ my $state_transition_script = VyattaKeepalived::get_state_script();
+
+ $output = "vrrp_instance vyatta-$intf-$group \{\n";
+ if ($preempt eq "false") {
+ $output .= "\tstate BACKUP\n";
+ } else {
+ $output .= "\tstate MASTER\n";
+ }
+ $output .= "\tinterface $intf\n";
+ $output .= "\tvirtual_router_id $group\n";
+ $output .= "\tpriority $priority\n";
+ if ($preempt eq "false") {
+ $output .= "\tnopreempt\n";
+ }
+ $output .= "\tadvert_int $advert_int\n";
+ if (defined $auth_type) {
+ $output .= "\tauthentication {\n";
+ $output .= "\t\tauth_type $auth_type\n";
+ $output .= "\t\tauth_pass $auth_pass\n\t}\n";
+ }
+ $output .= "\tvirtual_ipaddress \{\n";
+ $output .= "\t\t$vip\n";
+ $output .= "\t\}\n";
+ $output .= "\tnotify_master ";
+ $output .= "\"$state_transition_script master $intf $group $vip\" \n";
+ $output .= "\tnotify_backup ";
+ $output .= "\"$state_transition_script backup $intf $group $vip\" \n";
+ $output .= "\t notify_fault ";
+ $output .= "\"$state_transition_script fault $intf $group $vip\" \n";
+ $output .= "\}\n";
+
+ return $output;
+}
+
+sub vrrp_update_config {
+ my $output;
+
+ my $config = new VyattaConfig;
+
+ # todo: support vifs
+ $config->setLevel("interfaces ethernet");
+ my @eths = $config->listNodes();
+ my $vrrp_instances = 0;
+ foreach my $eth (@eths) {
+ $config->setLevel("interfaces ethernet $eth");
+ if ($config->exists("vrrp")) {
+ $output .= keepalived_get_values($eth);
+ $vrrp_instances++;
+ }
+ }
+
+ if ($vrrp_instances > 0) {
+ my $conf_file = VyattaKeepalived::get_conf_file();
+ keepalived_write_file($conf_file, $output);
+ VyattaKeepalived::restart_daemon($conf_file);
+ }
+ return $vrrp_instances;
+}
+
+sub keepalived_write_file {
+ my ($file, $data) = @_;
+
+ open(my $fh, '>', $file) || die "Couldn't open $file - $!";
+ print $fh $data;
+ close $fh;
+}
+
+
+#
+# main
+#
+my ($action, $vrrp_intf, $vrrp_group);
+
+GetOptions("vrrp-action=s" => \$action,
+ "intf=s" => \$vrrp_intf,
+ "group=s" => \$vrrp_group);
+
+if (! defined $action) {
+ print "no action\n";
+ exit 1;
+}
+
+if ($action eq "update") {
+ my $vrrp_instances = vrrp_update_config();
+ VyattaKeepalived::vrrp_log("vrrp update $vrrp_intf $vrrp_instances");
+ if ($vrrp_instances == 0) {
+ VyattaKeepalived::stop_daemon();
+ }
+}
+
+if ($action eq "delete") {
+ if (! defined $vrrp_intf || ! defined $vrrp_group) {
+ print "must include interface & group";
+ exit 1;
+ }
+ my $state_file = VyattaKeepalived::get_state_file($vrrp_intf, $vrrp_group);
+ system("rm $state_file");
+ VyattaKeepalived::vrrp_log("vrrp delete $vrrp_intf $vrrp_group");
+ exit 0;
+}
+
+exit 0;
+
+# end of file
+
+
+
+
diff --git a/scripts/keepalived/vyatta-show-vrrp.pl b/scripts/keepalived/vyatta-show-vrrp.pl
new file mode 100755
index 00000000..6540eaf5
--- /dev/null
+++ b/scripts/keepalived/vyatta-show-vrrp.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-show-vrrp.pl
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2005, 2006, 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2007
+# Description: display vrrp info
+#
+# **** End License ****
+#
+use lib "/opt/vyatta/share/perl5/";
+use VyattaKeepalived;
+
+use strict;
+use warnings;
+
+
+sub elapse_time {
+ my ($start, $stop) = @_;
+
+ my $seconds = $stop - $start;
+ my $string = '';
+ my $secs_min = 60;
+ my $secs_hour = $secs_min * 60;
+ my $secs_day = $secs_hour * 24;
+ my $secs_week = $secs_day * 7;
+
+ my $weeks = int($seconds / $secs_week);
+ if ($weeks > 0 ) {
+ $seconds = int($seconds % $secs_week);
+ $string .= $weeks . "w";
+ }
+ my $days = int($seconds / $secs_day);
+ if ($days > 0) {
+ $seconds = int($seconds % $secs_day);
+ $string .= $days . "d";
+ }
+ my $hours = int($seconds / $secs_hour);
+ if ($hours > 0) {
+ $seconds = int($seconds % $secs_hour);
+ $string .= $hours . "h";
+ }
+ my $mins = int($seconds / $secs_min);
+ if ($mins > 0) {
+ $seconds = int($seconds % $secs_min);
+ $string .= $mins . "m";
+ }
+ $string .= $seconds . "s";
+
+ return $string;
+}
+
+sub link_updown {
+ my ($intf) = @_;
+
+ my $status = `sudo /usr/sbin/ethtool $intf | grep Link`;
+ if ($status =~ m/yes/) {
+ return "up";
+ }
+ if ($status =~ m/no/) {
+ return "down";
+ }
+ return "unknown";
+}
+
+sub get_master_info {
+ my ($intf, $group, $vip) = @_;
+
+ my $file = VyattaKeepalived::get_master_file($intf, $group);
+ if ( -f $file) {
+ my $master = `grep ip.src $file`;
+ chomp $master;
+ if (defined $master and $master =~ m/show=\"(\d+\.\d+\.\d+\.\d+)\"/) {
+ $master = $1;
+ } else {
+ $master = "unknown";
+ }
+ my $priority = `grep vrrp.prio $file`;
+ chomp $priority;
+ if (defined $priority and $priority =~ m/show=\"(\d+)\"/) {
+ $priority = $1;
+ } else {
+ $priority = "unknown";
+ }
+ return ($master, $priority);
+ } else {
+ return ("unknown", "unknown");
+ }
+}
+
+sub vrrp_show {
+ my ($file) = @_;
+
+ my $now_time = time;
+ my ($start_time, $intf, $group, $state, $ltime) =
+ VyattaKeepalived::vrrp_state_parse($file);
+ my $link = link_updown($intf);
+ if ($state eq "master" || $state eq "backup" || $state eq "fault") {
+ my ($primary_addr, $vip, $priority, $preempt, $advert_int, $auth_type) =
+ VyattaKeepalived::vrrp_get_config($intf, $group);
+ print "Physical interface: $intf, Address $primary_addr\n";
+ print " Interface state: $link, Group $group, State: $state\n";
+ print " Priority: $priority, Advertisement interval: $advert_int, ";
+ print "Authentication type: $auth_type\n";
+ print " Preempt: $preempt, VIP count: 1, VIP: $vip\n";
+ if ($state eq "master") {
+ print " Master router: $primary_addr\n";
+ } elsif ($state eq "backup") {
+ my ($master_rtr, $master_prio) = get_master_info($intf,
+ $group, $vip);
+ print " Master router: $master_rtr, ";
+ print "Master Priority: $master_prio\n";
+ }
+ } else {
+ print "Physical interface $intf, State: unknown\n";
+ }
+ my $elapsed = elapse_time($start_time, $now_time);
+ print " Last transition: $elapsed\n\n";
+}
+
+#
+# main
+#
+my $intf = "eth";
+if ($#ARGV > -1) {
+ $intf = $ARGV[0];
+}
+
+if (!VyattaKeepalived::is_running()) {
+ print "VRRP isn't running\n";
+ exit 1;
+}
+
+my @state_files = VyattaKeepalived::get_state_files($intf);
+foreach my $state_file (@state_files) {
+ vrrp_show($state_file);
+}
+
+exit 0;
+
+#end of file
diff --git a/scripts/keepalived/vyatta-vrrp-state.pl b/scripts/keepalived/vyatta-vrrp-state.pl
new file mode 100755
index 00000000..1f5ae6cb
--- /dev/null
+++ b/scripts/keepalived/vyatta-vrrp-state.pl
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-vrrp-state.pl
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2007
+# Description: Script called on vrrp master state transition
+#
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5/";
+use VyattaKeepalived;
+use POSIX;
+
+use strict;
+use warnings;
+
+
+sub snoop_for_master {
+ my ($intf, $group, $vip, $file) = @_;
+
+ my $cap_filt = "-f \"host 224.0.0.18 and proto VRRP\"";
+ my $dis_filt = "-R \"vrrp.virt_rtr_id == $group and vrrp.ip_addr == $vip\"";
+ my $cmd = "tshark -a duration:60 -p -i$intf -c1 -T pdml $cap_filt $dis_filt";
+ system("$cmd > $file 2> /dev/null");
+}
+
+sub vrrp_state_log {
+ my ($state, $intf, $group) = @_;
+
+ my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime);
+ my $file = VyattaKeepalived::get_state_file($intf, $group);
+ my $time = time();
+ my $line = "$time $intf $group $state $timestamp";
+ open my $fh, ">", $file;
+ print $fh $line;
+ close $fh;
+}
+
+my $vrrp_state = $ARGV[0];
+my $vrrp_intf = $ARGV[1];
+my $vrrp_group = $ARGV[2];
+my $vrrp_vip = $ARGV[3];
+
+my $sfile = VyattaKeepalived::get_state_file($vrrp_intf, $vrrp_group);
+my ($old_time, $old_intf, $old_group, $old_state, $old_ltime) =
+ VyattaKeepalived::vrrp_state_parse($sfile);
+if (defined $old_state and $vrrp_state eq $old_state) {
+ #
+ # restarts call the transition script even if it really hasn't
+ # changed.
+ #
+ exit 0;
+}
+
+VyattaKeepalived::vrrp_log("$vrrp_intf $vrrp_group transition to $vrrp_state");
+vrrp_state_log($vrrp_state, $vrrp_intf, $vrrp_group);
+my $mfile = VyattaKeepalived::get_master_file($vrrp_intf, $vrrp_group);
+if ($vrrp_state eq "backup") {
+ snoop_for_master($vrrp_intf, $vrrp_group, $vrrp_vip, $mfile);
+} elsif ($vrrp_state eq "master") {
+ system("rm -f $mfile");
+}
+
+exit 0;
+
+# end of file
+
+
+
+