diff options
Diffstat (limited to 'scripts/keepalived')
-rwxr-xr-x | scripts/keepalived/VyattaKeepalived.pm | 181 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-keepalived.pl | 184 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-show-vrrp.pl | 158 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-vrrp-state.pl | 89 |
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 + + + + |