diff options
author | John Southworth <john.southworth@vyatta.com> | 2012-05-15 11:34:33 -0700 |
---|---|---|
committer | John Southworth <john.southworth@vyatta.com> | 2012-05-15 11:34:33 -0700 |
commit | 6325118d9aa1ae7890a29c6f211ce456d04d68a9 (patch) | |
tree | d6cbbcad7acb4cd01cf520eff96e1641bd6a175f | |
parent | 0da3c8a7e5b7506a4b9a7d1bedbd48fd45e7d89d (diff) | |
download | vyatta-op-6325118d9aa1ae7890a29c6f211ce456d04d68a9.tar.gz vyatta-op-6325118d9aa1ae7890a29c6f211ce456d04d68a9.zip |
Add Vyatta wrappers for new keepalived output
1. Move show and clear vrrp scripts from vyatta-cfg-system. These
belong in vyatta-op.
2. Create templates for new vrrp commands
3. Make show commands go through a perl module so they can be
referenced from the webgui.
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | lib/Vyatta/VRRP/OPMode.pm | 366 | ||||
-rwxr-xr-x | scripts/vrrp/vyatta-clear-vrrp.pl | 303 | ||||
-rw-r--r-- | scripts/vrrp/vyatta-show-vrrp.pl | 114 | ||||
-rw-r--r-- | templates/show/vrrp/detail/node.def | 3 | ||||
-rw-r--r-- | templates/show/vrrp/interface/node.tag/group/node.tag/node.def | 4 | ||||
-rw-r--r-- | templates/show/vrrp/interface/node.tag/node.def | 4 | ||||
-rw-r--r-- | templates/show/vrrp/node.def | 2 | ||||
-rw-r--r-- | templates/show/vrrp/statistics/interface/node.def | 1 | ||||
-rw-r--r-- | templates/show/vrrp/statistics/interface/node.tag/group/node.def | 1 | ||||
-rw-r--r-- | templates/show/vrrp/statistics/interface/node.tag/group/node.tag/node.def | 3 | ||||
-rw-r--r-- | templates/show/vrrp/statistics/interface/node.tag/node.def | 3 | ||||
-rw-r--r-- | templates/show/vrrp/statistics/node.def | 2 | ||||
-rw-r--r-- | templates/show/vrrp/sync-group/group/node.def | 1 | ||||
-rw-r--r-- | templates/show/vrrp/sync-group/group/node.tag/node.def | 3 | ||||
-rw-r--r-- | templates/show/vrrp/sync-group/node.def | 3 |
16 files changed, 813 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am index 99f5da6..2d82760 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ completion_DATA = etc/bash_completion.d/vyatta-op opdir = $(datadir)/vyatta-op/templates bin_sudo_usersdir = $(bindir)/sudo-users etc_shell_leveldir = $(sysconfdir)/shell/level +share_perl5dir = $(datarootdir)/perl5/Vyatta/VRRP/ funcdir = $(datadir)/vyatta-op/functions func_DATA = functions/tech-support @@ -58,6 +59,10 @@ bin_sudo_users_SCRIPTS += scripts/vyatta-reboot.pl bin_sudo_users_SCRIPTS += scripts/vyatta-op-dns-forwarding.pl bin_sudo_users_SCRIPTS += scripts/vyatta-op-dynamic-dns.pl bin_sudo_users_SCRIPTS += scripts/vyatta-clear-conntrack +bin_sudo_users_SCRIPTS += scripts/vrrp/vyatta-clear-vrrp.pl +bin_sudo_users_SCRIPTS += scripts/vrrp/vyatta-show-vrrp.pl + +share_perl5_DATA = lib/Vyatta/VRRP/OPMode.pm all-local: ./gen-unpriv-commands.sh diff --git a/lib/Vyatta/VRRP/OPMode.pm b/lib/Vyatta/VRRP/OPMode.pm new file mode 100644 index 0000000..32d86fc --- /dev/null +++ b/lib/Vyatta/VRRP/OPMode.pm @@ -0,0 +1,366 @@ +# +# Module: Vyatta::VRRP::OPMode +# +# **** 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-2012 Vyatta, Inc. +# All Rights Reserved. +# +# Author: John Southworth +# Date: May 2012 +# Description: Process operational data from keepalived +# +# **** End License **** +# + +package Vyatta::VRRP::OPMode; +use strict; +use warnings; +our @EXPORT = qw(process_data process_stats print_summary print_stats print_sync print_detail check_intf); +use base qw(Exporter); + +use Sort::Versions; + +my $PIDFILE='/var/run/vrrp.pid'; +my $DATAFILE='/tmp/keepalived.data'; +my $STATSFILE='/tmp/keepalived.stats'; + +open my $PIDF, '<', $PIDFILE; +my $PID=<$PIDF>; +close $PIDF; + +sub trim { + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +sub conv_name { + my $name = shift; + $name = trim $name; + $name = lc $name; + $name =~ s/\s/-/g; + return $name; +} + +sub add_to_datahash { + my ($dh, $interface, $instance, $in_sync, $name, $val) = @_; + $name = conv_name $name; + if ($in_sync) { + if ($name eq 'monitor'){ + $dh->{'sync-groups'}->{$instance}->{$name} = + [ $dh->{'sync-groups'}->{$instance}->{$name} ? + @{$dh->{'sync-groups'}->{$instance}->{$name}} : (), + $val + ]; + } else { + $dh->{'sync-groups'}->{$instance}->{$name} = $val; + } + } else { + $dh->{'instances'}->{$interface}->{$instance}->{$name} = $val; + } +} + +sub process_data { + my ($dh) = @_; + my ($instance, $interface, $in_sync, $in_vip); + kill 'SIGUSR1', $PID; + open my $DATA, '<', $DATAFILE; + while (<$DATA>) + { + m/VRRP Instance = vyatta-(.*?)-(.*)/ && do { + $interface = $1; + $instance = $2; + $in_sync = undef; + $in_vip = undef; + $dh->{'instances'}->{$interface}->{$instance} = {}; + next; + }; + m/VRRP Sync Group = (.*?), (.*)/ && do { + $instance = $1; + $interface = undef; + $in_vip = undef; + my $state = $2; + $in_sync = 1; + add_to_datahash $dh, $interface, $instance, $in_sync, 'state', $state; + next; + }; + if ($in_vip){ + m/(.*?) dev (.*)/ && do { + $dh->{'instances'}->{$interface}->{$instance}->{vips} = + [ $dh->{'instances'}->{$interface}->{$instance}->{vips} ? + @{$dh->{'instances'}->{$interface}->{$instance}->{vips}} : (), + trim $1 ]; + }; + } + m/(.*?) = (.*)/ && do { + $in_vip = undef; + add_to_datahash $dh, $interface, $instance, $in_sync, $1, $2; + m/Virtual IP/ && do {$in_vip = 1}; + next; + }; + } + close $DATA; +} + +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 find_sync { + my ($intf, $vrid, $dh) = @_; + my $instance = "vyatta-$intf-$vrid"; + foreach my $sync (sort versioncmp keys(%{$dh->{'sync-groups'}})){ + return $sync if (grep { $instance } @{$dh->{'sync-groups'}->{$sync}->{monitor}}); + } + return; +} + +sub check_intf { + my ($hash, $intf, $vrid) = @_; + if ($intf) { + if (!exists($hash->{instances}->{$intf})){ + print "VRRP is not running on $intf\n"; + return 1; + } + if ($vrid){ + if (!exists($hash->{instances}->{$intf}->{$vrid})){ + print "No VRRP group $vrid exists on $intf\n"; + return 1; + } + } + } + return; +} + + +sub print_detail { + my ($dh,$intf,$group) = @_; + print "--------------------------------------------------\n"; + foreach my $interface (sort versioncmp keys(%{$dh->{instances}})) { + next if ($intf && $interface ne $intf); + printf "Interface: %s\n", $interface; + printf "--------------\n"; + foreach my $vrid (sort versioncmp keys(%{$dh->{instances}->{$interface}})){ + next if ($group && $vrid ne $group); + printf " Group: %s\n", $vrid; + printf " ----------\n"; + printf " State:\t\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{state}; + printf " Last transition:\t\t%s\n", + elapse_time($dh->{instances}->{$interface}->{$vrid}->{'last-transition'}, time); + printf "\n"; + if ( $dh->{instances}->{$interface}->{$vrid}->{state} eq 'BACKUP') { + printf " Master router:\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'master-router'}; + printf " Master priority:\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'master-priority'}; + printf "\n"; + } + if ($dh->{instances}->{$interface}->{$vrid}->{'transmitting-device'} ne + $dh->{instances}->{$interface}->{$vrid}->{'listening-device'}){ + printf " RFC 3768 Compliant\n"; + printf " Virtual MAC interface:\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'transmitting-device'}; + printf " Address Owner:\t\t%s\n", + ($dh->{instances}->{$interface}->{$vrid}->{priority} == 255) ? 'yes': 'no'; + printf "\n"; + } + printf " Source Address:\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'using-mcast-src_ip'}; + printf " Priority:\t\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'priority'}; + printf " Advertisement interval:\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'advert-interval'}; + printf " Authentication type:\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'authentication-type'}; + printf " Preempt:\t\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'preempt'}; + printf "\n"; + my $sync = find_sync($interface, $vrid, $dh); + if ($sync) { + printf " Sync-group:\t\t\t%s\n", $sync; + printf "\n"; + } + printf " VIP count:\t\t\t%s\n", + $dh->{instances}->{$interface}->{$vrid}->{'virtual-ip'}; + foreach my $vip (@{$dh->{instances}->{$interface}->{$vrid}->{vips}}){ + printf " %s\n", $vip; + } + printf "\n"; + } + } +} + +sub print_summary { + my ($dh, $intf, $group) = @_; + my $format = "%-18s%-7s%-8s%-11s%-7s%-12s%s\n"; + printf $format, '','','','RFC','Addr','Last','Sync'; + printf $format, 'Interface','Group','State','Compliant','Owner','Transition','Group'; + printf $format, '---------','-----','-----','---------','-----','----------','-----'; + foreach my $interface (sort versioncmp keys(%{$dh->{instances}})) { + next if ($intf && $interface ne $intf); + foreach my $vrid (sort versioncmp keys(%{$dh->{instances}->{$interface}})){ + next if ($group && $vrid ne $group); + my $state = $dh->{instances}->{$interface}->{$vrid}->{state}; + my $compliant = + ($dh->{instances}->{$interface}->{$vrid}->{'transmitting-device'} ne + $dh->{instances}->{$interface}->{$vrid}->{'listening-device'}) ? 'yes': 'no'; + my $addr_owner = ($dh->{instances}->{$interface}->{$vrid}->{priority} == 255) ? 'yes': 'no'; + my $lt = elapse_time($dh->{instances}->{$interface}->{$vrid}->{'last-transition'}, time); + my $sync = find_sync($interface, $vrid, $dh); + $sync = "<none>" if (!defined($sync)); + printf $format, $interface, $vrid, $state, $compliant, $addr_owner, $lt, $sync; + } + } + printf "\n"; +} + +sub process_stats { + my ($sh) = @_; + my ($instance, $interface, $section); + kill 'SIGUSR2', $PID; + open my $STATS, '<', $STATSFILE; + while (<$STATS>) + { + m/VRRP Instance: vyatta-(.*?)-(.*)/ && do { + $interface = $1; + $instance = $2; + $sh->{'instances'}->{$interface}->{$instance} = {}; + next; + }; + m/Released master: (.*)/ && do { + $sh->{'instances'}->{$interface}->{$instance}->{'released-master'} = $1; + next; + }; + m/Became master: (.*)/ && do { + $sh->{'instances'}->{$interface}->{$instance}->{'became-master'} = $1; + next; + }; + m/(.*?):$/ && do { + $section = conv_name $1; + $sh->{'instances'}->{$interface}->{$instance}->{$section} = {}; + next; + }; + m/(.*?): (.*)/ && do { + my $id = conv_name $1; + $sh->{'instances'}->{$interface}->{$instance}->{$section}->{$id} = $2; + next; + }; + print $_; + } + + close $STATS; +} + +sub print_stats { + my ($sh, $intf, $group) = @_; + print "--------------------------------------------------\n"; + foreach my $interface (sort versioncmp keys(%{$sh->{instances}})) { + next if ($intf && $interface ne $intf); + printf "Interface: %s\n", $interface; + printf "--------------\n"; + foreach my $vrid (sort versioncmp keys(%{$sh->{instances}->{$interface}})){ + next if ($group && $vrid ne $group); + printf " Group: %s\n", $vrid; + printf " ----------\n"; + printf " Advertisements:\n"; + printf " Received:\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{advertisements}->{received}; + printf " Sent:\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{advertisements}->{sent}; + printf "\n"; + printf " Became master:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'became-master'}; + printf " Released master:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'released-master'}; + printf "\n"; + printf " Packet errors:\n"; + printf " Length:\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'packet-errors'}->{length}; + printf " TTL:\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'packet-errors'}->{ttl}; + printf " Invalid type:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'packet-errors'}->{'invalid-type'}; + printf " Advertisement interval:\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'packet-errors'}->{'advertisement-interval'}; + printf " Address List:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'packet-errors'}->{'address-list'}; + printf "\n"; + printf " Authentication Errors:\n"; + printf " Invalid type:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'authentication-errors'}->{'invalid-type'}; + printf " Type mismatch:\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'authentication-errors'}->{'type-mismatch'}; + printf " Failure:\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'authentication-errors'}->{'failure'}; + printf "\n"; + printf " Priority Zero Advertisements:\n"; + printf " Received\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'priority-zero'}->{'received'}; + printf " Sent\t\t\t%d\n", + $sh->{instances}->{$interface}->{$vrid}->{'priority-zero'}->{'sent'}; + printf "\n"; + } + } +} + +sub print_sync { + my ($dh, $sync_group) = @_; + print "--------------------------------------------------\n"; + foreach my $sync (sort versioncmp keys(%{$dh->{'sync-groups'}})){ + next if ($sync_group && $sync ne $sync_group); + printf "Group: %s\n", $sync; + printf "---------\n"; + printf " State: %s\n", $dh->{'sync-groups'}->{$sync}->{state}; + printf " Monitoring:\n"; + foreach my $mon (@{$dh->{'sync-groups'}->{$sync}->{monitor}}){ + my ($intf, $vrid) = $mon =~ m/vyatta-(.*?)-(.*)/; + printf " Interface: %s, Group: %s\n", $intf, $vrid; + } + printf "\n"; + } +} + +1; diff --git a/scripts/vrrp/vyatta-clear-vrrp.pl b/scripts/vrrp/vyatta-clear-vrrp.pl new file mode 100755 index 0000000..34c0327 --- /dev/null +++ b/scripts/vrrp/vyatta-clear-vrrp.pl @@ -0,0 +1,303 @@ +#!/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/vrrp/vyatta-show-vrrp.pl b/scripts/vrrp/vyatta-show-vrrp.pl new file mode 100644 index 0000000..afc490b --- /dev/null +++ b/scripts/vrrp/vyatta-show-vrrp.pl @@ -0,0 +1,114 @@ +#!/usr/bin/env perl +# +# **** 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-2012 Vyatta, Inc. +# All Rights Reserved. +# +# Author: John Southworth +# Date: May 2012 +# Description: Process operational data from keepalived +# +# **** End License **** +# + +use strict; +use lib "/opt/vyatta/share/perl5"; + +use Getopt::Long; +use Vyatta::VRRP::OPMode; +use Sort::Versions; +use v5.10; + +my ($show, $intf, $vrid); +GetOptions("show=s" => \$show, + "intf=s" => \$intf, + "vrid=s" => \$vrid + ); + +sub list_vrrp_intf { + my $intf = shift; + my $hash = {}; + process_data $hash; + if ($intf) { + printf "%s\n", join " ", sort versioncmp keys(%{$hash->{instances}->{$intf}}); + } else { + printf "%s\n", join " ", sort versioncmp keys(%{$hash->{instances}}); + } +} + +sub list_vrrp_sync_groups { + my $hash = {}; + process_data $hash; + printf "%s\n", join " ", sort versioncmp keys(%{$hash->{'sync-groups'}}); +} + +sub show_vrrp_summary { + my ($intf, $vrid) = @_; + my $hash = {}; + process_data $hash; + return if (check_intf($hash, $intf, $vrid)); + print_summary $hash, $intf, $vrid; +} + +sub show_vrrp_stats { + my ($intf, $vrid) = @_; + my $hash = {}; + process_stats $hash; + return if (check_intf($hash, $intf, $vrid)); + print_stats $hash, $intf, $vrid; +} + +sub show_vrrp_detail { + my ($intf, $vrid) = @_; + my $hash = {}; + process_data $hash; + return if (check_intf($hash, $intf, $vrid)); + print_detail $hash, $intf, $vrid; +} + +sub show_vrrp_sync_groups { + my $sync = shift; + my $hash = {}; + process_data $hash; + if ($sync && !exists($hash->{'sync-groups'}->{$sync})){ + print "Sync-group: $sync does not exist\n"; + return; + } + print_sync $hash, $intf; +} + +given ($show) { + when ('summary') { + show_vrrp_summary $intf, $vrid; + } + when ('detail') { + show_vrrp_detail $intf, $vrid; + } + when ('stats') { + show_vrrp_stats $intf, $vrid; + } + when ('sync') { + show_vrrp_sync_groups $intf; + } + when ('interface') { + list_vrrp_intf $intf; + } + when ('syncs') { + list_vrrp_sync_groups; + } + default { + exit; + } +} + + diff --git a/templates/show/vrrp/detail/node.def b/templates/show/vrrp/detail/node.def new file mode 100644 index 0000000..269df73 --- /dev/null +++ b/templates/show/vrrp/detail/node.def @@ -0,0 +1,3 @@ +help: Show detailed VRRP information +run: /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=detail + diff --git a/templates/show/vrrp/interface/node.tag/group/node.tag/node.def b/templates/show/vrrp/interface/node.tag/group/node.tag/node.def index de7eb12..c0df0f2 100644 --- a/templates/show/vrrp/interface/node.tag/group/node.tag/node.def +++ b/templates/show/vrrp/interface/node.tag/group/node.tag/node.def @@ -1,3 +1,3 @@ help: Show VRRP information for specified interface and group -allowed: /opt/vyatta/sbin/vyatta-keepalived.pl --vrrp-action=list-vrrp-group --intf "${COMP_WORDS[COMP_CWORD-2]}" -run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl "$4" "$6" +allowed: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=interface --intf="${COMP_WORDS[COMP_CWORD-2]}" +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=detail --intf=$4 --vrid=$6 diff --git a/templates/show/vrrp/interface/node.tag/node.def b/templates/show/vrrp/interface/node.tag/node.def index 1defd31..f9e53ee 100644 --- a/templates/show/vrrp/interface/node.tag/node.def +++ b/templates/show/vrrp/interface/node.tag/node.def @@ -1,3 +1,3 @@ help: Show VRRP information for specified interface -allowed: /opt/vyatta/sbin/vyatta-keepalived.pl --vrrp-action=list-vrrp-intf -run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl "$4" +allowed: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=interface +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=detail --intf=$4 diff --git a/templates/show/vrrp/node.def b/templates/show/vrrp/node.def index 51e9b9d..606e215 100644 --- a/templates/show/vrrp/node.def +++ b/templates/show/vrrp/node.def @@ -1,2 +1,2 @@ help: Show Virtual Router Redundancy Protocol (VRRP) information -run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=summary diff --git a/templates/show/vrrp/statistics/interface/node.def b/templates/show/vrrp/statistics/interface/node.def new file mode 100644 index 0000000..7d7d648 --- /dev/null +++ b/templates/show/vrrp/statistics/interface/node.def @@ -0,0 +1 @@ +help: Show VRRP statistics for specified interface diff --git a/templates/show/vrrp/statistics/interface/node.tag/group/node.def b/templates/show/vrrp/statistics/interface/node.tag/group/node.def new file mode 100644 index 0000000..4673669 --- /dev/null +++ b/templates/show/vrrp/statistics/interface/node.tag/group/node.def @@ -0,0 +1 @@ +help: Show VRRP statistics for specified interface and group diff --git a/templates/show/vrrp/statistics/interface/node.tag/group/node.tag/node.def b/templates/show/vrrp/statistics/interface/node.tag/group/node.tag/node.def new file mode 100644 index 0000000..05606f8 --- /dev/null +++ b/templates/show/vrrp/statistics/interface/node.tag/group/node.tag/node.def @@ -0,0 +1,3 @@ +help: Show VRRP statistics for specified interface and group +allowed: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=interface --intf="${COMP_WORDS[COMP_CWORD-2]}" +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=stats --intf=$5 --vrid=$7 diff --git a/templates/show/vrrp/statistics/interface/node.tag/node.def b/templates/show/vrrp/statistics/interface/node.tag/node.def new file mode 100644 index 0000000..494032b --- /dev/null +++ b/templates/show/vrrp/statistics/interface/node.tag/node.def @@ -0,0 +1,3 @@ +help: Show VRRP statistics for specified interface +allowed: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=interface +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=stats --intf=$5 diff --git a/templates/show/vrrp/statistics/node.def b/templates/show/vrrp/statistics/node.def new file mode 100644 index 0000000..d125c2a --- /dev/null +++ b/templates/show/vrrp/statistics/node.def @@ -0,0 +1,2 @@ +help: Show Virtual Router Redundancy Protocol (VRRP) statistics +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=stats diff --git a/templates/show/vrrp/sync-group/group/node.def b/templates/show/vrrp/sync-group/group/node.def new file mode 100644 index 0000000..7d7d648 --- /dev/null +++ b/templates/show/vrrp/sync-group/group/node.def @@ -0,0 +1 @@ +help: Show VRRP statistics for specified interface diff --git a/templates/show/vrrp/sync-group/group/node.tag/node.def b/templates/show/vrrp/sync-group/group/node.tag/node.def new file mode 100644 index 0000000..8beb76e --- /dev/null +++ b/templates/show/vrrp/sync-group/group/node.tag/node.def @@ -0,0 +1,3 @@ +help: Show VRRP statistics for specified interface +allowed: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=syncs +run: sudo /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=sync --intf=$5 diff --git a/templates/show/vrrp/sync-group/node.def b/templates/show/vrrp/sync-group/node.def new file mode 100644 index 0000000..5242743 --- /dev/null +++ b/templates/show/vrrp/sync-group/node.def @@ -0,0 +1,3 @@ +help: Show VRRP sync-group information +run: /opt/vyatta/bin/sudo-users/vyatta-show-vrrp.pl --show=sync + |