mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1385 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1385 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| # IBM(c) 2010 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head1
 | |
|   xCAT plugin package to handle xdsh
 | |
| 
 | |
|    Supported command:
 | |
|          nodenetconn
 | |
|          ipforward (internal command)
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| package xCAT_plugin::route;
 | |
| 
 | |
| BEGIN
 | |
| {
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| use lib "$::XCATROOT/lib/perl";
 | |
| use strict;
 | |
| use xCAT::Table;
 | |
| use xCAT::Utils;
 | |
| use xCAT::TableUtils;
 | |
| use xCAT::ServiceNodeUtils;
 | |
| use xCAT::NetworkUtils;
 | |
| use xCAT::MsgUtils;
 | |
| use Getopt::Long;
 | |
| use xCAT::NodeRange;
 | |
| use Data::Dumper;
 | |
| use xCAT::NodeRange;
 | |
| use IO::File;
 | |
| use File::Copy;
 | |
| use File::Path;
 | |
| use Sys::Hostname;
 | |
| 
 | |
| 
 | |
| my $xcat_config_start = "# xCAT_CONFIG_START";
 | |
| my $xcat_config_end   = "# xCAT_CONFIG_END";
 | |
| 
 | |
| 
 | |
| 
 | |
| 1;
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  handled_commands
 | |
| 
 | |
| Return list of commands handled by this plugin
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| sub handled_commands
 | |
| {
 | |
|     return {
 | |
|         makeroutes => "route",
 | |
|         ipforward  => "route"
 | |
|     };
 | |
| }
 | |
| 
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  preprocess_request
 | |
| 
 | |
|   Preprocess the command
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub preprocess_request
 | |
| {
 | |
|     my $request  = shift;
 | |
|     my $callback = shift;
 | |
|     my $sub_req  = shift;
 | |
|     my $command  = $request->{command}->[0];
 | |
|     my $args     = $request->{arg};
 | |
| 
 | |
|     #if already preprocessed, go straight to request
 | |
|     if ((defined($request->{_xcatpreprocessed}))
 | |
|         && ($request->{_xcatpreprocessed}->[0] == 1))
 | |
|     {
 | |
|         return [$request];
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if ($command eq "ipforward") {
 | |
|         my $nodes = $request->{node};
 | |
|         my @sns   = ();
 | |
|         if ($nodes) {
 | |
|             @sns = @$nodes;
 | |
|         }
 | |
| 
 | |
|         #print "sns=@sns\n";
 | |
|         my @requests = ();
 | |
|         foreach (@sns) {
 | |
|             my $reqcopy = {%$request};
 | |
|             $reqcopy->{'node'}                 = [];
 | |
|             $reqcopy->{'_xcatdest'}            = $_;
 | |
|             $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | |
|             push @requests, $reqcopy;
 | |
|         }
 | |
|         return \@requests;
 | |
|     } else {
 | |
| 
 | |
|         # parse the options
 | |
|         @ARGV = ();
 | |
|         if ($args) {
 | |
|             @ARGV = @{$args};
 | |
|         }
 | |
|         Getopt::Long::Configure("bundling");
 | |
|         Getopt::Long::Configure("no_pass_through");
 | |
| 
 | |
|         my $routelist_in;
 | |
|         my $delete = 0;
 | |
|         if (!GetOptions(
 | |
|                 'h|help'        => \$::HELP,
 | |
|                 'v|version'     => \$::VERSION,
 | |
|                 'r|routename=s' => \$routelist_in,
 | |
|                 'd|delete'      => \$delete,
 | |
|             ))
 | |
|         {
 | |
|             &usage($callback);
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         # display the usage if -h or --help is specified
 | |
|         if ($::HELP) {
 | |
|             &usage($callback);
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         # display the version statement if -v or --verison is specified
 | |
|         if ($::VERSION)
 | |
|         {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = xCAT::Utils->Version();
 | |
|             $callback->($rsp);
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         #make sure the input routes are in the routes table.
 | |
|         if ($routelist_in) {
 | |
|             my %all_routes = ();
 | |
|             my $routestab = xCAT::Table->new("routes", -create => 1);
 | |
|             if ($routestab) {
 | |
|                 my @tmp1 = $routestab->getAllAttribs(('routename', 'net'));
 | |
|                 if (@tmp1 > 0) {
 | |
|                     foreach (@tmp1) {
 | |
|                         $all_routes{ $_->{routename} } = $_;
 | |
|                         $_->{process} = 0;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             my @badroutes = ();
 | |
|             foreach (split(',', $routelist_in)) {
 | |
|                 if (!exists($all_routes{$_})) {
 | |
|                     push(@badroutes, $_);
 | |
|                 }
 | |
|             }
 | |
|             if (@badroutes > 0) {
 | |
|                 my $rsp = {};
 | |
|                 my $badroutes_s = join(',', @badroutes);
 | |
|                 if (@badroutes == 1) {
 | |
|                     $rsp->{error}->[0] = "The route $badroutes_s is not defined in the routes table.";
 | |
|                 }
 | |
|                 else {
 | |
|                     $rsp->{error}->[0] = "The routes $badroutes_s are not defined in the routes table.";
 | |
|                 }
 | |
|                 $callback->($rsp);
 | |
|                 return 1;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (@ARGV == 0) {    #no noderange is specifiled, assume it is on the mn
 | |
|             my $reqcopy = {%$request};
 | |
|             $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | |
|             if ($routelist_in) {
 | |
|                 $reqcopy->{routelist}->[0] = $routelist_in;
 | |
|             }
 | |
|             if ($delete) {
 | |
|                 $reqcopy->{delete}->[0] = 1;
 | |
|             }
 | |
|             return [$reqcopy];
 | |
|         }
 | |
|         else {               #noderange is specified,
 | |
|             my $ret         = [];
 | |
|             my $nr          = $ARGV[0];
 | |
|             my @noderange   = xCAT::NodeRange::noderange($nr, 1);
 | |
|             my @missednodes = xCAT::NodeRange::nodesmissed();
 | |
|             if (@missednodes > 0) {
 | |
|                 my $rsp = {};
 | |
|                 $rsp->{error}->[0] = "Invalide nodes in noderange: " . join(',', @missednodes);
 | |
|                 $callback->($rsp);
 | |
|                 return 1;
 | |
|             }
 | |
|             my @servicenodes = xCAT::ServiceNodeUtils->getSNList();
 | |
| 
 | |
|             #print "noderange=@noderange, missednodes=@missednodes, servicenodes=@servicenodes\n";
 | |
| 
 | |
|             #pick out the service nodes from the node list
 | |
|             foreach my $sn (@servicenodes) {
 | |
|                 if (grep /^$sn$/, @noderange) {
 | |
|                     @noderange = grep(!/^$sn$/, @noderange);
 | |
|                     my $reqcopy = {%$request};
 | |
|                     $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | |
|                     $reqcopy->{'_xcatdest'}            = $sn;
 | |
|                     $reqcopy->{node}                   = [$sn];
 | |
|                     if ($routelist_in) {
 | |
|                         $reqcopy->{routelist}->[0] = $routelist_in;
 | |
|                     }
 | |
|                     if ($delete) {
 | |
|                         $reqcopy->{delete}->[0] = 1;
 | |
|                     }
 | |
|                     push(@$ret, $reqcopy);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             #now find out the service nodes for each node and
 | |
|             #send the request to the service node
 | |
|             my $sn_hash = xCAT::ServiceNodeUtils->get_ServiceNode(\@noderange, "xcat", "MN");
 | |
| 
 | |
|             # build each request for each service node
 | |
|             foreach my $sn (keys %$sn_hash)
 | |
|             {
 | |
|                 my $reqcopy = {%$request};
 | |
|                 $reqcopy->{node}                   = $sn_hash->{$sn};
 | |
|                 $reqcopy->{'_xcatdest'}            = $sn;
 | |
|                 $reqcopy->{_xcatpreprocessed}->[0] = 1;
 | |
|                 $reqcopy->{remote}->[0]            = 1;
 | |
|                 if ($routelist_in) {
 | |
|                     $reqcopy->{routelist}->[0] = $routelist_in;
 | |
|                 }
 | |
|                 if ($delete) {
 | |
|                     $reqcopy->{delete}->[0] = 1;
 | |
|                 }
 | |
|                 push(@$ret, $reqcopy);
 | |
|             }
 | |
| 
 | |
|             return $ret;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  process_request
 | |
| 
 | |
|   Process the command
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub process_request
 | |
| {
 | |
| 
 | |
|     my $request  = shift;
 | |
|     my $callback = shift;
 | |
|     my $sub_req  = shift;
 | |
|     my $command  = $request->{command}->[0];
 | |
| 
 | |
|     if ($command eq "makeroutes") {
 | |
|         return process_makeroutes($request, $callback, $sub_req);
 | |
|     } elsif ($command eq "ipforward") {
 | |
|         return process_ipforward($request, $callback, $sub_req);
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| sub process_makeroutes {
 | |
|     my $request  = shift;
 | |
|     my $callback = shift;
 | |
|     my $sub_req  = shift;
 | |
|     my $command  = $request->{command}->[0];
 | |
| 
 | |
|     my $nodes;
 | |
|     if (exists($request->{node})) {
 | |
|         $nodes = $request->{node};
 | |
|     }
 | |
| 
 | |
|     my $delete = 0;
 | |
|     if (exists($request->{delete})) {
 | |
|         $delete = $request->{delete}->[0];
 | |
|     }
 | |
| 
 | |
|     my $remote = 0;
 | |
|     if (exists($request->{remote})) {
 | |
|         $remote = $request->{remote}->[0];
 | |
|     }
 | |
| 
 | |
| 
 | |
|     my $routelist;
 | |
|     if (exists($request->{routelist})) {
 | |
|         $routelist = $request->{routelist}->[0];
 | |
|     }
 | |
| 
 | |
| 
 | |
|     #get all the routes from the routes table
 | |
|     my %all_routes = ();
 | |
|     my $routestab = xCAT::Table->new("routes", -create => 1);
 | |
|     if ($routestab) {
 | |
|         my @tmp1 = $routestab->getAllAttribs(('routename', 'net', 'mask', 'gateway', 'ifname'));
 | |
|         if (@tmp1 > 0) {
 | |
|             foreach (@tmp1) {
 | |
|                 $all_routes{ $_->{routename} } = $_;
 | |
|                 $_->{process} = 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($routelist) {
 | |
|         foreach (split(',', $routelist)) {
 | |
|             $all_routes{$_}->{process} = 1;
 | |
|             if (($nodes) && ($remote)) {
 | |
|                 $all_routes{$_}->{nodes} = $nodes;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         #get the routes for each nodes from the noderes table (for sn and cn) and site table (for mn)
 | |
|         if ($nodes) {
 | |
|             my $nrtab = xCAT::Table->new("noderes", -create => 1);
 | |
|             my $nrhash = $nrtab->getNodesAttribs($nodes, ['routenames']);
 | |
|             foreach (@$nodes) {
 | |
|                 my $node = $_;
 | |
|                 my $rn;
 | |
|                 my $ent = $nrhash->{$node}->[0];
 | |
|                 if (ref($ent) and defined $ent->{routenames}) {
 | |
|                     $rn = $ent->{routenames};
 | |
|                 }
 | |
|                 if ($rn) {
 | |
|                     my @a = split(',', $rn);
 | |
|                     my @badroutes = ();
 | |
|                     foreach my $r (@a) {
 | |
|                         if (!exists($all_routes{$r})) {
 | |
|                             push(@badroutes, $r);
 | |
|                         }
 | |
|                         else {
 | |
|                             #print "got here...., remote=$remote\n";
 | |
|                             $all_routes{$r}->{process} = 1;
 | |
|                             if ($remote) {
 | |
|                                 my $pa = $all_routes{$r}->{nodes};
 | |
|                                 if ($pa) {
 | |
|                                     push(@$pa, $node);
 | |
|                                 }
 | |
|                                 else {
 | |
|                                     $all_routes{$r}->{nodes} = [$node];
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     if (@badroutes > 0) {
 | |
|                         my $badroutes_s = join(',', @badroutes);
 | |
|                         my $rsp = {};
 | |
|                         if (@badroutes == 1) {
 | |
|                             $rsp->{error}->[0] = "The route $badroutes_s is not defined in the routes table. Please check noderes.routenames for node $node.";
 | |
|                         }
 | |
|                         else {
 | |
|                             $rsp->{error}->[0] = "The routes $badroutes_s are not defined in the routes table. Please check noderes.routenames for node $node.";
 | |
|                         }
 | |
|                         $callback->($rsp);
 | |
|                         return 1;
 | |
|                     }
 | |
|                 }
 | |
|                 else {
 | |
|                     my $rsp = {};
 | |
|                     $rsp->{data}->[0] = "No routes defined in noderes.routenames for node $node, skiping $node.";
 | |
|                     $callback->($rsp);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         else {    #this is mn, get the routes from the site table
 | |
|             my @mnroutes = xCAT::TableUtils->get_site_attribute("mnroutenames");
 | |
|             if ($mnroutes[0]) {
 | |
|                 my @a = split(',', $mnroutes[0]);
 | |
|                 my @badroutes = ();
 | |
|                 foreach my $r (@a) {
 | |
|                     if (!exists($all_routes{$r})) {
 | |
|                         push(@badroutes, $r);
 | |
|                     }
 | |
|                     else {
 | |
|                         $all_routes{$r}->{process} = 1;
 | |
|                     }
 | |
|                 }
 | |
|                 if (@badroutes > 0) {
 | |
|                     my $badroutes_s = join(',', @badroutes);
 | |
|                     my $rsp = {};
 | |
|                     if (@badroutes == 1) {
 | |
|                         $rsp->{error}->[0] = "The route $badroutes_s is not defined in the routes table. Please check site.mnroutenames for the management node.";
 | |
|                     }
 | |
|                     else {
 | |
|                         $rsp->{error}->[0] = "The routes $badroutes_s are not defined in the routes table. Please check site.mnroutenames for the management node.";
 | |
|                     }
 | |
|                     $callback->($rsp);
 | |
|                     return 1;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 my $rsp = {};
 | |
|                 $rsp->{data}->[0] = "No routes defined in the site.mnroutenames for the management node.";
 | |
|                 $callback->($rsp);
 | |
|                 return 1;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #print Dumper(%all_routes);
 | |
| 
 | |
|     #now let's handle the route creatation and deletion
 | |
|     my @sns        = ();
 | |
|     my $installdir = xCAT::TableUtils->getInstallDir();
 | |
|     while (my ($routename, $route_hash) = each(%all_routes)) {
 | |
|         if ($route_hash->{process}) {
 | |
|             my ($gw_name, $gw_ip) = xCAT::NetworkUtils->gethostnameandip($route_hash->{gateway});
 | |
|             push(@sns, $gw_name);
 | |
| 
 | |
|             if ($route_hash->{net} =~ /:/) {
 | |
| 
 | |
|                 # Remove the subnet postfix like /64
 | |
|                 if ($route_hash->{net} =~ /\//) {
 | |
|                     $route_hash->{net} =~ s/\/.*$//;
 | |
|                 }
 | |
| 
 | |
|                 # Remove the "/" from the ipv6 prefixlength
 | |
|                 if ($route_hash->{mask}) {
 | |
|                     if ($route_hash->{mask} =~ /\//) {
 | |
|                         $route_hash->{mask} =~ s/^\///;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if ($remote) {    #to the nodes
 | |
|                 my $nodes_tmp = $route_hash->{nodes};
 | |
| 
 | |
|                 #print "nodes=@$nodes_tmp, remote=$remote, delete=$delete\n";
 | |
|                 my $op = "add";
 | |
|                 if ($delete) { $op = "delete"; }
 | |
|                 my $output = xCAT::Utils->runxcmd(
 | |
|                     {
 | |
|                         command => ["xdsh"],
 | |
|                         node    => $nodes_tmp,
 | |
|                         arg => [ "-e", "/$installdir/postscripts/routeop $op " . $route_hash->{net} . " " . $route_hash->{mask} . " $gw_ip" . " $route_hash->{ifname}" ],
 | |
|                         _xcatpreprocessed => [1],
 | |
|                     },
 | |
|                     $sub_req, -1, 1);
 | |
|                 my $rsp = {};
 | |
|                 $rsp->{data} = $output;
 | |
|                 $callback->($rsp);
 | |
|             }
 | |
|             else {    #local on mn or sn
 | |
|                 if ($delete) {
 | |
|                     delete_route($callback, $route_hash->{net}, $route_hash->{mask}, $gw_ip, $gw_name, $route_hash->{ifname});
 | |
|                 }
 | |
|                 else {
 | |
|                     set_route($callback, $route_hash->{net}, $route_hash->{mask}, $gw_ip, $gw_name, $route_hash->{ifname});
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     #not all gateways are service nodes
 | |
|     my %sn_hash    = ();
 | |
|     my @allSN      = xCAT::ServiceNodeUtils->getAllSN();
 | |
|     my %allSN_hash = ();
 | |
|     foreach (@allSN) { $allSN_hash{$_} = 1; }
 | |
|     foreach my $sn (@sns) {
 | |
|         if (exists($allSN_hash{$sn})) {
 | |
|             $sn_hash{$sn} = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #update servicenode.ipforward
 | |
|     my $sntab = xCAT::Table->new("servicenode", -create => 1, -autocommit => 1);
 | |
|     my %valuehash = ();
 | |
|     my $value     = 1;
 | |
|     if ($delete) { $value = 0; }
 | |
|     foreach my $sn (keys %sn_hash) {
 | |
|         $valuehash{$sn} = { ipforward => $value };
 | |
|     }
 | |
|     $sntab->setNodesAttribs(\%valuehash);
 | |
| 
 | |
|     #go to the service nodes to enable/disable ipforwarding
 | |
|     my @nodes = keys(%sn_hash);
 | |
|     $sub_req->({
 | |
|             command => ['ipforward'],
 | |
|             node    => \@nodes,
 | |
|             arg     => [$delete] },
 | |
|         $callback);
 | |
| 
 | |
| 
 | |
| }
 | |
| 
 | |
| sub process_ipforward {
 | |
|     my $request  = shift;
 | |
|     my $callback = shift;
 | |
|     my $sub_req  = shift;
 | |
|     my $args     = $request->{arg};
 | |
| 
 | |
|     my $delete = 0;
 | |
|     if ($args) {
 | |
|         $delete = $args->[0];
 | |
|     }
 | |
| 
 | |
|     if ($delete) {
 | |
|         xCAT::NetworkUtils->setup_ip_forwarding(0);
 | |
|     } else {
 | |
|         xCAT::NetworkUtils->setup_ip_forwarding(1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| sub usage {
 | |
|     my $cb  = shift;
 | |
|     my $rsp = {};
 | |
| 
 | |
|     $rsp->{data}->[0] = "Usage: makeroutes -h";
 | |
|     $rsp->{data}->[1] = "       makeroutes -v";
 | |
|     $rsp->{data}->[2] = "       makeroutes [-r routename[,routename...]]";
 | |
|     $rsp->{data}->[3] = "       makeroutes [-r routename[,routename...]] -d ";
 | |
|     $rsp->{data}->[4] = "       makeroutes noderange [-r routename[,routename...]]";
 | |
|     $rsp->{data}->[5] = "       makeroutes noderange [-r routename[,routename...]] -d";
 | |
|     $cb->($rsp);
 | |
| }
 | |
| 
 | |
| #check if the route exits or not from the route table
 | |
| sub route_exists {
 | |
|     my $net    = shift;
 | |
|     my $mask   = shift;
 | |
|     my $gw_ip  = shift;
 | |
|     my $gw     = shift;
 | |
|     my $ifname = shift;
 | |
| 
 | |
|     my $islinux = xCAT::Utils->isLinux();
 | |
| 
 | |
|     # ipv6 net
 | |
|     if ($net =~ /:/) {
 | |
|         if ($islinux) {
 | |
|             my $result = `ip -6 route show $net/$mask`;
 | |
| 
 | |
|             # ip -6 route show will return nothing if the route does not exist
 | |
|             if (!$result || ($? != 0))
 | |
|             {
 | |
|                 return 0;
 | |
|             } else {
 | |
|                 return 1;
 | |
|             }
 | |
|         } else {    # AIX
 | |
|                     # TODO
 | |
|         }
 | |
|     } else {
 | |
|         my $result;
 | |
|         $result = `netstat -nr|grep $net`;
 | |
|         if ($? == 0) {
 | |
|             if ($result) {
 | |
|                 my @b = split('\n', $result);
 | |
|                 foreach my $tmp (@b) {
 | |
|                     chomp($tmp);
 | |
|                     my @a = split(' ', $tmp);
 | |
|                     if ($islinux) {    #Linux
 | |
|                         if (@a >= 3) {
 | |
|                             my $net1    = $a[0];
 | |
|                             my $mask1   = $a[2];
 | |
|                             my $gw1     = $a[1];
 | |
|                             my $ifname1 = $a[7];
 | |
|                             if (($net1 eq $net) && ($mask1 eq $mask) && (($gw1 eq $gw) || ($gw1 eq $gw_ip) || ($ifname1 eq $ifname))) {
 | |
|                                 return 1;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     else {             #AIX
 | |
|                         if (@a >= 2) {
 | |
|                             my $tmp1 = $a[0];
 | |
|                             my $gw1  = $a[1];
 | |
| 
 | |
|                             #now convert $mask to bits
 | |
|                             $net =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/;
 | |
|                             my $netnum = ($1 << 24) + ($2 << 16) + ($3 << 8) + $4;
 | |
|                             my $bits = 32;
 | |
|                             while (($netnum % 2) == 0) {
 | |
|                                 $bits--;
 | |
|                                 $netnum = $netnum >> 1;
 | |
|                             }
 | |
|                             my $tmp2 = "$net/$bits";
 | |
|                             if (($tmp1 eq $tmp2) && (($gw1 eq $gw) || ($gw1 eq $gw_ip))) {
 | |
|                                 return 1;
 | |
|                             }
 | |
|                         }    # end if (@a >= 2)
 | |
|                     }    #end else linux/aix
 | |
|                 }    # end foreach
 | |
|             }    # end if ($result)
 | |
|         }    # end if ($? == 0
 | |
|     }    # end else ipv4/ipv6
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| # sets the route with given parameters
 | |
| sub set_route {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     #print "set_route get called\n";
 | |
| 
 | |
|     my $result;
 | |
|     if (!route_exists($net, $mask, $gw_ip, $gw, $ifname)) {
 | |
| 
 | |
|         #set temporay route
 | |
|         my $cmd;
 | |
| 
 | |
|         # ipv6 network
 | |
|         if ($net =~ /:/) {
 | |
|             if (xCAT::Utils->isLinux()) {
 | |
|                 if ($gw_ip eq "" || $gw_ip eq "::") {
 | |
|                     $cmd = "ip -6 route add $net/$mask dev $ifname";
 | |
|                 } else {
 | |
|                     $cmd = "ip -6 route add $net/$mask via $gw_ip";
 | |
|                 }
 | |
|             } else {
 | |
| 
 | |
|                 # AIX TODO
 | |
|             }
 | |
|         } else {
 | |
|             if (xCAT::Utils->isLinux()) {
 | |
|                 if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|                     $cmd = "route add -net $net netmask $mask dev $ifname";
 | |
|                 } else {
 | |
|                     $cmd = "route add -net $net netmask $mask gw $gw_ip";
 | |
|                 }
 | |
|             } else {
 | |
|                 $cmd = "route add -net $net -netmask $mask $gw_ip";
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #print "cmd=$cmd\n";
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Adding temporary route: $cmd";
 | |
|         $callback->($rsp);
 | |
| 
 | |
|         $result = `$cmd 2>&1`;
 | |
|         if ($? != 0) {
 | |
|             my $rsp = {};
 | |
|             $rsp->{error}->[0] = "$host: $cmd\nerror code=$?, result=$result\n";
 | |
|             $callback->($rsp);
 | |
| 
 | |
|             #return 1;
 | |
|         }
 | |
|     } else {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: The temporary route already exists for $net.";
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| 
 | |
|     #handle persistent routes
 | |
|     if (xCAT::Utils->isLinux()) {    #Linux
 | |
|         my $os = xCAT::Utils->osver();
 | |
| 
 | |
|         #print "os=$os  $net, $mask, $gw_ip, $gw, $ifname\n";
 | |
|         if ($os =~ /sles/) {         #sles
 | |
|             addPersistentRoute_Sles($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         } elsif ($os =~ /ubuntu|debian/) {    #ubuntu or Debian?
 | |
|             addPersistentRoute_Debian($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         }
 | |
|         elsif ($os =~ /rh|fedora|centos/) {    #RH, Ferdora, CentOS
 | |
|             addPersistentRoute_RH($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         }
 | |
|     } else {    #AIX
 | |
|                 # chdev -l inet0 -a route=net,-hopcount,0,,0,192.168.1.1
 | |
|          # chdev -l inet0 -a route=net, -hopcount,255.255.255.128,,,,,192.168.3.155,192.168.2.1
 | |
|          # lsattr -El inet0 -a route
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Adding persistent route on AIX is not supported yet.";
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| # deletes the route with given parameters
 | |
| sub delete_route {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     #print "delete_route get called\n";
 | |
| 
 | |
|     my $result;
 | |
|     if (route_exists($net, $mask, $gw_ip, $gw, $ifname)) {
 | |
| 
 | |
|         #delete  route temporarily
 | |
|         my $cmd;
 | |
|         if ($net =~ /:/) {
 | |
|             if (xCAT::Utils->isLinux()) {
 | |
|                 if ($gw_ip eq "" || $gw_ip eq "::") {
 | |
|                     $cmd = "ip -6 route delete $net/$mask dev $ifname";
 | |
|                 } else {
 | |
|                     $cmd = "ip -6 route delete $net/$mask via $gw_ip";
 | |
|                 }
 | |
|             } else {
 | |
| 
 | |
|                 # AIX TODO
 | |
|             }
 | |
|         } else {
 | |
|             if (xCAT::Utils->isLinux()) {
 | |
|                 if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|                     $cmd = "route delete -net $net netmask $mask dev $ifname";
 | |
|                 } else {
 | |
|                     $cmd = "route delete -net $net netmask $mask gw $gw_ip";
 | |
|                 }
 | |
|             } else {
 | |
|                 $cmd = "route delete -net $net -netmask $mask $gw_ip";
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #print "cmd=$cmd\n";
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Removing the temporary route: $cmd";
 | |
|         $callback->($rsp);
 | |
| 
 | |
|         $result = `$cmd 2>&1`;
 | |
|         if ($? != 0) {
 | |
|             my $rsp = {};
 | |
|             $rsp->{error}->[0] = "$host: $cmd\nerror code=$?, result=$result\n";
 | |
|             $callback->($rsp);
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         my $rsp = {};
 | |
|         if ($net =~ /:/) {
 | |
|             $rsp->{data}->[0] = "$host: The temporary route does not exist for $net/$mask.";
 | |
|         } else {
 | |
|             $rsp->{data}->[0] = "$host: The temporary route does not exist for $net.";
 | |
|         }
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| 
 | |
|     #handle persistent route
 | |
|     if (xCAT::Utils->isLinux()) {    #Linux
 | |
|         my $os = xCAT::Utils->osver();
 | |
|         if ($os =~ /sles/) {         #sles
 | |
|             deletePersistentRoute_Sles($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         } elsif ($os =~ /ubuntu/) {    #ubuntu or Debian?
 | |
|             deletePersistentRoute_Debian($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         }
 | |
|         elsif ($os =~ /rh|fedora|centos/) {    #RH, Ferdora
 | |
|             deletePersistentRoute_RH($callback, $net, $mask, $gw_ip, $gw, $ifname);
 | |
|         }
 | |
|     }
 | |
|     else {                                     #AIX
 | |
|             # chdev -l inet0 -a delroute=net,-hopcount,0,,0,192.168.1.1
 | |
|          # chdev -l inet0 -a delroute=net,-hopcount,255.255.255.128,,,,,192.168.3.128,192.168.2.1
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Removing persistent route on AIX is not supported yet.";
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| #set the given route to the configuration file
 | |
| sub setConfig {
 | |
|     my $filename       = shift;
 | |
|     my $new_conf_block = shift;
 | |
| 
 | |
|     #print "filename=$filename\n";
 | |
| 
 | |
|     my $new_config = join("\n", @$new_conf_block);
 | |
|     my $last_char = substr $new_config, -1, 1;
 | |
|     if ($last_char ne "\n") { $new_config .= "\n"; }
 | |
| 
 | |
|     my $filename_tmp = "$filename.$$";
 | |
|     open(OUTFILE, '>', $filename_tmp);
 | |
|     my $found = 0;
 | |
|     if (-f $filename) {
 | |
|         open(INFILE, '<', $filename);
 | |
|         my $inblock = 0;
 | |
|         while (<INFILE>) {
 | |
|             my $line = $_;
 | |
|             if (!$inblock) {
 | |
|                 print OUTFILE $line;
 | |
|             }
 | |
|             if ($line =~ /$xcat_config_start/) {
 | |
|                 $found   = 1;
 | |
|                 $inblock = 1;
 | |
|                 print OUTFILE $new_config;
 | |
|             } elsif ($line =~ /$xcat_config_end/) {
 | |
|                 $inblock = 0;
 | |
|                 print OUTFILE "$xcat_config_end\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     if (!$found) {
 | |
|         print OUTFILE "$xcat_config_start\n";
 | |
|         print OUTFILE $new_config;
 | |
|         print OUTFILE "$xcat_config_end\n";
 | |
|     }
 | |
|     close(INFILE);
 | |
|     close(OUTFILE);
 | |
|     copy($filename_tmp, $filename);
 | |
|     unlink($filename_tmp);
 | |
| }
 | |
| 
 | |
| #gets the xCAT configurations from the given file
 | |
| sub getConfig {
 | |
|     my $filename = shift;
 | |
|     my @output   = ();
 | |
|     if (-f $filename) {
 | |
|         open(FILE, "<", $filename);
 | |
|         my $xcatconf = 0;
 | |
|         my $first    = 0;
 | |
|         while (<FILE>) {
 | |
|             chomp;
 | |
|             if (/$xcat_config_start/) {
 | |
|                 $xcatconf = 1;
 | |
|                 $first    = 1;
 | |
|             }
 | |
|             elsif (/$xcat_config_end/) {
 | |
|                 $xcatconf = 0;
 | |
|             }
 | |
|             if ($first) {
 | |
|                 $first = 0;
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             if ($xcatconf) {
 | |
|                 push @output, $_;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return @output;
 | |
| }
 | |
| 
 | |
| #add the routes to the /etc/sysconfig/network/routes file
 | |
| #The format is: destination  gateway  mask  ifname
 | |
| sub addPersistentRoute_Sles {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     my $filename = "/etc/sysconfig/network/routes";
 | |
|     my @output   = getConfig($filename);
 | |
| 
 | |
|     #print "old output=" . join("\n", @output) . "\n";
 | |
|     my $hasConfiged = 0;
 | |
|     if (@output && (@output > 0)) {
 | |
|         $hasConfiged = checkConfig_Sles($net, $mask, $gw_ip, $gw, $ifname, \@output);
 | |
|     }
 | |
| 
 | |
|     #print "hasConfiged=$hasConfiged\n";
 | |
|     my $new_config;
 | |
|     if ($net =~ /:/) {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "::") {
 | |
|             $new_config = "$net/$mask :: - $ifname\n";
 | |
|         } else {
 | |
|             $new_config = "$net/$mask $gw_ip - -\n";
 | |
|         }
 | |
|     } else {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|             $new_config = "$net 0.0.0.0 $mask $ifname\n";
 | |
|         } else {
 | |
|             $new_config = "$net $gw_ip $mask $ifname\n";
 | |
|         }
 | |
|     }
 | |
|     if (!$hasConfiged) {
 | |
|         push(@output, $new_config);
 | |
| 
 | |
|         #print "new output=" . join("\n", @output) . "\n";
 | |
|         #Add the route to the configuration file
 | |
|         #the format is: destination  gateway  mask  ifname
 | |
|         setConfig($filename, \@output);
 | |
| 
 | |
|         chomp($new_config);
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Added persistent route \"$new_config\" to $filename.";
 | |
|         $callback->($rsp);
 | |
|     } else {
 | |
|         chomp($new_config);
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Persistent route \"$new_config\" already exists in $filename.";
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #remove the routes from the /etc/sysconfig/network/routes file
 | |
| sub deletePersistentRoute_Sles {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     my $filename = "/etc/sysconfig/network/routes";
 | |
|     my @output   = getConfig($filename);
 | |
| 
 | |
|     #print "old output=" . join("\n", @output) . "\n";
 | |
|     my @new_output = ();
 | |
|     my $bigfound   = 0;
 | |
|     foreach my $tmp_conf (@output) {
 | |
|         my $found = checkConfig_Sles($net, $mask, $gw_ip, $gw, $ifname, [$tmp_conf]);
 | |
|         if (!$found) {
 | |
|             push(@new_output, $tmp_conf);
 | |
|         } else {
 | |
|             $bigfound = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #print "new output=" . join("\n", @new_output) . "\n";
 | |
|     #set the new configuration to the configuration file
 | |
|     setConfig($filename, \@new_output);
 | |
|     if ($bigfound) {
 | |
|         my $rsp = {};
 | |
|         if ($net =~ /:/) {
 | |
|             $rsp->{data}->[0] = "$host: Removed persistent route \"$net/$mask $gw_ip\" from $filename.";
 | |
|         } else {
 | |
|             $rsp->{data}->[0] = "$host: Removed persistent route \"$net $gw_ip $mask $ifname\" from $filename.";
 | |
|         }
 | |
|         $callback->($rsp);
 | |
|     } else {
 | |
|         my $rsp = {};
 | |
|         if ($net =~ /:/) {
 | |
|             $rsp->{data}->[0] = "$host: Persistent route \"$net/$mask $gw_ip\" does not exist in $filename.";
 | |
|         } else {
 | |
|             $rsp->{data}->[0] = "$host: Persistent route \"$net $gw_ip $mask $ifname\" does not exist in $filename.";
 | |
|         }
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| #check if the route is in the SLES network configuration file
 | |
| sub checkConfig_Sles {
 | |
|     my $net    = shift;
 | |
|     my $mask   = shift;
 | |
|     my $gw_ip  = shift;
 | |
|     my $gw     = shift;
 | |
|     my $ifname = shift;
 | |
|     my $output = shift;
 | |
| 
 | |
|     # Format:
 | |
|     # DESTINATION GATEWAY NETMASK INTERFACE
 | |
|     # DESTINATION/PREFIXLEN GATEWAY - INTERFACE
 | |
| 
 | |
|     # ipv4 format: 192.168.0.0 207.68.156.51 255.255.0.0 eth1
 | |
|     # ipv6 format: fd59::/64 fd57:faaf:e1ab:336:21a:64ff:fe01:1 - -
 | |
|     foreach my $line (@$output) {
 | |
|         my @a = split(' ', $line);
 | |
|         my ($net1, $mask1, $gw1, $ifname1);
 | |
|         if ($net =~ /:/) {
 | |
|             if (@a > 0) {
 | |
|                 my $ipv6net = $a[0];
 | |
|                 ($net1, $mask1) = split("/", $ipv6net);
 | |
|             }
 | |
|             if (@a > 1) {
 | |
|                 $gw1 = $a[1];
 | |
|                 if ($gw1 eq '-') { $gw1 = $gw_ip; }
 | |
|             }
 | |
|             if (@a > 3) {
 | |
|                 $ifname1 = $a[3];
 | |
|                 if ($ifname1 eq '-') { $ifname1 = $ifname; }
 | |
|             }
 | |
| 
 | |
|         } else {
 | |
|             if (@a > 0) {
 | |
|                 $net1 = $a[0];
 | |
|                 if ($net1 eq '-') { $net1 = $net; }
 | |
|             }
 | |
|             if (@a > 1) {
 | |
|                 $gw1 = $a[1];
 | |
|                 if ($gw1 eq '-') { $gw1 = $gw_ip; }
 | |
|             }
 | |
|             if (@a > 2) {
 | |
|                 $mask1 = $a[2];
 | |
|                 if ($mask1 eq '-') { $mask1 = $mask; }
 | |
|             }
 | |
|             if (@a > 3) {
 | |
|                 $ifname1 = $a[3];
 | |
|                 if ($ifname1 eq '-') { $ifname1 = $ifname; }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip ifname=$ifname1\n";
 | |
|         if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip) || ($ifname1 && $ifname1 eq $ifname))) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #add the routes to the /etc/sysconfig/static-routes file
 | |
| #The format is: any net 172.16.0.0 netmask 255.240.0.0 gw 192.168.0.1 eth0
 | |
| sub addPersistentRoute_RH {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     my $filename;
 | |
| 
 | |
|     # ipv6
 | |
|     if ($net =~ /:/) {
 | |
|         $filename = "/etc/sysconfig/static-routes-ipv6";
 | |
|     } else {
 | |
|         $filename = "/etc/sysconfig/static-routes";
 | |
|     }
 | |
|     my @output = getConfig($filename);
 | |
| 
 | |
|     #print "old output=" . join("\n", @output) . "\n";
 | |
|     my $hasConfiged = 0;
 | |
|     if (@output && (@output > 0)) {
 | |
|         $hasConfiged = checkConfig_RH($net, $mask, $gw_ip, $gw, $ifname, \@output);
 | |
|     }
 | |
| 
 | |
|     #print "hasConfiged=$hasConfiged\n";
 | |
|     my $new_config;
 | |
|     if ($net =~ /:/) {
 | |
| 
 | |
|         # ifname is required for ipv6 routing
 | |
|         if (!$ifname) {
 | |
|             my $rsp = {};
 | |
|             $rsp->{data}->[0] = "$host: Could not add persistent route for ipv6 network $net/$mask, the ifname is required in the routes table.";
 | |
|             $callback->($rsp);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $new_config = "$ifname $net/$mask $gw_ip";
 | |
|     } else {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|             $new_config = "any net $net netmask $mask dev $ifname\n";
 | |
|         } else {
 | |
|             $new_config = "any net $net netmask $mask gw $gw_ip\n";
 | |
|         }
 | |
|     }
 | |
|     if (!$hasConfiged) {
 | |
|         push(@output, $new_config);
 | |
| 
 | |
|         #print "new output=" . join("\n", @output) . "\n";
 | |
|         #Add the route to the configuration file
 | |
|         #the format is: destination  gateway  mask  ifname
 | |
|         setConfig($filename, \@output);
 | |
| 
 | |
|         chomp($new_config);
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Added persistent route \"$new_config\" to $filename.";
 | |
|         $callback->($rsp);
 | |
|     } else {
 | |
|         chomp($new_config);
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Persistent route \"$new_config\" already exists in $filename.";
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #remove the routes from the /etc/sysconfig/static-routes file
 | |
| sub deletePersistentRoute_RH {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host = hostname();
 | |
| 
 | |
|     my $filename;
 | |
| 
 | |
|     # ipv6
 | |
|     if ($net =~ /:/) {
 | |
|         $filename = "/etc/sysconfig/static-routes-ipv6";
 | |
|     } else {
 | |
|         $filename = "/etc/sysconfig/static-routes";
 | |
|     }
 | |
|     my @output = getConfig($filename);
 | |
| 
 | |
|     #print "old output=" . join("\n", @output) . "\n";
 | |
|     my @new_output = ();
 | |
|     my $bigfound   = 0;
 | |
|     foreach my $tmp_conf (@output) {
 | |
|         my $found = checkConfig_RH($net, $mask, $gw_ip, $gw, $ifname, [$tmp_conf]);
 | |
|         if (!$found) {
 | |
|             push(@new_output, $tmp_conf);
 | |
|         } else {
 | |
|             $bigfound = 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #print "new output=" . join("\n", @new_output) . "\n";
 | |
|     #set the new configuration to the configuration file
 | |
|     setConfig($filename, \@new_output);
 | |
|     if ($bigfound) {
 | |
|         my $rsp = {};
 | |
|         if ($net =~ /:/) {
 | |
|             $rsp->{data}->[0] = "$host: Removed persistent route \"$ifname $net/$mask $gw_ip\" from $filename.";
 | |
|         } else {
 | |
|             $rsp->{data}->[0] = "$host: Removed persistent route \"any net $net netmask $mask gw $gw_ip $ifname\" from $filename.";
 | |
|         }
 | |
|         $callback->($rsp);
 | |
|     } else {
 | |
|         my $rsp = {};
 | |
|         if ($net =~ /:/) {
 | |
|             $rsp->{data}->[0] = "$host: Persistent route \"$ifname $net/$mask $gw_ip\" does not exist in $filename.";
 | |
|         } else {
 | |
|             $rsp->{data}->[0] = "$host: Persistent route \"any net $net netmask $mask gw $gw_ip $ifname\" does not exist in $filename.";
 | |
|         }
 | |
|         $callback->($rsp);
 | |
|     }
 | |
| }
 | |
| 
 | |
| sub checkConfig_RH {
 | |
|     my $net    = shift;
 | |
|     my $mask   = shift;
 | |
|     my $gw_ip  = shift;
 | |
|     my $gw     = shift;
 | |
|     my $ifname = shift;
 | |
|     my $output = shift;
 | |
| 
 | |
|     foreach my $line (@$output) {
 | |
|         my @a = split(' ', $line);
 | |
| 
 | |
|         #The format is: any net 172.16.0.0 netmask 255.240.0.0 gw 192.168.0.1 eth0
 | |
|         # ipv6 format: eth1 fd60::/64 fd57::214:5eff:fe15:1
 | |
|         my ($net1, $mask1, $gw1, $ifname1);
 | |
|         if ($net =~ /:/) {
 | |
|             $ifname1 = $a[0];
 | |
|             if (@a > 1) {
 | |
|                 my $ipv6net = $a[1];
 | |
|                 ($net1, $mask1) = split("/", $ipv6net);
 | |
|             }
 | |
|             if (@a > 2) {
 | |
|                 $gw1 = $a[2];
 | |
|             }
 | |
|         } else {
 | |
|             if (@a > 2) {
 | |
|                 $net1 = $a[2];
 | |
|                 if ($net1 eq '-') { $net1 = $net; }
 | |
|             }
 | |
|             if (@a > 4) {
 | |
|                 $mask1 = $a[4];
 | |
|                 if ($mask1 eq '-') { $mask1 = $mask; }
 | |
|             }
 | |
|             if (@a > 6) {
 | |
|                 if ($a[5] eq 'dev') {
 | |
|                     $ifname1 = $a[6];
 | |
|                     if ($ifname1 eq '-') { $ifname1 = $ifname; }
 | |
|                 } else {
 | |
|                     $gw1 = $a[6];
 | |
|                     if ($gw1 eq '-') { $gw1 = $gw_ip; }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #print "net=$net1,$net mask=$mask1,$mask gw=$gw1,$gw_ip ifname=$ifname1,ifname\n";
 | |
|         if (($net1 && $net1 eq $net) && ($mask1 && $mask1 eq $mask) && (($gw1 && $gw1 eq $gw) || ($gw1 && $gw1 eq $gw_ip) || ($ifname1 && $ifname1 eq $ifname))) {
 | |
|             return 1;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub addPersistentRoute_Debian {
 | |
|     my $callback   = shift;
 | |
|     my $net        = shift;
 | |
|     my $mask       = shift;
 | |
|     my $gw_ip      = shift;
 | |
|     my $gw_name    = shift;
 | |
|     my $ifname     = shift;
 | |
|     my $host       = hostname();
 | |
|     my $conf_file  = "/etc/network/interfaces.d/$ifname";
 | |
|     my $cmd        = '';
 | |
|     my $route_conf = '';
 | |
| 
 | |
|     preParse_Debian();
 | |
| 
 | |
|     #ipv6
 | |
|     if ($net =~ /:/) {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "::") {
 | |
|             $cmd = "grep \"$net/$mask dev $ifname\" $conf_file";
 | |
|             $route_conf = "  up route -A inet6 add $net/$mask dev $ifname \n  down route -A inet6 del $net/$mask dev $ifname \n";
 | |
|         } else {
 | |
|             $cmd = "grep \"$net/$mask gw $gw_ip\" $conf_file";
 | |
|             $route_conf = "  up route -A inet6 add $net/$mask gw $gw_ip \n  down route -A inet6 del $net/$mask gw $gw_ip \n";
 | |
|         }
 | |
|     }
 | |
|     else {    #ipv4
 | |
|         $cmd = "grep \"-net $net netmask $mask gw $gw_ip\" $conf_file";
 | |
|         if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|             $route_conf = "  up route add -net $net netmask $mask dev $ifname \n  down route del -net $net netmask $mask dev $ifname \n";
 | |
|         } else {
 | |
|             $route_conf = "  up route add -net $net netmask $mask gw $gw_ip \n  down route del -net $net netmask $mask gw $gw_ip\n";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #fine the corresponding config in the config file
 | |
|     my @returninfo = `$cmd`;
 | |
|     if (@returninfo) {
 | |
|         my $rsp = {};
 | |
|         $rsp->{data}->[0] = "$host: Persistent route \"$returninfo[0]\" already exists in $conf_file.";
 | |
|         callback->($rsp);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     #add the configuration to the config file
 | |
|     my $readyflag = 0;
 | |
|     open(FH, "<", $conf_file);
 | |
|     my @content = <FH>;
 | |
|     close(FH);
 | |
| 
 | |
|     #read each line of the file and find the insert place
 | |
|     open(FH, ">", $conf_file);
 | |
|     foreach my $line (@content) {
 | |
| 
 | |
|         #add the route line at the end of this dev part
 | |
|         if (($readyflag == 1) && ($line =~ /iface|modprobe/)) {
 | |
|             $readyflag = 0;
 | |
|             print FH $route_conf;
 | |
|         }
 | |
| 
 | |
|         if ($line =~ /iface $ifname/) {
 | |
|             $readyflag = 1;
 | |
|         }
 | |
| 
 | |
|         print FH $line;
 | |
|     }
 | |
| 
 | |
|     #the dev is the last one, add the route at the end of the file
 | |
|     if ($readyflag == 1) {
 | |
|         print FH $route_conf;
 | |
|     }
 | |
| 
 | |
|     close(FH);
 | |
| }
 | |
| 
 | |
| sub deletePersistentRoute_Debian {
 | |
|     my $callback = shift;
 | |
|     my $net      = shift;
 | |
|     my $mask     = shift;
 | |
|     my $gw_ip    = shift;
 | |
|     my $gw       = shift;
 | |
|     my $ifname   = shift;
 | |
| 
 | |
|     my $host      = hostname();
 | |
|     my $conf_file = "/etc/network/interfaces.d/$ifname";
 | |
|     my $match     = "";
 | |
|     my $modflag   = 0;
 | |
| 
 | |
|     preParse_Debian();
 | |
| 
 | |
|     #ipv6
 | |
|     if ($net =~ /:/) {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "::") {
 | |
|             $match = "$net/$mask dev $ifname";
 | |
|         } else {
 | |
|             $match = "$net/$mask gw $gw_ip";
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         if ($gw_ip eq "" || $gw_ip eq "0.0.0.0") {
 | |
|             $match = "net $net netmask $mask dev $ifname";
 | |
|         } else {
 | |
|             $match = "net $net netmask $mask gw $gw_ip";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     open(FH, "<", $conf_file);
 | |
|     my @lines = <FH>;
 | |
|     close(FH);
 | |
| 
 | |
|     open(FH, ">", $conf_file);
 | |
|     foreach my $line (@lines) {
 | |
| 
 | |
|         #match the route config, jump to next line
 | |
|         if ($line =~ /$match/) {
 | |
|             $modflag = 1;
 | |
|         }
 | |
|         else {
 | |
|             print FH $line;
 | |
|         }
 | |
|     }
 | |
|     close(FH);
 | |
| 
 | |
|     my $rsp = {};
 | |
|     if ($modflag) {
 | |
|         $rsp->{data}->[0] = "$host: Removed persistent route \"$match\" from $conf_file.";
 | |
|     }
 | |
|     else {
 | |
|         $rsp->{data}->[0] = "$host: Persistent route \"$match\" does not exist in $conf_file.";
 | |
|     }
 | |
| 
 | |
|     $callback->($rsp);
 | |
| 
 | |
| }
 | |
| 
 | |
| sub preParse_Debian {
 | |
|     my $configfile;
 | |
| 
 | |
|     open(FH, "<", "/etc/network/interfaces");
 | |
|     my @lines = <FH>;
 | |
|     close(FH);
 | |
| 
 | |
|     if ($lines[0] =~ /XCAT_CONFIG/i) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     unless (-e "/etc/network/interfaces.bak") {
 | |
|         copy("/etc/network/interfaces", "/etc/network/interfaces.bak");
 | |
|     }
 | |
| 
 | |
|     unless (-d "/etc/network/interfaces.d") {
 | |
|         mkpath("/etc/network/interfaces.d");
 | |
|     }
 | |
| 
 | |
|     open(FH, ">", "/etc/network/interfaces");
 | |
|     print FH "#XCAT_CONFIG\n";
 | |
|     print FH "source /etc/network/interfaces.d/* \n";
 | |
|     close(FH);
 | |
| 
 | |
|     foreach my $line (@lines) {
 | |
|         if ($line =~ /^\s*$/) {
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         if ($line =~ /^#.*/) {
 | |
|             next;
 | |
|         }
 | |
| 
 | |
|         my @attr = split /\s+/, $line;
 | |
|         if ($attr[0] =~ /auto|allow-hotplug/) {
 | |
|             my $i = 1;
 | |
|             while ($i < @attr) {
 | |
|                 open(SFH, ">", "/etc/network/interfaces.d/$attr[$i]");
 | |
|                 print SFH "$attr[0] $attr[$i]\n";
 | |
|                 close(SFH);
 | |
|                 print FH "source /etc/network/interfaces.d/$attr[$i] \n";
 | |
|                 $i = $i + 1;
 | |
|             }
 | |
|         }
 | |
|         elsif ($attr[0] =~ /mapping|iface/) {
 | |
|             $configfile = "/etc/network/interfaces.d/$attr[1]";
 | |
|             open(SFH, ">>", $configfile);
 | |
|             unless (-e $configfile) {
 | |
|                 print SFH "auto $attr[1] \n";
 | |
|             }
 | |
|             print SFH $line;
 | |
|             close(SFH);
 | |
|         }
 | |
|         else {
 | |
|             open(SFH, ">>", $configfile);
 | |
|             print SFH $line;
 | |
|             close(SFH);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 |