diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | etc/logrotate.d/vyatta-config-logs | 2 | ||||
-rwxr-xr-x | lib/Vyatta/ConfigLoad.pm | 422 | ||||
-rwxr-xr-x | scripts/init/vyos-router | 3 | ||||
-rwxr-xr-x | scripts/vyatta-boot-config-loader | 79 | ||||
-rwxr-xr-x | scripts/vyatta-config-loader.pl | 156 | ||||
-rwxr-xr-x | scripts/vyatta-load-config.pl | 248 |
7 files changed, 1 insertions, 912 deletions
diff --git a/Makefile.am b/Makefile.am index 0919508..1f839ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,11 +123,9 @@ sbin_SCRIPTS = scripts/vyatta-cfg-cmd-wrapper sbin_SCRIPTS += scripts/vyatta-validate-type.pl sbin_SCRIPTS += scripts/vyatta-find-type.pl sbin_SCRIPTS += scripts/priority.pl -sbin_SCRIPTS += scripts/vyatta-boot-config-loader sbin_SCRIPTS += scripts/vyatta-cli-expand-var.pl sbin_SCRIPTS += scripts/vyatta-output-config.pl sbin_SCRIPTS += scripts/vyatta-save-config.pl -sbin_SCRIPTS += scripts/vyatta-load-config.pl sbin_SCRIPTS += scripts/vyatta-cfg-notify sbin_SCRIPTS += scripts/vyatta-check-typeless-node.pl sbin_SCRIPTS += scripts/vyatta-strip-migration-comments.pl @@ -142,7 +140,6 @@ share_perl5_DATA += lib/Vyatta/ioctl.pm share_perl5_DATA += lib/Vyatta/Interface.pm share_perl5_DATA += lib/Vyatta/TypeChecker.pm share_perl5_DATA += lib/Vyatta/ConfigOutput.pm -share_perl5_DATA += lib/Vyatta/ConfigLoad.pm enum_SCRIPTS = scripts/enumeration/existing-interfaces diff --git a/etc/logrotate.d/vyatta-config-logs b/etc/logrotate.d/vyatta-config-logs index 79a373b..3b9799e 100644 --- a/etc/logrotate.d/vyatta-config-logs +++ b/etc/logrotate.d/vyatta-config-logs @@ -1,4 +1,4 @@ -/var/log/vyatta/cfg-stderr.log /var/log/vyatta/cfg-stdout.log /var/log/vyatta/vyos-boot-config-loader.log /var/log/vyatta/vyatta-commit.log /var/log/vyatta/vyatta-config-loader.log { +/var/log/vyatta/cfg-stderr.log /var/log/vyatta/cfg-stdout.log /var/log/vyatta/vyos-boot-config-loader.log /var/log/vyatta/vyatta-commit.log { nocompress size 1M rotate 2 diff --git a/lib/Vyatta/ConfigLoad.pm b/lib/Vyatta/ConfigLoad.pm deleted file mode 100755 index 960240c..0000000 --- a/lib/Vyatta/ConfigLoad.pm +++ /dev/null @@ -1,422 +0,0 @@ -# Author: Vyatta <eng@vyatta.com> -# Date: 2007 -# Description: Perl module for loading configuration. - -# **** 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) 2006, 2007, 2008 Vyatta, Inc. -# All Rights Reserved. - -package Vyatta::ConfigLoad; -use strict; - -our @EXPORT = qw(getStartupConfigStatements loadConfigHierarchy getConfigDiff); -use base qw(Exporter); - -use sort 'stable'; -use lib "/opt/vyatta/share/perl5"; -use XorpConfigParser; -use Vyatta::Config; - -my @all_nodes = (); -my @all_naked_nodes = (); - -my @disable_list = (); - - -sub match_regex { - my ($pattern, $str) = @_; - $pattern =~ s/^(.*)$/\^$1\$/; - return ($str =~ m/$pattern/) ? 1 : 0; -} - - -sub applySingleQuote { - my @return = (); - foreach (@_) { - # change all single quotes to "'\''" since we're going to single-quote - # every component of the command - if (/^'(.*)'$/) { - $_ = $1; - } - $_ =~ s/'/'\\''/g; - # single-quote every component of the command - if (/^'.*'$/) { - push @return, $_; - } elsif (/^"(.*)"$/) { - push @return, "'$1'"; - } else { - push @return, "'$_'"; - } - } - return @return; -} - -my @comment_list = (); - -sub enumerate_branch { - my $cur_node = shift; - my @cur_path = @_; - # name not defined at root level - if (defined($cur_node->{'name'})) { - my $name = $cur_node->{'name'}; - if ($name =~ /^\s*(\S+)\s+(\S.*)$/) { - push @cur_path, ($1, $2); - } else { - push @cur_path, $name; - } - } - my $terminal = 0; - if (!defined($cur_node->{'children'})) { - $terminal = 1; - } else { - my $comment; - foreach (@{$cur_node->{'children'}}) { - if (defined($_->{'comment'})) { - $comment = $_->{'comment'}; - } - - if (defined($_->{'name'})) { - if (defined $comment) { - push @comment_list, join(" ", (@cur_path, $_->{'name'}, "\"" . $comment . "\"")); - $comment = undef; - } - else { - #need to check for existance of .comment file here. - push @comment_list, join(" ", (@cur_path, $_->{'name'}, "\"\"")); - } - enumerate_branch($_, @cur_path); - $terminal = 0; - } - - } - } - - if (defined($cur_node->{'disable'})) { - push @disable_list, join(" ",@cur_path); - } - - if ($terminal) { - my $val = $cur_node->{'value'}; - if (defined($val)) { - push @cur_path, $val; - } - push @all_naked_nodes, [ @cur_path ]; - my @qpath = applySingleQuote(@cur_path); - push @all_nodes, [\@qpath, 0]; - } -} - -# $0: config file to load -# return: list of all config statement -sub getStartupConfigStatements { - # clean up the lists first - @all_nodes = (); - @all_naked_nodes = (); - - my $load_cfg = shift; - if (!defined($load_cfg)) { - return (); - } - - my $comments = shift; - - my $xcp = new XorpConfigParser(); - $xcp->parse($load_cfg); - my $root = $xcp->get_node( () ); - if (!defined($root)) { - return (); - } - enumerate_branch($root, ( )); - - if (defined $comments && $comments eq 'true') { - #add comment commands to all nodes - foreach my $c (@comment_list) { - if ($c !~ /\"\"$/) { - my @pth = split(" ",'comment ' . $c); - push @all_nodes, [\@pth, 1]; - } - } - } - my %conf = ( - 'set' => \@all_nodes, - 'deactivate' => \@disable_list, - ); - return %conf; -} - -my %node_order = (); - -# $0: ref of list of parsed naked statements. -# return: hash containing the config hierarchy. -sub generateHierarchy { - my @node_list = @{$_[0]}; - my %hash = (); - %node_order = (); - my $order = 0; - foreach my $node (@node_list) { - my @path = @{$node}; - my $path_str = join ' ', @path; - $node_order{$path_str} = $order; - $order++; - my $cur_ref = \%hash; - foreach (@path) { - if (!defined($cur_ref->{$_})) { - $cur_ref->{$_} = { }; - } - $cur_ref = $cur_ref->{$_}; - } - } - return %hash; -} - -# $0: config file to load. -# return: hash containing the config hierarchy. -sub loadConfigHierarchy { - # clean up the lists first - @all_nodes = (); - @all_naked_nodes = (); - - my $load_cfg = shift; - if (!defined($load_cfg)) { - return (); - } - - #allows loading from arbritary root - my $root_node = shift; - - my $xcp = new XorpConfigParser(); - $xcp->parse($load_cfg); - my $root; - my @root_path; - if (defined($root_node)) { - my $tmp = [split("/",$root_node)]; - $root = $xcp->get_node($tmp); - my @tmp2 = split("/",$root_node); - @root_path = pop(@tmp2); - @root_path = @tmp2; - } - else { - $root = $xcp->get_node( () ); - } - if (!defined($root)) { - return (); - } - enumerate_branch($root, @root_path); - - return generateHierarchy(\@all_naked_nodes); -} - -# $0: ref of hierarchy root. -# $1: display prefix. -sub printHierarchy { - my $cur_ref = shift; - my $prefix = shift; - foreach (sort keys %{$cur_ref}) { - print "$prefix$_"; - if (scalar(keys %{$cur_ref->{$_}}) == 0) { - print " (terminal)\n"; - next; - } else { - print "\n"; - } - printHierarchy($cur_ref->{$_}, "$prefix "); - } -} - -# $0: hash ref representing a "multi:" node. -# $1: array ref representing current config path. -# returns the list of node values sorted by the original order. -sub getSortedMultiValues { - my $nref = $_[0]; - my @npath = @{$_[1]}; - my $path_str = join ' ', @npath; - my @list = (); - foreach (keys %{$nref}) { - my $key = "$path_str $_"; - push @list, [ $_, $node_order{$key} ]; - } - my @slist = sort { ${$a}[1] <=> ${$b}[1] } @list; - @slist = map { ${$_}[0] } @slist; - return @slist; -} - -my $active_cfg = undef; -my $new_cfg_ref = undef; -my @delete_list = (); - -# find specified node's values in active config that have been deleted from -# new config. -# $0: hash ref at the current hierarchy level (new config) -# $1: array ref representing current config path (active config) -sub findDeletedValues { - my $new_ref = $_[0]; - my @active_path = @{$_[1]}; - - $active_cfg->setLevel(join ' ', @active_path); - my ($is_multi, $is_text) = $active_cfg->parseTmpl(); - if ($is_multi) { - # for "multi:" nodes, need to sort the values by the original order. - my @nvals = getSortedMultiValues($new_ref, \@active_path); - if ($is_text) { - @nvals = map { /^"(.*)"$/ ? $1 : $_ }@nvals; - } - my @ovals = $active_cfg->returnOrigValues(''); - my %comp_hash = $active_cfg->compareValueLists(\@ovals, \@nvals); - foreach (@{$comp_hash{'deleted'}}) { - my @plist = applySingleQuote(@active_path, $_); - push @delete_list, [\@plist, 0]; - } - } else { - # do nothing. if a single-value leaf node is deleted, it should have - # been detected at the previous level. since we are already at node.val, - # it can only be "added" or "changed", handled later. - } -} - -# find nodes in active config that have been deleted from new config. -# $0: hash ref at the current hierarchy level (new config) -# $1: array ref representing current config path (active config) -sub findDeletedNodes { - my $new_ref = $_[0]; - my @active_path = @{$_[1]}; - $active_cfg->setLevel(join ' ', @active_path); - if ($active_cfg->isLeafNode()) { - findDeletedValues($new_ref, \@active_path); - return; - } - # not a leaf node - my @active_nodes = $active_cfg->listOrigNodesDA(); - foreach (@active_nodes) { - if (!defined($new_ref->{$_})) { - my @plist = applySingleQuote(@active_path, $_); - push @delete_list, [\@plist, 0]; - } else { - findDeletedNodes($new_ref->{$_}, [ @active_path, $_ ]); - } - } -} - -my @set_list = (); - -# find specified node's values in active config that are set -# (added or changed). -# $0: hash ref at the current hierarchy level (new config) -# $1: array ref representing current config path (active config) -sub findSetValues { - my $new_ref = $_[0]; - my @active_path = @{$_[1]}; - - $active_cfg->setLevel(join ' ', @active_path); - my ($is_multi, $is_text) = $active_cfg->parseTmpl(); - if ($is_multi) { - # for "multi:" nodes, need to sort the values by the original order. - my @nvals = getSortedMultiValues($new_ref, \@active_path); - if ($is_text) { - @nvals = map { /^"(.*)"$/ ? $1 : $_ } @nvals; - } - my @ovals = $active_cfg->returnOrigValues(''); - my %comp_hash = $active_cfg->compareValueLists(\@ovals, \@nvals); - foreach (@{$comp_hash{'added'}}) { - my @plist = applySingleQuote(@active_path, $_); - push @set_list, [\@plist, 0]; - } - } else { - my @nvals = keys %{$new_ref}; - my $nval = $nvals[0]; - if ($is_text) { - $nval =~ s/^"(.*)"$/$1/; - } - my $oval = $active_cfg->returnOrigValue(''); - if (!defined($oval) || ($nval ne $oval)) { - my @plist = applySingleQuote(@active_path, $nval); - push @set_list, [\@plist, 0]; - } - } -} - -# find nodes in new config that are set (added or changed). -# $0: hash ref at the current hierarchy level (new config) -# $1: array ref representing current config path (active config) -sub findSetNodes { - my $new_ref = $_[0]; - my @active_path = @{$_[1]}; - $active_cfg->setLevel(join ' ', @active_path); - my @active_nodes = $active_cfg->listOrigNodes(); - my %active_hash = map { $_ => 1 } @active_nodes; - my $nref = $active_cfg->parseTmplAll(); - if (defined($nref->{type}) and !defined($nref->{tag})) { - # we are at a leaf node. - findSetValues($new_ref, \@active_path); - return; - } - foreach (sort keys %{$new_ref}) { - if (scalar(keys %{$new_ref->{$_}}) == 0) { - # we are at a non-value leaf node. - # check if we need to add this node. - if (!defined($active_hash{$_})) { - my @plist = applySingleQuote(@active_path, $_); - push @set_list, [\@plist, 0]; - } else { - # node already present. do nothing. - } - next; - } - # we recur regardless of whether it's in active. all changes will be - # handled when we reach leaf nodes (above). - findSetNodes($new_ref->{$_}, [ @active_path, $_ ]); - } -} - -# compare the current active config with the specified hierarchy and return -# the "diff". -# $0: hash ref of config hierarchy. -# return: hash containing the diff. -sub getConfigDiff { - $active_cfg = new Vyatta::Config; - $new_cfg_ref = shift; - @set_list = (); -# @disable_list = (); - @delete_list = (); - findDeletedNodes($new_cfg_ref, [ ]); - findSetNodes($new_cfg_ref, [ ]); - - # need to filter out deletions of nodes with default values - my @new_delete_list = (); - foreach my $del (@delete_list) { - my @comps = map { - my $file = $_; - $file =~ s/^'(.*)'$/$1/; - $file; - } @{${$del}[0]}; - - $active_cfg->setLevel(join ' ', @comps); - my ($is_multi, $is_text, $default) = $active_cfg->parseTmpl(); - if (!defined($default)) { - push @new_delete_list, $del; - } - } - - #let's get active disable nodes - my @enable_list = $active_cfg->getAllDeactivated("");; - - my %diff = ( - 'delete' => \@new_delete_list, - 'set' => \@set_list, - 'deactivate' => \@disable_list, - 'activate' => \@enable_list, - 'comment' => \@comment_list, - ); - return %diff; -} - -1; diff --git a/scripts/init/vyos-router b/scripts/init/vyos-router index 2668390..9130307 100755 --- a/scripts/init/vyos-router +++ b/scripts/init/vyos-router @@ -100,9 +100,6 @@ load_bootfile () fi if [ -x $vyos_libexec_dir/vyos-boot-config-loader.py ]; then sg ${GROUP} -c "$vyos_libexec_dir/vyos-boot-config-loader.py $BOOTFILE" - else - # if not available, fallback to earlier version - sg ${GROUP} -c "$vyatta_sbindir/vyatta-boot-config-loader $BOOTFILE" fi ) } diff --git a/scripts/vyatta-boot-config-loader b/scripts/vyatta-boot-config-loader deleted file mode 100755 index b242b78..0000000 --- a/scripts/vyatta-boot-config-loader +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -BOOT_FILE=$1 -shift - -CAPI=/bin/cli-shell-api -CLOG=/var/log/vyatta/vyatta-config-loader.log -COMMIT=/opt/vyatta/sbin/my_commit -COMMIT_LOG=/var/log/vyatta/vyatta-commit.log - -do_log () { - local level=$1 - shift - logger -t 'boot-config-loader' -p "local0.$level" -- "$*" -} - -do_commit () { - # Check if debug is enabled in the kernel command line - grep vyos-debug /proc/cmdline > /dev/null - if [ $? == 0 ]; then - VYOS_DEBUG=$debug $COMMIT "$@" >>$COMMIT_LOG - else - $COMMIT "$@" >>$COMMIT_LOG - fi -} - -trace () { - echo "$(date +'%F %T') $*" -} - -umask 0002 - -( - trace '== begin boot-config-loader' - # set up config session - SID=$$ - SENV=$($CAPI getSessionEnv $SID) - eval "$SENV" - if ! $CAPI setupSession; then - do_log err 'Cannot set up configuration session.' - trace 'Cannot set up configuration session.' - exit 1 - fi - - # do load - trace '-- begin load' - if ! $CAPI loadFile $BOOT_FILE; then - do_log warn "Failure(s) encountered during load. See $CLOG for details." - trace '-- load finished with failure(s)' - else - trace '-- load finished successfully' - fi - - # do commit - trace '-- begin commit' - ret=0 - export COMMIT_VIA=boot-config-loader - if ! do_commit ; then - do_log err 'Commit failed at boot.' - trace '-- commit failed' - ret=1 - else - trace '-- commit succeeded' - fi - - # clean up - if ! $CAPI teardownSession; then - do_log warn 'Failed to tear down configuration session.' - trace '-- teardown failed' - else - trace '-- teardown succeeded' - fi - trace '-- exiting' - echo $ret > /tmp/vyos-config-status - sync - exit $ret -) </dev/null >>$CLOG 2>&1 - -exit $? diff --git a/scripts/vyatta-config-loader.pl b/scripts/vyatta-config-loader.pl deleted file mode 100755 index 9e296ad..0000000 --- a/scripts/vyatta-config-loader.pl +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/perl - -# Author: An-Cheng Huang <ancheng@vyatta.com> -# Date: 2007 -# Description: configuration loader - -# **** 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) 2006, 2007, 2008 Vyatta, Inc. -# All Rights Reserved. -# **** End License **** - -# Perl script for loading the startup config file. -# $0: startup config file. - -use strict; -use lib "/opt/vyatta/share/perl5/"; -use Vyatta::ConfigLoad; -use Sys::Syslog qw(:standard :macros); -use POSIX qw(strftime); - -my $CWRAPPER = '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper'; -my $CONFIG_LOG = '/var/log/vyatta/vyatta-config-loader.log'; -my $COMMIT_CMD = "$CWRAPPER commit"; -my $CLEANUP_CMD = "$CWRAPPER cleanup"; -my $BEGIN_CMD = "$CWRAPPER begin"; -my $END_CMD = "$CWRAPPER end"; - -umask 0002; - -# Set up logging -openlog("config-loader", "nofail", LOG_LOCAL0); - -open(STDIN, '<', "/dev/null") - or die "Can't open /dev/null : $!"; -open(STDOUT, '>>', $CONFIG_LOG) - or die "Can't open $CONFIG_LOG : $!"; -open(STDERR, '>&STDOUT') - or die "Can't redirect stderr: $!"; - -sub trace { - my $str = shift; - - printf "%s %s\n", strftime("%F %T ", localtime), $str; -} - -# get a list of all config statement in the startup config file -my %cfg_hier = Vyatta::ConfigLoad::getStartupConfigStatements($ARGV[0],'true'); -my @all_nodes = @{$cfg_hier{'set'}}; - -# empty configuration? -die "Empty configuration!\n" - if (scalar(@all_nodes) == 0); - -# set up the config environment -unless (system($BEGIN_CMD) == 0) { - syslog(LOG_WARNING, "Cannot set up configuration environment"); - die "Cannot set up configuration environment\n"; -} - -my $start = time; -trace "-- begin"; - -#cmd below is added to debug last set of command ordering -foreach (@all_nodes) { - my ($path_ref, $rank) = @$_; - my @pr = @$path_ref; - - if ($pr[0] =~ /^comment$/) { - my $ct = 0; - my $rel_path; - foreach my $rp (@pr[1..$#pr]) { - $ct++; - my $tmp_path = $rel_path . "/" . $rp; - my $node_path = "/opt/vyatta/share/vyatta-cfg/templates/". $tmp_path . "/node.def"; - - last if ($rp eq '"'); - last if ($rp eq '""'); - - if (!-e $node_path) { - - #pop this element - delete $pr[$ct]; - last; - } - $rel_path = $tmp_path; - } - - my $comment_cmd = "$CWRAPPER " . join(" ",@pr); - `$comment_cmd`; - next; - } - - my $cmd = 'set ' . join(' ', @pr); - - # Show all commands in log - trace $cmd; - unless (system("$CWRAPPER $cmd") == 0) { - warn "*** %s failed: %d\n", $cmd, $?; - syslog(LOG_NOTICE, "[[%s]] failed", $cmd); - } -} - -my $commit_start = time; -trace "commit"; -syslog(LOG_INFO, "Configuration took %d seconds.", $commit_start - $start); - -unless (system($COMMIT_CMD) == 0) { - warn "*** Commit failed: %d\n", $?; - syslog(LOG_WARNING, "Commit failed at boot"); - - system($CLEANUP_CMD); - system($END_CMD); - exit 1; -} - -my $commit_end = time; -syslog(LOG_INFO, "Commit succeeded took %d seconds.",$commit_end - $commit_start); - -# Now process any deactivate nodes -my @deactivate_nodes = @{$cfg_hier{'deactivate'}}; -if (@deactivate_nodes) { - foreach (@deactivate_nodes) { - my $cmd = "deactivate " . $_; - trace $cmd; - - unless (system("$CWRAPPER $cmd") == 0) { - warn "*** %s failed: %d\n", $cmd, $?; - syslog(LOG_WARNING, "[[%s]] failed", $cmd); - last; - } - } - - unless (system($COMMIT_CMD) == 0) { - warn "deactivate commit failed: %d\n", $?; - syslog(LOG_NOTICE, "Commit deactivate failed at boot"); - system($CLEANUP_CMD); - } -} - -unless (system($END_CMD) == 0) { - syslog(LOG_WARNING, "Cannot teardown configuration environment"); - die "Cannot teardown configuration environment\n"; -} -trace "done."; - -exit 0; diff --git a/scripts/vyatta-load-config.pl b/scripts/vyatta-load-config.pl deleted file mode 100755 index d432af9..0000000 --- a/scripts/vyatta-load-config.pl +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/perl - -# Author: Vyatta <eng@vyatta.com> -# Date: 2007 -# Description: Perl script for loading config file at run time. - -# **** 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) 2006, 2007, 2008 Vyatta, Inc. -# All Rights Reserved. -# **** End License **** - -# $0: config file. - -use strict; -use lib "/opt/vyatta/share/perl5/"; -use POSIX; -use IO::Prompt; -use Getopt::Long; -use Sys::Syslog qw(:standard :macros); -use Vyatta::Config; -use Vyatta::ConfigLoad; -use Vyatta::Misc qw(get_short_config_path); - -$SIG{'INT'} = 'IGNORE'; - -my $etcdir = $ENV{vyatta_sysconfdir}; -my $sbindir = $ENV{vyatta_sbindir}; -my $bootpath = $etcdir . "/config"; -my $load_file = $bootpath . "/config.boot"; -my $url_tmp_file = $bootpath . "/config.boot.$$"; -my $vyos_libexec_dir = $ENV{vyos_libexec_dir}; - - -# -# Note: to get merge to work on arbitrary nodes -# within the configuration multinodes need to be escaped. -# i.e.: -# load --merge='load-balancing/wan/interface-health\ eth0' -# -# will start loading of the configuration node from: -# -# load-balancing/wan/interface-health:eth0 -# -# Note current loading is limited to first new -# multinode. -# -sub usage { - print "Usage: $0 --merge=<root>\n"; - exit 0; -} - -my $merge; -GetOptions( - "merge:s" => \$merge, - ) or usage(); - -my $mode = 'local'; -my $proto; - -if ( defined( $ARGV[0] ) ) { - $load_file = $ARGV[0]; -} -my $orig_load_file = $load_file; - -if ( $load_file =~ /^[^\/]\w+:\// ) { - if ( $load_file =~ /^(\w+):\/\/\w/ ) { - $mode = 'url'; - $proto = lc($1); - unless( $proto eq 'tftp' || - $proto eq 'ftp' || - $proto eq 'http' || - $proto eq 'https' || - $proto eq 'scp' || - $proto eq 'sftp' ) { - die "Invalid url protocol [$proto]\n"; - } - } else { - print "Invalid url [$load_file]\n"; - exit 1; - } -} - -if ( $mode eq 'local' and !( $load_file =~ /^\// ) ) { - # relative path - $load_file = "$bootpath/$load_file"; -} - -my $cfg; -if ( $mode eq 'local' ) { - die "Cannot open configuration file $load_file: $!\n" - unless open( $cfg, '<', $load_file); -} -elsif ( $mode eq 'url' ) { - if ( !-f '/usr/bin/curl' ) { - print "Package [curl] not installed\n"; - exit 1; - } - if ( $proto eq 'http' or $proto eq 'https' ) { - # - # error codes are send back in html, so 1st try a header - # and look for "HTTP/1.1 200 OK" or "HTTP/1.1 301 Moved Permanently" - # - my $rc = `curl -L -q -I $load_file 2>&1`; - if ( $rc =~ /HTTP\/\d+\.?\d\s+(\d+)\s+(.*)$/mi ) { - my $rc_code = $1; - my $rc_string = $2; - if ( $rc_code == 200 or $rc_code == 301 ) { - # good response - } - else { - print "http error: [$rc_code] $rc_string\n"; - exit 1; - } - } - else { - print "Error: $rc\n"; - exit 1; - } - } - my $rc = system("curl -# -o $url_tmp_file $load_file"); - if ($proto =~ /^(scp|sftp)$/ && ($rc >> 8) == 51){ - $load_file =~ m/(?:scp|sftp):\/\/(.*?)\//; - my $host = $1; - if ($host =~ m/.*@(.*)/) { - $host = $1; - } - my $rsa_key = `ssh-keyscan -t rsa $host 2>/dev/null`; - print "The authenticity of host '$host' can't be established.\n"; - my $fingerprint = `ssh-keygen -lf /dev/stdin <<< \"$rsa_key\" | awk {' print \$2 '}`; - chomp $fingerprint; - print "RSA key fingerprint is $fingerprint.\n"; - if (prompt("Are you sure you want to continue connecting (yes/no) [Yes]? ", -tynd=>"y")) { - mkdir "~/.ssh/"; - open(my $known_hosts, ">>", "$ENV{HOME}/.ssh/known_hosts") - or die "Cannot open known_hosts: $!"; - print $known_hosts "$rsa_key\n"; - close($known_hosts); - $rc = system("curl -# -o $url_tmp_file $load_file"); - print "\n"; - } - } - if ($rc) { - print "Can not open remote configuration file $load_file\n"; - exit 1; - } - die "Cannot open configuration file $load_file: $!\n" - unless open( $cfg, '<', $url_tmp_file); - - $load_file = $url_tmp_file; -} - -my $xorp_cfg = 0; -my $valid_cfg = 0; -while (<$cfg>) { - if (/\/\*XORP Configuration File, v1.0\*\//) { - $xorp_cfg = 1; - last; - } - elsif (/vyatta-config-version/) { - $valid_cfg = 1; - last; - } - elsif (/vyos-config-version/) { - $valid_cfg = 1; - last; - } -} -if ( $xorp_cfg or !$valid_cfg ) { - if ($xorp_cfg) { - print "Warning: Loading a pre-Glendale configuration.\n"; - } - else { - print "Warning: file does NOT appear to be a valid config file.\n"; - } - if ( !prompt( "Do you want to continue? ", -tty, -Yes, -default => 'no' ) ) - { - print "Configuration not loaded\n"; - exit 1; - } -} -close $cfg; - -# log it -openlog( $0, "", LOG_USER ); -my $login = getlogin() || getpwuid($<) || "unknown"; -syslog( "warning", "Load config [$orig_load_file] by $login" ); - -# do config migration -system("$vyos_libexec_dir/run-config-migration.py $load_file"); - -# note: "load" is now handled in the backend so only "merge" is actually -# handled in this script. "merge" hasn't been moved into the backend since -# the command itself needs to be revisited after mendocino time frame. - -# when presenting to users, show shortened /config path -my $shortened_load_file = get_short_config_path($load_file); -print "Loading configuration from '$shortened_load_file'...\n"; - -my $cobj = new Vyatta::Config; -if (!defined($merge)) { - # "load" => use backend through API - $cobj->loadFile($load_file); -} else { - # "merge" => handled here - my %cfg_hier = Vyatta::ConfigLoad::loadConfigHierarchy($load_file,$merge); - if ( scalar( keys %cfg_hier ) == 0 ) { - print "The specified file does not contain any configuration.\n"; - print - "Do you want to remove everything in the running configuration? [no] "; - my $resp = <STDIN>; - if ( !( $resp =~ /^yes$/i ) ) { - print "Configuration not loaded\n"; - exit 1; - } - } - - my %cfg_diff = Vyatta::ConfigLoad::getConfigDiff(\%cfg_hier); - my @set_list = @{ $cfg_diff{'set'} }; - foreach (@set_list) { - my ( $cmd_ref, $rank ) = @{$_}; - my @cmd = ( "$sbindir/my_set", @{$cmd_ref} ); - my $cmd_str = join ' ', @cmd; - system("$cmd_str"); - if ( $? >> 8 ) { - $cmd_str =~ s/^$sbindir\/my_//; - print "\"$cmd_str\" failed\n"; - } - } -} - -if (!($cobj->sessionChanged())) { - print "No configuration changes to commit\n"; - exit 0; -} - -print ("\n" . (defined($merge) ? 'Merge' : 'Load') - . " complete. Use 'commit' to make changes active.\n"); -exit 0; |