diff options
author | John Southworth <john.southworth@vyatta.com> | 2012-05-15 13:52:52 -0700 |
---|---|---|
committer | John Southworth <john.southworth@vyatta.com> | 2012-05-15 13:52:52 -0700 |
commit | c43ac111560888ef0393aecbd54202f1a8b7b9fc (patch) | |
tree | 8ac60bc10d0963ae033eb9752601f0b8d6e2b538 /scripts | |
parent | 28bcc9d884550e630895bb65151d2d857e80478b (diff) | |
download | vyatta-cfg-system-c43ac111560888ef0393aecbd54202f1a8b7b9fc.tar.gz vyatta-cfg-system-c43ac111560888ef0393aecbd54202f1a8b7b9fc.zip |
Move VRRP to its own package
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/keepalived/vyatta-clear-vrrp.pl | 303 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-keepalived.pl | 668 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-show-vrrp.pl | 322 | ||||
-rwxr-xr-x | scripts/keepalived/vyatta-vrrp-state.pl | 107 |
4 files changed, 0 insertions, 1400 deletions
diff --git a/scripts/keepalived/vyatta-clear-vrrp.pl b/scripts/keepalived/vyatta-clear-vrrp.pl deleted file mode 100755 index 34c0327e..00000000 --- a/scripts/keepalived/vyatta-clear-vrrp.pl +++ /dev/null @@ -1,303 +0,0 @@ -#!/usr/bin/perl -# -# Module: vyatta-clear-vrrp.pl -# -# **** License **** -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# This code was originally developed by Vyatta, Inc. -# Portions created by Vyatta are Copyright (C) 2007-2009 Vyatta, Inc. -# All Rights Reserved. -# -# Author: Stig Thormodsrud -# Date: May 2008 -# Description: Script to clear vrrp -# -# **** End License **** -# - -use lib '/opt/vyatta/share/perl5/'; -use Vyatta::Keepalived; -use Vyatta::Interface; -use Vyatta::Misc; - -use Getopt::Long; -use Sys::Syslog qw(:standard :macros); - -use strict; -use warnings; - -my $conf_file = get_conf_file(); - - -sub keepalived_write_file { - my ($file, $data) = @_; - - open(my $fh, '>', $file) || die "Couldn't open $file - $!"; - print $fh $data; - close $fh; -} - -sub set_instance_inital_state { - my ($instance, $init) = @_; - - if ($init eq 'MASTER' and $instance =~ /state \s+ BACKUP/ix) { - if ($instance !~ s/state \s+ BACKUP/state MASTER/ix) { - print "Error: unable to replace BACKUP/MASTER\n"; - } - } elsif ($init eq 'BACKUP' and $instance =~ /state \s+ MASTER/ix) { - if ($instance !~ s/state \s+ MASTER/state BACKUP/ix) { - print "Error: unable to replace MASTER/BACKUP\n"; - } - } - return $instance; -} - -my $brace_block; - -sub vrrp_extract_instance { - my ($conf, $instance) = @_; - - # - # regex to find a balanced group of squiggly braces {{{ }}} - # - $brace_block = qr/ - \{ # 1st brace - ( - [^\{\}]+ # anything but brace - | # or - (??{ $brace_block }) # another brace_block - )* - \} # matching brace - /x; - - # - # regex to match instance: - # - # vrrp_instance vyatta-eth1.100-15 { - # state MASTER - # interface eth1 - # virtual_router_id 15 - # virtual_ipaddress { - # 1.1.1.1 - # } - # } - # - my $instance_regex = qr/(vrrp_instance \s+ $instance \s+ $brace_block)/x; - - # - # replace the instance with nothing - # - my $match_instance; - if ($conf =~ s/($instance_regex)//) { - $match_instance = $1; - } else { - return ($conf, undef); - } - - return ($conf, $match_instance); -} - -sub get_vrrp_intf_group { - my @array; - - # - # return an array of hashes that contains all the intf/group pairs - # - my $config = new Vyatta::Config; - - foreach my $name ( getInterfaces() ) { - my $intf = new Vyatta::Interface($name); - next unless $intf; - my $path = $intf->path(); - $config->setLevel($path); - if ($config->existsOrig('vrrp')) { - $path = "$path vrrp vrrp-group"; - $config->setLevel($path); - my @groups = $config->listOrigNodes(); - foreach my $group (@groups) { - my %hash; - $hash{'intf'} = $name; - $hash{'group'} = $group; - $hash{'path'} = "$path $group"; - push @array, {%hash}; - } - } - } - - return @array; -} - -sub set_inital_state { - my $conf = shift; - - my $new_conf = ''; - - # - # find all intf/groups, extract instance, set init state - # - my @vrrp_instances = get_vrrp_intf_group(); - - my $tmp_conf = $conf; - foreach my $hash (@vrrp_instances) { - my $intf = $hash->{'intf'}; - my $group = $hash->{'group'}; - my $instance = 'vyatta-' . "$intf" . '-' . "$group"; - my $match_instance; - ($tmp_conf, $match_instance) = - vrrp_extract_instance($tmp_conf, $instance); - if (defined $match_instance) { - my $init = vrrp_get_init_state($intf, $group, '', 'false'); - $match_instance = set_instance_inital_state($match_instance, $init); - $new_conf .= $match_instance . "\n\n"; - } - } - $new_conf = $tmp_conf . $new_conf; - - return $new_conf; -} - - -# -# 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; -} - -openlog($0, '', LOG_USER); -my $login = getlogin(); - -# -# clear_process -# -if ($action eq 'clear_process') { - syslog('warning', "clear vrrp process requested by $login"); - if (Vyatta::Keepalived::is_running()) { - print "Restarting VRRP...\n"; - restart_daemon(get_conf_file()); - } else { - print "Starting VRRP...\n"; - start_daemon(get_conf_file()); - } - exit 0; -} - -# -# clear_master -# -if ($action eq 'clear_master') { - - # - # The kludge here to force a vrrp instance to switch from master to - # backup is to read the keepalived config, remove the instance to be - # cleared, signal the daemon to reread it's config. This will cause - # keepalived to see the old instance missing and send a priorty 0 - # advert to cause the backup to immediately take over master. Once - # that is done we put back the orginal config and signal the daemon - # again. Note: if the instance if preempt=true, then it may immediately - # try to become master again. - # - - if (! defined $vrrp_intf || ! defined $vrrp_group) { - print "must include interface & group\n"; - exit 1; - } - - my $instance = 'vyatta-' . "$vrrp_intf" . '-' . "$vrrp_group"; - my $state_file = Vyatta::Keepalived::get_state_file($vrrp_intf, $vrrp_group); - if (! -f $state_file) { - print "Invalid interface/group [$vrrp_intf][$vrrp_group]\n"; - exit 1; - } - - my ($start_time, $intf, $group, $state, $ltime) = - Vyatta::Keepalived::vrrp_state_parse($state_file); - if ($state ne 'master') { - print "vrrp group $vrrp_group on $vrrp_intf is already in backup\n"; - exit 1; - } - - syslog('warning', "clear vrrp master [$instance] requested by $login"); - Vyatta::Keepalived::vrrp_log("vrrp clear_master $vrrp_intf $vrrp_group"); - - # should add a file lock - local($/); # slurp mode - open my $f, '<', $conf_file or die "Couldn't open $conf_file\n"; - my $conf = <$f>; - close $f; - - my $sync_group = list_vrrp_sync_group($intf, $group); - my @instances = (); - if (defined($sync_group)) { - print "vrrp group $vrrp_group on $vrrp_intf is in sync-group " - . "$sync_group\n"; - @instances = list_vrrp_sync_group_members($sync_group); - } else { - push @instances, $instance; - } - - my $new_conf = $conf; - my $clear_instances; - foreach my $inst (@instances) { - my $match_instance; - print "Forcing $inst to BACKUP...\n"; - Vyatta::Keepalived::vrrp_log("vrrp extract $inst"); - ($new_conf, $match_instance) = vrrp_extract_instance($new_conf, $inst); - if ($match_instance !~ /nopreempt/) { - print "Warning: $instance is in preempt mode"; - print " and may retake master\n"; - - } - $match_instance = set_instance_inital_state($match_instance, 'BACKUP'); - $clear_instances .= "$match_instance\n"; - } - - # - # need to set the correct initial state for the remaining instances - # - $new_conf = set_inital_state($new_conf); - - # - # create the temporary config file - # - my $tmp_conf_file = $conf_file . ".$$"; - keepalived_write_file($tmp_conf_file, $new_conf); - - my $conf_file_bak = $conf_file . '.bak'; - system("mv $conf_file $conf_file_bak"); - system("cp $tmp_conf_file $conf_file"); - - restart_daemon($conf_file); - - sleep(3); - - # - # add modified instance back and restart - # - $new_conf .= "\n" . $clear_instances . "\n"; - - keepalived_write_file($conf_file, $new_conf); - Vyatta::Keepalived::restart_daemon($conf_file); - - system("rm $conf_file_bak $tmp_conf_file"); - exit 0; -} - -exit 0; - -# end of file diff --git a/scripts/keepalived/vyatta-keepalived.pl b/scripts/keepalived/vyatta-keepalived.pl deleted file mode 100755 index 60b02608..00000000 --- a/scripts/keepalived/vyatta-keepalived.pl +++ /dev/null @@ -1,668 +0,0 @@ -#!/usr/bin/perl -# -# Module: vyatta-keepalived.pl -# -# **** License **** -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# This code was originally developed by Vyatta, Inc. -# Portions created by Vyatta are Copyright (C) 2007-2009 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 Vyatta::Config; -use Vyatta::Keepalived; -use Vyatta::Interface; -use Vyatta::ConntrackSync; -use Vyatta::Misc; -use Getopt::Long; - -use strict; -use warnings; - -my ( $action, $vrrp_intf, $vrrp_group, $vrrp_vip, $ctsync ); -my ( $conf_file, $changes_file ); -my %HoA_sync_groups; -my $ctsync_script = "/opt/vyatta/sbin/vyatta-vrrp-conntracksync.sh"; - -sub validate_source_addr { - my ( $ifname, $source_addr ) = @_; - - if ( defined $source_addr ) { - unless (is_local_address ( $source_addr )) { - vrrp_log("hello-source not local"); - return "hello-source-address [$source_addr] must be " - . "configured on the interface\n"; - } - return; - } - - # if the hello-source-address wasn't configured, check that the - # interface has an IPv4 address configured on it. - my $primary_addr = vrrp_get_primary_addr($ifname); - if ( ! defined $primary_addr ) { - vrrp_log("no primary or hello-source"); - return "must configure either a primary address on [$ifname] or" - . " a hello-source-address\n"; - } - return; -} - -sub get_ctsync_syncgrp { - my ($origfunc) = @_; - my $failover_sync_grp = undef; - - my $listnodesfunc = "listNodes"; - my $returnvalfunc = "returnValue"; - if ( defined $origfunc ) { - $listnodesfunc = "listOrigNodes"; - $returnvalfunc = "returnOrigValue"; - } - - my @failover_mechanism = - Vyatta::ConntrackSync::get_conntracksync_val( $listnodesfunc, - "failover-mechanism" ); - - if ( defined $failover_mechanism[0] && $failover_mechanism[0] eq 'vrrp' ) { - $failover_sync_grp = - Vyatta::ConntrackSync::get_conntracksync_val( $returnvalfunc, - "failover-mechanism $failover_mechanism[0] sync-group" ); - } - return $failover_sync_grp; -} - -sub keepalived_get_values { - my ( $intf, $path , $noerr) = @_; - - my @loc; - my $err; - my @errs = (); - my $output = ''; - my $config = new Vyatta::Config; - - my $state_transition_script = get_state_script(); - - my $on_off = "off"; - $on_off = "on" if $noerr; - vrrp_log("keepalived_get_values [$intf][$path] noerr = $on_off"); - $config->setLevel($path); - if ( $config->isDeleted("vrrp") ) { - return ($output, @errs) if $noerr; - vrrp_log("vrrp_instance [$intf] deleted"); - return ( $output, @errs ); - } - - $config->setLevel("$path vrrp vrrp-group"); - my @groups = $config->listNodes(); - if (scalar(@groups) < 1) { - return ($output, @errs) if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group"); - $err = "must define a vrrp-group"; - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - return ( $output, @errs ); - } - foreach my $group (@groups) { - my $vrrp_instance = "vyatta-$intf-$group"; - $config->setLevel("$path vrrp vrrp-group $group"); - if ( $config->exists("disable") ) { - next if $noerr; - vrrp_log("$vrrp_instance disabled - skipping"); - my $state_file = get_state_file( $intf, $group ); - unlink($state_file); - next; - } - my @vips = $config->returnValues("virtual-address"); - my $num_vips = scalar(@vips); - if ( $num_vips == 0 ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - $err = "must define a virtual-address for vrrp-group $group"; - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - if ( $num_vips > 20 ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - $err = "can not set more than 20 VIPs per group"; - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - - my $use_vmac = 0; - my $transition_intf = $intf; - if ( $config->exists("interface") ) { - $use_vmac = 1; - $transition_intf = "$intf"."v"."$group"; - } - - my $priority = $config->returnValue("priority"); - if ( !defined $priority ) { - $priority = 100; # Default backup priority is 100 from RFC. - } - my $address_owner = 0; - $address_owner = 1 if ($priority == 255 && $use_vmac == 1); - my $preempt = $config->returnValue("preempt"); - if (defined $preempt && $address_owner == 1){ - if ($preempt ne "true") { # the handling of default in configuration is odd so we need to allow it to be set to true... - $err = "cannot define preempt if this is the address owner"; - if ( defined $err ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - } - } - if ( !defined $preempt ) { - $preempt = "true"; - } - my $preempt_delay = $config->returnValue("preempt-delay"); - if ( defined $preempt_delay and $preempt eq "false" ) { - print "Warning: preempt delay is ignored when preempt=false\n"; - } - my $advert_int = $config->returnValue("advertise-interval"); - if ( !defined $advert_int ) { - $advert_int = 1; - } - my $sync_group = $config->returnValue("sync-group"); - if ( defined $sync_group && $sync_group ne "" ) { - push @{ $HoA_sync_groups{$sync_group} }, $vrrp_instance; - } - my $hello_source_addr = $config->returnValue("hello-source-address"); - $err = validate_source_addr( $intf, $hello_source_addr ) if (!$address_owner == 1); - if ( defined $err ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - if (defined $hello_source_addr && $address_owner == 1){ - $err = "cannot define hello-source-address if this is the address owner"; - if ( defined $err ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - } elsif ($address_owner == 1) { - $hello_source_addr = $vips[0]; - $hello_source_addr =~ s/(.*?)\/.*/$1/; - } - - $config->setLevel("$path vrrp vrrp-group $group"); - my ($auth_type, $auth_pass) = (undef, undef); - if ($config->exists('authentication')) { - $config->setLevel("$path vrrp vrrp-group $group authentication"); - $auth_type = $config->returnValue("type"); - $auth_pass = $config->returnValue("password"); - if ( defined $auth_type ) { - $auth_type = "PASS" if $auth_type eq "plaintext-password"; - $auth_type = uc($auth_type); - if ( !defined $auth_pass ) { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - $err = "vrrp authentication password not set"; - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - } else { - next if $noerr; - @loc = split(/ /, "$path vrrp vrrp-group $group"); - $err = "vrrp authentication type not set"; - Vyatta::Config::outputError(\@loc, $err); - push @errs, $err; - next; - } - } - - $config->setLevel("$path vrrp vrrp-group $group run-transition-scripts"); - my $run_backup_script = $config->returnValue("backup"); - if ( !defined $run_backup_script ) { - $run_backup_script = "null"; - } - my $run_fault_script = $config->returnValue("fault"); - if ( !defined $run_fault_script ) { - $run_fault_script = "null"; - } - my $run_master_script = $config->returnValue("master"); - if ( !defined $run_master_script ) { - $run_master_script = "null"; - } - - # We now have the values and have validated them, so - # generate the config. - - $output .= "vrrp_instance $vrrp_instance \{\n"; - my $init_state; - if ( defined $ctsync ) { - - # check if this group is part of conntrack-sync vrrp sync-group - my $ctsync_syncgrp = get_ctsync_syncgrp(); - my $vrrpsyncgrp = - list_vrrp_sync_group( $intf, $group, 'returnOrigPlusComValue' ); - if ( defined $ctsync_syncgrp - && defined $vrrpsyncgrp - && ( $ctsync_syncgrp eq $vrrpsyncgrp ) ) - { - $init_state = 'BACKUP'; - } else { - $init_state = vrrp_get_init_state( $intf, $group, $vips[0], $preempt ); - } - } else { - $init_state = vrrp_get_init_state( $intf, $group, $vips[0], $preempt ); - } - $output .= "\tstate $init_state\n"; - $output .= "\tinterface $intf\n"; - $output .= "\tvirtual_router_id $group\n"; - if ($use_vmac) { - $output .= "\tuse_vmac $intf"; - $output .= "v"; - $output .= "$group\n"; - } - $output .= "\tpriority $priority\n"; - if ( $preempt eq "false" ) { - $output .= "\tnopreempt\n"; - } - if ( defined $preempt_delay ) { - $output .= "\tpreempt_delay $preempt_delay\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"; - } - if ( defined $hello_source_addr ) { - $output .= "\tmcast_src_ip $hello_source_addr\n"; - } - $output .= "\tvirtual_ipaddress \{\n"; - foreach my $vip (@vips) { - $output .= "\t\t$vip\n"; - } - $output .= "\t\}\n"; - $output .= "\tnotify_master \"$state_transition_script master "; - $output .= "$intf $group $transition_intf \'$run_master_script\' @vips\" \n"; - $output .= "\tnotify_backup \"$state_transition_script backup "; - $output .= "$intf $group $transition_intf \'$run_backup_script\' @vips\" \n"; - $output .= "\tnotify_fault \"$state_transition_script fault "; - $output .= "$intf $group $transition_intf \'$run_fault_script\' @vips\" \n"; - $output .= "\}\n\n"; - } - - return ( $output, @errs ); -} - -sub vrrp_get_sync_groups { - - my $output = ""; - - foreach my $sync_group ( keys %HoA_sync_groups ) { - $output .= "vrrp_sync_group $sync_group \{\n\tgroup \{\n"; - foreach my $vrrp_instance ( 0 .. $#{ $HoA_sync_groups{$sync_group} } ) { - $output .= "\t\t$HoA_sync_groups{$sync_group}[$vrrp_instance]\n"; - } - $output .= "\t\}\n"; - - ## add conntrack-sync part here if configured ## - my $origfunc = undef; - $origfunc = 'true' if !defined $ctsync; - my $failover_sync_grp = get_ctsync_syncgrp($origfunc); - if ( defined $failover_sync_grp && $failover_sync_grp eq $sync_group ) { - $output .= "\tnotify_master \"$ctsync_script master $sync_group\"\n"; - $output .= "\tnotify_backup \"$ctsync_script backup $sync_group\"\n"; - $output .= "\tnotify_fault \"$ctsync_script fault $sync_group\"\n"; - } - $output .= "\}\n"; - } - return $output; -} - -sub vrrp_read_changes { - my @lines = (); - return @lines if !-e $changes_file; - open( my $FILE, "<", $changes_file ) or die "Error: read $!"; - @lines = <$FILE>; - close($FILE); - chomp @lines; - return @lines; -} - -sub vrrp_save_changes { - my @list = @_; - - my $num_changes = scalar(@list); - vrrp_log("saving changes file $num_changes"); - open( my $FILE, ">", $changes_file ) or die "Error: write $!"; - print $FILE join( "\n", @list ), "\n"; - close($FILE); -} - -sub vrrp_find_changes { - - my @list = (); - my $config = new Vyatta::Config; - my $vrrp_instances = 0; - - foreach my $name ( getInterfaces() ) { - my $intf = new Vyatta::Interface($name); - next unless $intf; - my $path = $intf->path(); - $config->setLevel($path); - if ( $config->exists("vrrp") ) { - my %vrrp_status_hash = $config->listNodeStatus("vrrp"); - my ( $vrrp, $vrrp_status ) = each(%vrrp_status_hash); - if ( $vrrp_status ne "static" ) { - push @list, $name; - vrrp_log("$vrrp_status found $name"); - } - } - - # - # Now look for deleted from the origin tree - # - $config->setLevel($path); - if ( $config->isDeleted("vrrp") ) { - push @list, $name; - vrrp_log("Delete found $name"); - } - - } - - my $num = scalar(@list); - vrrp_log("Start transation: $num changes"); - if ($num) { - vrrp_save_changes(@list); - } - return $num; -} - -sub remove_from_changes { - my $intf = shift; - - my @lines = vrrp_read_changes(); - if ( scalar(@lines) < 1 ) { - - # - # we shouldn't get to this point, but try to handle it if we do - # - vrrp_log("unexpected remove_from_changes()"); - unlink($changes_file); - return 0; - } - my @new_lines = (); - foreach my $line (@lines) { - if ( $line =~ /$intf$/ ) { - vrrp_log("remove_from_changes [$line]"); - } else { - push @new_lines, $line; - } - } - - my $num_changes = scalar(@new_lines); - if ( $num_changes > 0 ) { - vrrp_save_changes(@new_lines); - } else { - unlink($changes_file); - } - return $num_changes; -} - -sub vrrp_update_config { - - my @errs = (); - my $output; - - my $config = new Vyatta::Config; - my $vrrp_instances = 0; - - %HoA_sync_groups = (); - foreach my $name ( getInterfaces() ) { - my $intf = new Vyatta::Interface($name); - next unless $intf; - my $path = $intf->path(); - $config->setLevel($path); - if ( $config->exists("vrrp") ) { - - # - # keepalived gets real grumpy with interfaces that - # don't exist, so skip vlans that haven't been - # instantiated yet (typically occurs at boot up). - # - if ( !( -d "/sys/class/net/$name" ) ) { - push @errs, "$name doesn't exist"; - next; - } - my ( $inst_output, @inst_errs ) = keepalived_get_values( $name, $path, 1 ); - if ( scalar(@inst_errs) ) { - push @errs, @inst_errs; - } else { - $output .= $inst_output; - $vrrp_instances++; - } - } - } - - if ( $vrrp_instances > 0 ) { - my $sync_groups = vrrp_get_sync_groups(); - if ( defined $sync_groups && $sync_groups ne "" ) { - $output = $sync_groups . $output; - } - $output = "global_defs {\n\tenable_traps\n}\n" . $output; - $output = "#\n# autogenerated by $0\n#\n\n" . $output; - keepalived_write_file( $conf_file, $output ); - } - return ( $vrrp_instances, @errs ); -} - -sub keepalived_write_file { - my ( $file, $data ) = @_; - - open( my $fh, '>', $file ) || die "Couldn't open $file - $!"; - print $fh $data; - close $fh; -} - -# -# main -# -GetOptions( - "vrrp-action=s" => \$action, - "intf=s" => \$vrrp_intf, - "group=s" => \$vrrp_group, - "vip=s" => \$vrrp_vip, - "ctsync=s" => \$ctsync, -); - -if ( !defined $action ) { - print "no action\n"; - exit 1; -} - - -# -# run op mode command first -# -if ( $action eq "list-vrrp-intf" ) { - my @intfs = list_vrrp_intf(); - print join( ' ', @intfs ); - exit 0; -} - -if ( $action eq "list-vrrp-group" ) { - if ( !defined $vrrp_intf ) { - print "must include interface\n"; - exit 1; - } - my @groups = list_vrrp_group($vrrp_intf); - print join( ' ', @groups ); - exit 0; -} - -# -# end of op mode commands -# - - -# -# This script can be called from two places : -# 1. a vrrp node under one of the interfaces -# 2. service conntrack-sync when conntrack-sync uses VRRP as failover-mechanism -# -# when called from conntrack-sync; we just need to add/remove config -# for sync-group transition scripts and restart daemon. We do NOT -# perform any other actions usually done in the update part of this -# script otherwise -# - -if ( !defined $ctsync ) { - - # make sure sync-group used by ctsync has not been deleted - - my $failover_sync_grp = get_ctsync_syncgrp(); - if ( defined $failover_sync_grp ) { - - # make sure vrrp sync-group exists - my $sync_grp_exists = 'false'; - my @vrrp_intfs = list_vrrp_intf('exists'); - foreach my $vrrp_intf (@vrrp_intfs) { - my @vrrp_groups = list_vrrp_group( $vrrp_intf, 'listNodes' ); - foreach my $vrrp_group (@vrrp_groups) { - my $sync_grp = - list_vrrp_sync_group( $vrrp_intf, $vrrp_group, 'returnValue' ); - if ( defined $sync_grp && $sync_grp eq "$failover_sync_grp" ) { - $sync_grp_exists = 'true'; - last; - } - } - last if $sync_grp_exists eq 'true'; - } - - if ( $sync_grp_exists eq 'false' ) { - print "sync-group $failover_sync_grp used for conntrack-sync" - . " is either deleted or undefined\n"; - exit 1; - } - } - -} - -# -# UPDATE action: the logic for "update" is far more complex than it should -# be due to limitations of the @&!#ing cli. Ideally we would have just one -# end node at the top level 'interfaces' level. That way we would know that -# all the vif's and bond interfaces have been created and we could call this -# function once to generate the entire keepalived conf file and restart the -# daemon 1 time. Unfortuately the cli doesn't support nested end nodes, so -# we have to put and end node at every vrrp node and call this function for -# every vrrp instance, but since we only want to start the daemon once we -# need to keep track of some state. The first call checks if the "changes" -# file exists, if not it search for all the vrrp instances that have changed -# and adds them to the changes file. As each instance is processed it is -# removed from changes and when there are no more changes the daemon is -# started/restarted/stopped. Now since we need to run the script for each -# instance, we can NOT do "commit" checks in the node.def files since that -# prevents the end node from getting called. So all the validation needs to -# be in this script, but why not just do all the work once when the changes -# file is empty? Well the problem then becomes that when the validation -# fails, the non-zero exit needs to be associated with the end node otherwise -# the cli will assume it's good push it through to the active config. So -# we need to do only the validation for the instance being processed and -# then on the last instance generate the full conf file and signal the daemon -# if any changes have been made even if the last instance has a non-zero exit. -# -if ( $action eq "update" ) { - $changes_file = get_changes_file(); - $conf_file = get_conf_file(); - vrrp_log("vrrp update $vrrp_intf") if defined $vrrp_intf; - if ( !-e $changes_file ) { - my $num_changes = vrrp_find_changes(); - if ( $num_changes == 0 ) { - # - # Shouldn't happen, but ... - # - one place were this has been know to occur is if a vif is deleted - # that has a vrrp instance under it. Because the cli doesn't - # reverse priorities on delete, then the vrrp under the vif - # is gone by the time we get here. - # - vrrp_log("unexpected 0 changes"); - } - } - - my $intf = new Vyatta::Interface($vrrp_intf); - if (! defined $intf) { - die "Error: invalid interface [$vrrp_intf]"; - } - my $path = $intf->path(); - my ( $inst_output, @inst_errs ) = keepalived_get_values( $vrrp_intf, $path ); - my $more_changes = remove_from_changes($vrrp_intf); - vrrp_log("more changes $more_changes"); - - if ( $more_changes == 0 ) { - my ( $vrrp_instances, @errs ) = vrrp_update_config(); - vrrp_log("instances $vrrp_instances"); - if ( $vrrp_instances > 0 ) { - restart_daemon($conf_file); - # The changes_file should already be gone by this point, but - # this is the "belt & suspenders" approach. - unlink($changes_file); - vrrp_log("end transaction\n"); - } elsif ( $vrrp_instances == 0 ) { - stop_daemon(); - unlink($conf_file); - unlink($changes_file); - vrrp_log("end transaction\n"); - } - } - if ( scalar(@inst_errs) ) { - vrrp_log( join( "\n", @inst_errs ) ); - exit 1; - } - exit 0; -} - -if ( $action eq "update-ctsync" ) { - vrrp_log("vrrp update conntrack-sync"); - $conf_file = get_conf_file(); - my ( $vrrp_instances, @errs ) = vrrp_update_config(); - vrrp_log("instances $vrrp_instances"); - if ($vrrp_instances > 0) { - restart_daemon($conf_file); - } - exit 0; -} - -if ( $action eq "delete" ) { - if ( !defined $vrrp_intf || !defined $vrrp_group ) { - print "must include interface & group"; - exit 1; - } - vrrp_log("vrrp delete $vrrp_intf $vrrp_group"); - my $state_file = get_state_file( $vrrp_intf, $vrrp_group ); - unlink($state_file); - exit 0; -} - -exit 0; - -# end of file diff --git a/scripts/keepalived/vyatta-show-vrrp.pl b/scripts/keepalived/vyatta-show-vrrp.pl deleted file mode 100755 index 3eadd605..00000000 --- a/scripts/keepalived/vyatta-show-vrrp.pl +++ /dev/null @@ -1,322 +0,0 @@ -#!/usr/bin/perl -# -# Module: vyatta-show-vrrp.pl -# -# **** License **** -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# 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 Vyatta::Keepalived; -use Vyatta::Interface; - -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 get_state_link { - my $intf_name = shift; - - my $intf = new Vyatta::Interface($intf_name); - die "Unknown interface [$intf_name]" unless $intf; - - my ($state, $link); - if ($intf->up()) { - $state = 'up'; - } else { - $state = 'admin down'; - } - - if ($intf->running() == 1) { - $link = 'up'; - } else { - $link = 'down'; - } - return ($state, $link); -} - -sub parse_arping { - my $file = shift; - - return "" if ! -f $file; - - open (my $FD, '<', $file) - or die "Can't open file $file"; - - my @lines = <$FD>; - close $FD; - my $mac = undef; - foreach my $line (@lines) { - # regex for xx:xx:xx:xx:xx:xx - if ($line =~ /(([0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2})/) { - $mac = $1; - return uc($mac); - } - } - return $mac; -} - -sub get_master_info { - my ($intf, $group, $vip) = @_; - - # remove mask if vip has one - if ($vip =~ /([\d.]+)\/\d+/) { - $vip = $1; - } - - # Calling snoop_for_master() is an expensive operation, so we - # normally only do it on vrrp state transitions by calling the - # vyatta-vrrp-state.pl script. However if there are more than - # 2 routers in the vrrp group when a transition occurs, then - # only those 2 routes that transitioned will know who the current - # master is and it's priority. So here we will arp for the VIP - # address and compare it to our masterfile. If it doesn't match - # then we will snoop for the new master. - - my $master_file = Vyatta::Keepalived::get_master_file($intf, $group); - my $arp_file = "$master_file.arp"; - my $source_ip = (vrrp_get_config($intf, $group))[0]; - - my $interface = new Vyatta::Interface($intf); - my $arp_intf = $intf; - if ($interface->vif()) { - $arp_intf = $interface->physicalDevice(); - } - my $cmd = "/usr/bin/arping -c1 -f -I $arp_intf -s $source_ip $vip"; - system("$cmd > $arp_file"); - my $arp_mac = parse_arping($arp_file); - - if ( ! -f $master_file) { - Vyatta::Keepalived::snoop_for_master($intf, $group, $vip, 2); - } - - if ( -f $master_file) { - my $master_ip = `grep ip.src $master_file 2> /dev/null`; - my $master_mac = `grep eth.src $master_file 2> /dev/null`; - chomp $master_ip; chomp $master_mac; - - # regex for show="xx:xx:xx:xx:xx:xx - if (defined $master_mac and - $master_mac =~ /show=\"(([0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2})/) - { - $master_mac = uc($1); - if (defined($arp_mac) and ($arp_mac ne $master_mac)) { - Vyatta::Keepalived::snoop_for_master($intf, $group, $vip, 2); - $master_ip = `grep ip.src $master_file 2> /dev/null`; - } - } - - if (defined $master_ip and - $master_ip =~ m/show=\"(\d+\.\d+\.\d+\.\d+)\"/) - { - $master_ip = $1; - } else { - $master_ip = "unknown"; - system("mv $master_file /tmp"); - } - - my $priority = `grep vrrp.prio $master_file 2> /dev/null`; - chomp $priority; - if (defined $priority and $priority =~ m/show=\"(\d+)\"/) { - $priority = $1; - } else { - $priority = "unknown"; - } - - return ($master_ip, $priority, $master_mac); - } else { - return ('unknown', 'unknown', ''); - } -} - -sub vrrp_showsummary { - my ($file) = @_; - my $owner = "no"; - my ($start_time, $intf, $group, $state, $ltime) = - Vyatta::Keepalived::vrrp_state_parse($file); - my ($interface_state, $link) = get_state_link($intf); - if ($state eq "master" || $state eq "backup" || $state eq "fault") { - my ($primary_addr, $priority, $preempt, $advert_int, $auth_type, - $vmac_interface, - @vips) = Vyatta::Keepalived::vrrp_get_config($intf, $group); - my $format = "\n%-16s%-8s%-8s%-16s%-10s%-9s%-13s"; - my $vip = shift @vips; - if ($vmac_interface) { - $intf = "$intf" . "v" . "$group"; - $owner = "yes" if ($priority == 255); - } - printf($format, $intf, $group, 'vip', $vip, $link, $owner, $state); - foreach my $vip (@vips){ - printf("\n%-24s%-8s%-16s", ' ', 'vip', $vip); - } - } else { - print "Physical interface $intf, State: unknown\n"; - } -} - -sub vrrp_show { - my ($file) = @_; - my $owner = "no"; - my $now_time = time; - my ($start_time, $intf, $group, $state, $ltime) = - Vyatta::Keepalived::vrrp_state_parse($file); - my ($interface_state, $link) = get_state_link($intf); - my $first_vip = ''; - if ($state eq "master" || $state eq "backup" || $state eq "fault") { - my ($primary_addr, $priority, $preempt, $advert_int, $auth_type, - $vmac_interface, - @vips) = Vyatta::Keepalived::vrrp_get_config($intf, $group); - my $sync = list_vrrp_sync_group($intf, $group); - print "Physical interface: $intf, Source Address $primary_addr\n"; - if ($vmac_interface) { - my $vma = "$intf" . "v" . "$group"; - $owner = "yes" if ($priority == 255); - print " Virtual MAC interface: $vma\n"; - print " Address Owner: $owner\n"; - } - print " Interface state: $link, Group $group, State: $state\n"; - print " Priority: $priority, Advertisement interval: $advert_int, "; - print "Authentication type: $auth_type\n"; - my $vip_count = scalar(@vips); - my $string = " Preempt: $preempt, VIP count: $vip_count, VIP: "; - my $strlen = length($string); - print $string; - foreach my $vip (@vips) { - if ($first_vip eq '') { - $first_vip = $vip; - } - if ($vip_count != scalar(@vips)) { - print " " x $strlen; - } - print "$vip\n"; - $vip_count--; - } - if ($state eq "master") { - print " Master router: $primary_addr\n"; - } elsif ($state eq "backup") { - my ($master_rtr, $master_prio,$master_mac) = - get_master_info($intf, $group, $first_vip); - print " Master router: $master_rtr"; - if ($master_mac ne '') { - print " [$master_mac]" - } - print ", Master Priority: $master_prio\n"; - } - print " Sync-group: $sync\n" if defined $sync; - } else { - print "Physical interface $intf, State: unknown\n"; - } - my $elapsed = elapse_time($start_time, $now_time); - print " Last transition: $elapsed\n\n"; - if ($state eq "backup") { - - } -} - -# -# main -# -my @intfs = ("eth", "bond"); -my $group = "all"; -my $showsummary = 0; - -if ($#ARGV >= 0) { - if ($ARGV[0] eq "summary") { - $showsummary = 1; - } else { - @intfs = ($ARGV[0]); - } -} - -if ($#ARGV == 1) { - $group = $ARGV[1]; -} - -if (!Vyatta::Keepalived::is_running()) { - print "VRRP isn't running\n"; - exit 1; -} - -my $display_func; -if ($showsummary == 1) { - $display_func = \&vrrp_showsummary; - my $format = '%-16s%-8s%-8s%-16s%-10s%-9s%-13s%s'; - printf($format, '', 'VRRP', 'Addr', '', 'Interface','Address', 'VRRP', "\n"); - printf($format, 'Interface', 'Group', 'Type', 'Address', 'State','Owner', 'State', - "\n"); - printf($format, '-' x 9, '-' x 5, '-' x 4 , '-' x 7, '-' x 5, '-' x 5, '-' x 5, '', ); -} else { - $display_func = \&vrrp_show; -} - -foreach my $intf (@intfs) { - my $intf_vrid; - if ($intf =~ m/(\w+)\.(\d+)v(\d+)/){ - $intf = "$1.$2"; - $intf_vrid = $3; - } elsif ($intf =~ m/(\w+)v(\d+)/){ - $intf = $1; - $intf_vrid = $2; - } - next if ($group ne 'all' && $intf_vrid && $intf_vrid != $group); - $group = $intf_vrid if ($group eq 'all' && $intf_vrid); - my @state_files = Vyatta::Keepalived::get_state_files($intf, $group); - foreach my $state_file (@state_files) { - &$display_func($state_file); - } -} - -exit 0; - -#end of file diff --git a/scripts/keepalived/vyatta-vrrp-state.pl b/scripts/keepalived/vyatta-vrrp-state.pl deleted file mode 100755 index 83fd80b0..00000000 --- a/scripts/keepalived/vyatta-vrrp-state.pl +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/perl -# -# Module: vyatta-vrrp-state.pl -# -# **** License **** -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# 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 strict; -use warnings; - -use lib "/opt/vyatta/share/perl5/"; -use Vyatta::Keepalived; -use POSIX; - -sub vrrp_state_log { - my ($state, $intf, $group) = @_; - - my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime); - my $file = Vyatta::Keepalived::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]; -# transition interface will contain the vmac interface -# when one is present and the vrrp interface when one is not -my $transition_intf = $ARGV[3]; -my $vrrp_transitionscript = $ARGV[4]; -my @vrrp_vips; -foreach my $arg (5 .. $#ARGV) { - push @vrrp_vips, $ARGV[$arg]; -} - -my $sfile = Vyatta::Keepalived::get_state_file($vrrp_intf, $vrrp_group); -my ($old_time, $old_intf, $old_group, $old_state, $old_ltime) = - Vyatta::Keepalived::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. - # - Vyatta::Keepalived::vrrp_log("$vrrp_intf $vrrp_group same - $vrrp_state"); - exit 0; -} - -Vyatta::Keepalived::vrrp_log("$vrrp_intf $vrrp_group transition to $vrrp_state"); -vrrp_state_log($vrrp_state, $vrrp_intf, $vrrp_group); -if ($vrrp_state eq 'backup') { - # comment out for now, too expensive with lots of vrrp's at boot - # Vyatta::Keepalived::snoop_for_master($vrrp_intf, $vrrp_group, - # $vrrp_vips[0], 60); - # Filter traffic incoming to the vmac interface when in backup state - # Delete the rule then add it to insure that we don't get duplicates -} elsif ($vrrp_state eq 'master') { - # - # keepalived will send gratuitous arp requests on master transition - # but some hosts do not update their arp cache for gratuitous arp - # requests. Some of those host do respond to gratuitous arp replies - # so here we will send 5 gratuitous arp replies also. - # - unless ($transition_intf =~ m/\w+v\d+/){ - foreach my $vip (@vrrp_vips) { - system("/usr/bin/arping -A -c5 -I $vrrp_intf $vip"); - } - } - - # - # remove the old master file since we are now master - # - my $mfile = Vyatta::Keepalived::get_master_file($vrrp_intf, $vrrp_group); - system("rm -f $mfile"); -} - -if (!($vrrp_transitionscript eq 'null')){ - exec("$vrrp_transitionscript $vrrp_state $vrrp_intf $vrrp_group"); -} - -exit 0; - -# end of file - - - - |