Enhance makenetworks to support AIX and display option.
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@3985 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -18,8 +18,8 @@ | ||||
| #	  /home/groups/x/xc/xcat/htdocs/aix/devel/core-snap | ||||
| #	- nothing is added to the release download area | ||||
| # | ||||
| # scp *.rpm nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/devel/core-snap | ||||
| #scp core-aix-snap.tar.gz nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/devel  | ||||
| # scp *.rpm nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/devel/xcat-core | ||||
| #scp core-aix-2.3.tar.gz nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/devel  | ||||
| #scp *.rpm nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/2.2/core-snap | ||||
| #scp core-aix-snap.tar.gz nott,xcat@web.sourceforge.net:/home/groups/x/xc/xcat/htdocs/aix/2.2 | ||||
|  | ||||
|   | ||||
| @@ -1,24 +1,55 @@ | ||||
| =head1 NAME | ||||
|  | ||||
| B<makenetworks> - populates the xCAT networks table, using network information from the local system | ||||
| B<makenetworks> - Gather cluster network information and add it to the xCAT database. | ||||
|  | ||||
| =head1 SYNOPSIS | ||||
|  | ||||
| B<makenetworks> | ||||
| I<makenetworks [-h|--help ]> | ||||
|  | ||||
| I<makenetworks [-v| --version]> | ||||
|  | ||||
| I<makenetworks [-V|--verbose] [-d|--display]> | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| The B<makenetworks> command is run by xCAT automatically, when xCAT is installed on the management node. | ||||
| It queries the network configuration of the management node and uses that information to populate the | ||||
| networks table in the xCAT database.  After that, you may want to update the networks table manually to, | ||||
| for example, disable the public network entry and add networks that service nodes are on that the management | ||||
| node can't see directly. | ||||
| The B<makenetworks> command can be used to gather network information from an xCAT cluster environment and create corresponding network definitions in the xCAT database. | ||||
|  | ||||
| You normally do not need to run the B<makenetworks> command yourself.  But if you want to reset the networks | ||||
| table to its original state, remove all the entries from it (using tabedit), and then run B<makenetworks> | ||||
| again. | ||||
| Every network that will be used to install a cluster node must be defined in the xCAT database. | ||||
|  | ||||
| The default behavior is to gather network information from the managment node, and any configured xCAT service nodes, and automatically save this information in the xCAT database. | ||||
|  | ||||
| You can use the "-d" option to display the network information without writing it to the database. | ||||
|  | ||||
| You can also redirect the output to a file that can be used with the xCAT B<mkdef> command to define the networks. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| 	makenetworks -d > mynetstanzas | ||||
|  | ||||
| 	cat mynetstanzas | mkdef -z | ||||
|  | ||||
| This features allows you to verify and modify the network information before writing it to the database. | ||||
|  | ||||
| When the network information is gathered a default value is created for the "netname" attribute.  This is done to make it possible to use the mkdef, chdef, lsdef, and rmdef commands to manage this data. | ||||
|  | ||||
| The default naming convention is to use a hyphen separated "net" and "mask" value with the "." replace by "_". (ex. "8_124_47_64-255_255_255_0") | ||||
|  | ||||
| You can also modify the xCAT "networks" database table directly using the xCAT B<tabedit> command. | ||||
|  | ||||
|    	tabedit networks | ||||
|  | ||||
|  | ||||
| Note: The B<makenetworks> command is run automatically when xCAT is installed on a Linux management node. | ||||
|  | ||||
| =head1 OPTIONS | ||||
|  | ||||
| B<-d|--display>       Display the network definitions but do not write to the definitions to the xCAT database. The output will be in stanza file format and can be redirected to a stanza file that can be used with B<mkdef> or B<chdef> commands to create or modify the network definitions. | ||||
|  | ||||
| B<-h | --help>         Display usage message. | ||||
|  | ||||
| B<-v | --version>      Command Version. | ||||
|  | ||||
| B<-V |--verbose>       Verbose mode. | ||||
|  | ||||
| =head1 RETURN VALUE | ||||
|  | ||||
| @@ -26,8 +57,28 @@ again. | ||||
|  | ||||
| 1 An error has occurred. | ||||
|  | ||||
| =head1 EXAMPLES | ||||
|  | ||||
| 1.  Gather cluster network information and create xCAT network definitions. | ||||
|  | ||||
| 	makenetworks | ||||
|  | ||||
| 2.  Display cluster network information but do not write the network definitions to the xCAT database. | ||||
|  | ||||
| 	makenetworks -d | ||||
|  | ||||
| The output would be one or more stanzas of information similar to the following. The line that ends with a colon is the value of the "netname" attribute and is the name of the network object to use with the lsdef, mkdef, chdef and rmdef commands. | ||||
|  | ||||
| 9_114_37_0-255_255_255_0: | ||||
|     objtype=network | ||||
|     gateway=9.114.37.254 | ||||
|     mask=255.255.255.0 | ||||
|     net=9.114.37.0 | ||||
|  | ||||
| =head1 FILES | ||||
|  | ||||
| /opt/xcat/sbin/makenetworks | ||||
|  | ||||
| =head1 SEE ALSO | ||||
|  | ||||
| L<makedhcp(8)|makedhcp.8> | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ use Data::Dumper; | ||||
| use Sys::Syslog; | ||||
| use Socket; | ||||
| use xCAT::Utils; | ||||
| use Getopt::Long; | ||||
|  | ||||
| sub handled_commands | ||||
| { | ||||
| @@ -14,16 +15,52 @@ sub handled_commands | ||||
| sub preprocess_request | ||||
| { | ||||
|     my $req = shift; | ||||
|     my $cb  = shift; | ||||
|     if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } | ||||
|     my $callback  = shift; | ||||
| 	if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } | ||||
|     # exit if preprocessed | ||||
|     my @requests = ({%$req}); #first element is local instance | ||||
| 	$::args     = $req->{arg}; | ||||
|  | ||||
| 	if (defined(@{$::args})) { | ||||
|         @ARGV = @{$::args}; | ||||
|     }  | ||||
|  | ||||
| 	Getopt::Long::Configure("no_pass_through"); | ||||
|     if ( | ||||
|         !GetOptions( | ||||
|                     'help|h|?'    => \$::HELP, | ||||
| 					'display|d'	=> \$::DISPLAY, | ||||
| 					'mnonly|m'	=> \$::MNONLY, | ||||
| 					'verbose|V' => \$::VERBOSE, | ||||
|                     'version|v' => \$::VERSION, | ||||
|         ) | ||||
|       ) | ||||
|     { | ||||
|     #    return 1; | ||||
|     } | ||||
|  | ||||
| 	# Option -h for Help | ||||
|     if ($::HELP ) | ||||
|     { | ||||
|         &makenetworks_usage($callback); | ||||
|         return undef; | ||||
|     } | ||||
|  | ||||
| 	# Option -v for version - do we need this??? | ||||
|     if ($::VERSION) | ||||
|     { | ||||
|         my $rsp; | ||||
|         my $version=xCAT::Utils->Version(); | ||||
|         $rsp->{data}->[0] = "makenetworks - $version"; | ||||
|         xCAT::MsgUtils->message("I", $rsp, $callback); | ||||
|         return undef; | ||||
|     } | ||||
|  | ||||
|     my @sn = xCAT::Utils->getSNList(); | ||||
|     foreach my $s (@sn) | ||||
|     { | ||||
|         my $reqcopy = {%$req}; | ||||
|         $reqcopy->{'_xcatdest'} = $s; | ||||
|         $reqcopy->{_xcatpreprocessed}->[0] = 1; | ||||
|         push @requests, $reqcopy; | ||||
|     } | ||||
|     return \@requests; | ||||
| @@ -31,98 +68,262 @@ sub preprocess_request | ||||
|  | ||||
| sub process_request | ||||
| { | ||||
|     my $nettab = xCAT::Table->new('networks', -create => 1, -autocommit => 0); | ||||
|     my @rtable = split /\n/, `/bin/netstat -rn`; | ||||
|     open($rconf, "/etc/resolv.conf"); | ||||
|     my @nameservers; | ||||
|     if ($rconf) | ||||
| 	my $request  = shift; | ||||
|     my $callback = shift; | ||||
|  | ||||
| 	my $host = `hostname`; | ||||
| 	chomp $host; | ||||
|  | ||||
| 	$::args     = $request->{arg}; | ||||
|  | ||||
|     if (defined(@{$::args})) { | ||||
|         @ARGV = @{$::args}; | ||||
|     } | ||||
|  | ||||
|     Getopt::Long::Configure("no_pass_through"); | ||||
|     if ( | ||||
|         !GetOptions( | ||||
|                     'help|h|?'    => \$::HELP, | ||||
|                     'display|d' => \$::DISPLAY, | ||||
|                     'mnonly|m'  => \$::MNONLY, | ||||
|                     'verbose|V' => \$::VERBOSE, | ||||
|                     'version|v' => \$::VERSION, | ||||
|         ) | ||||
|       ) | ||||
|     { | ||||
|         my @rcont; | ||||
|         while (<$rconf>) | ||||
|         { | ||||
|             push @rcont, $_; | ||||
|         } | ||||
|         close($rconf); | ||||
|         foreach (grep /nameserver/, @rcont) | ||||
|         { | ||||
|             my $line = $_; | ||||
|             my @pair; | ||||
|             $line =~ s/#.*//; | ||||
|             @pair = split(/\s+/, $line); | ||||
|             push @nameservers, $pair[1]; | ||||
|         } | ||||
|     #    return 1; | ||||
|     } | ||||
|     splice @rtable, 0, 2; | ||||
|     foreach (@rtable) | ||||
|     { #should be the lines to think about, do something with U, and something else with UG | ||||
|         my $net; | ||||
|         my $mask; | ||||
|         my $mgtifname; | ||||
|         my $gw; | ||||
|         my @ent = split /\s+/, $_; | ||||
|         my $firstoctet = $ent[0]; | ||||
|         $firstoctet =~ s/^(\d+)\..*/$1/; | ||||
|         if ($ent[0] eq "169.254.0.0" or ($firstoctet >= 224 and $firstoctet <= 239) or $ent[0] eq "127.0.0.0") | ||||
|         { | ||||
|             next; | ||||
|         } | ||||
|         if ($ent[3] eq 'U') | ||||
|         { | ||||
|             $net       = $ent[0]; | ||||
|             $mask      = $ent[2]; | ||||
|             $mgtifname = $ent[7]; | ||||
|             $nettab->setAttribs({'net' => $net}, | ||||
|                                 {'mask' => $mask, 'mgtifname' => $mgtifname}); | ||||
|             my $tent = $nettab->getAttribs({'net' => $net}, 'nameservers'); | ||||
|             unless ($tent and $tent->{nameservers}) | ||||
|             { | ||||
|                 my $text = join ',', @nameservers; | ||||
|                 $nettab->setAttribs({'net' => $net}, {nameservers => $text}); | ||||
|             } | ||||
|             unless ($tent and $tent->{tftpserver}) | ||||
|             { | ||||
|                 my $netdev = $ent[7]; | ||||
|                 my @netlines = split /\n/, `/sbin/ip addr show dev $netdev`; | ||||
|                 foreach (grep /\s*inet\b/, @netlines) | ||||
|                 { | ||||
|                     my @row = split(/\s+/, $_); | ||||
|                     my $ipaddr = $row[2]; | ||||
|                     $ipaddr =~ s/\/.*//; | ||||
|                     my @maska = split(/\./, $mask); | ||||
|                     my @ipa   = split(/\./, $ipaddr); | ||||
|                     my @neta  = split(/\./, $net); | ||||
|                     my $isme  = 1; | ||||
|                     foreach (0 .. 3) | ||||
|                     { | ||||
|                         my $oct = (0 + $maska[$_]) & ($ipa[$_] + 0); | ||||
|                         unless ($oct == $neta[$_]) | ||||
|                         { | ||||
|                             $isme = 0; | ||||
|                             last; | ||||
|                         } | ||||
|                     } | ||||
|                     if ($isme) | ||||
|                     { | ||||
|                         $nettab->setAttribs({'net' => $net}, | ||||
|                                             {tftpserver => $ipaddr}); | ||||
|                         last; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             $nettab->commit; | ||||
|  | ||||
|             #Nothing much sane to do for the other fields at the moment? | ||||
|         } | ||||
|         elsif ($ent[3] eq 'UG') | ||||
|         { | ||||
| 	my $nettab = xCAT::Table->new('networks', -create => 1, -autocommit => 0); | ||||
|  | ||||
|             #TODO: networks through gateway. and how we might care.. | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| 	if (xCAT::Utils->isAIX()) { | ||||
|  | ||||
|             #TODO: anything to do with such entries? | ||||
|         } | ||||
|     } | ||||
| 		# get list of interfaces "ifconfig -l" | ||||
| 		my $ifgcmd = "ifconfig -l"; | ||||
| 		my @interfaces = split(/\s+/, xCAT::Utils->runcmd($ifgcmd, 0)); | ||||
| 		if ($::RUNCMD_RC != 0) { | ||||
| 			my $rsp; | ||||
| 			push @{$rsp->{data}}, "Could not run \'$ifgcmd\'.\n"; | ||||
| 			xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		# do each ethernet interface | ||||
| 		foreach my $i (@interfaces) { | ||||
|  | ||||
| 			if ($i =~ /^en/) { | ||||
| 				# "mktcpip -S en0" to get nm & gw | ||||
| 				my $mkcmd = "mktcpip -S $i"; | ||||
| 				my @netinfo = xCAT::Utils->runcmd($mkcmd, 0); | ||||
| 				if ($::RUNCMD_RC != 0) { | ||||
| 					my $rsp; | ||||
| 					push @{$rsp->{data}}, "Could not run \'$mkcmd\'.\n"; | ||||
| 					xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
| 					return 1; | ||||
| 				} | ||||
|  | ||||
| 				my $netmask; | ||||
| 				my $ipaddr; | ||||
| 				my @fields; | ||||
| 				my $gateway; | ||||
| 				foreach my $line (@netinfo) { | ||||
| 					next if ($line =~ /^\s*#/); | ||||
|  | ||||
| 					@fields = split(/:/, $line); | ||||
| 				} | ||||
| 				$ipaddr = $fields[1]; | ||||
| 				$netmask = $fields[2]; | ||||
| 				$gateway = $fields[6]; | ||||
|  | ||||
| 				# split interface IP | ||||
|                 my ($ip1, $ip2, $ip3, $ip4) = split('\.', $ipaddr); | ||||
|  | ||||
| 				# split mask | ||||
|                 my ($m1, $m2, $m3, $m4) = split('\.', $netmask); | ||||
|  | ||||
| 				# AND nm and ip to get net attribute | ||||
| 				my $n1 = ((int $ip1) & (int $m1)); | ||||
|                 my $n2 = ((int $ip2) & (int $m2)); | ||||
|                 my $n3 = ((int $ip3) & (int $m3)); | ||||
|                 my $n4 = ((int $ip4) & (int $m4)); | ||||
|  | ||||
| 				my $net = "$n1.$n2.$n3.$n4"; | ||||
|  | ||||
| 				# use convention for netname attr | ||||
| 				my $netn; | ||||
| 				my $maskn; | ||||
| 				($netn = $net) =~ s/\./\_/g; | ||||
| 				($maskn = $netmask) =~ s/\./\_/g; | ||||
| 				#  ( 1_2_3_4-255_255_255_192 - ugh!) | ||||
| 				my $netname = $netn . "-" . $maskn; | ||||
|  | ||||
| 				if ($::DISPLAY) { | ||||
| 					my $rsp; | ||||
| 					push @{$rsp->{data}}, "\n#From $host."; | ||||
|             		push @{$rsp->{data}}, "$netname:"; | ||||
| 					push @{$rsp->{data}}, "    objtype=network"; | ||||
| 					push @{$rsp->{data}}, "    net=$net"; | ||||
| 					push @{$rsp->{data}}, "    mask=$netmask"; | ||||
| 					push @{$rsp->{data}}, "    gateway=$gateway\n"; | ||||
|             		xCAT::MsgUtils->message("I", $rsp, $callback); | ||||
| 				} else { | ||||
| 					# add new network def  | ||||
| 					$nettab->setAttribs({'net' => $net}, {'mask' => $mask}, {'netname' => $netname}, {'gateway' => $gateway}); | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	} else { | ||||
|  | ||||
| 		# For Linux systems | ||||
|     	my @rtable = split /\n/, `/bin/netstat -rn`; | ||||
|     	open($rconf, "/etc/resolv.conf"); | ||||
|     	my @nameservers; | ||||
|     	if ($rconf) | ||||
|     	{ | ||||
|         	my @rcont; | ||||
|         	while (<$rconf>) | ||||
|         	{ | ||||
|             	push @rcont, $_; | ||||
|         	} | ||||
|         	close($rconf); | ||||
|         	foreach (grep /nameserver/, @rcont) | ||||
|         	{ | ||||
|             	my $line = $_; | ||||
|             	my @pair; | ||||
|             	$line =~ s/#.*//; | ||||
|             	@pair = split(/\s+/, $line); | ||||
|             	push @nameservers, $pair[1]; | ||||
|         	} | ||||
|     	} | ||||
|     	splice @rtable, 0, 2; | ||||
|     	foreach (@rtable) | ||||
|     	{ #should be the lines to think about, do something with U, and something else with UG | ||||
|  | ||||
| 			my $rsp; | ||||
|         	my $net; | ||||
|         	my $mask; | ||||
|         	my $mgtifname; | ||||
|         	my $gw; | ||||
|         	my @ent = split /\s+/, $_; | ||||
|         	my $firstoctet = $ent[0]; | ||||
|         	$firstoctet =~ s/^(\d+)\..*/$1/; | ||||
|  | ||||
|         	if ($ent[0] eq "169.254.0.0" or ($firstoctet >= 224 and $firstoctet <= 239) or $ent[0] eq "127.0.0.0") | ||||
|         	{ | ||||
|             	next; | ||||
|         	} | ||||
|         	if ($ent[3] eq 'U') | ||||
|         	{ | ||||
|             	$net       = $ent[0]; | ||||
|             	$mask      = $ent[2]; | ||||
| 				$mgtifname = $ent[7]; | ||||
|  | ||||
| 				# use convention for netname attr | ||||
|                 my $netn; | ||||
|                 my $maskn; | ||||
|                 ($netn = $net) =~ s/\./\_/g; | ||||
|                 ($maskn = $mask) =~ s/\./\_/g; | ||||
|                 #  ( 1_2_3_4-255_255_255_192 - ugh!) | ||||
|                 my $netname = $netn . "-" . $maskn; | ||||
|  | ||||
| 				if ($::DISPLAY) { | ||||
| 					push @{$rsp->{data}}, "\n#From $host."; | ||||
| 					push @{$rsp->{data}}, "$netname:"; | ||||
| 					push @{$rsp->{data}}, "    objtype=network"; | ||||
|                     push @{$rsp->{data}}, "    net=$net"; | ||||
|                     push @{$rsp->{data}}, "    mask=$mask"; | ||||
|                     push @{$rsp->{data}}, "    mgtifname=$mgtifname"; | ||||
| 				} else { | ||||
|             		$nettab->setAttribs({'net' => $net}, {'mask' => $mask, 'mgtifname' => $mgtifname}, {'netname' => $netname}); | ||||
| 				} | ||||
|  | ||||
|             	my $tent = $nettab->getAttribs({'net' => $net}, 'nameservers'); | ||||
|             	unless ($tent and $tent->{nameservers}) | ||||
|             	{ | ||||
|                 	my $text = join ',', @nameservers; | ||||
| 					if ($::DISPLAY) { | ||||
|                     	push @{$rsp->{data}}, "    nameservers=$text"; | ||||
| 					} else { | ||||
|                 		$nettab->setAttribs({'net' => $net}, {nameservers => $text}); | ||||
| 					} | ||||
|             	} | ||||
|             	unless ($tent and $tent->{tftpserver}) | ||||
|             	{ | ||||
|                 	my $netdev = $ent[7]; | ||||
|                 	my @netlines = split /\n/, `/sbin/ip addr show dev $netdev`; | ||||
|                 	foreach (grep /\s*inet\b/, @netlines) | ||||
|                 	{ | ||||
|                     	my @row = split(/\s+/, $_); | ||||
|                     	my $ipaddr = $row[2]; | ||||
|                     	$ipaddr =~ s/\/.*//; | ||||
|                     	my @maska = split(/\./, $mask); | ||||
|                     	my @ipa   = split(/\./, $ipaddr); | ||||
|                     	my @neta  = split(/\./, $net); | ||||
|                     	my $isme  = 1; | ||||
|                     	foreach (0 .. 3) | ||||
|                     	{ | ||||
|                         	my $oct = (0 + $maska[$_]) & ($ipa[$_] + 0); | ||||
|                         	unless ($oct == $neta[$_]) | ||||
|                         	{ | ||||
|                             	$isme = 0; | ||||
|                             	last; | ||||
|                         	} | ||||
|                     	} | ||||
|                     	if ($isme) | ||||
|                     	{ | ||||
| 							if ($::DISPLAY) { | ||||
|                         		push @{$rsp->{data}}, "    tftpserver=$ipaddr"; | ||||
|                     		} else { | ||||
|                         		$nettab->setAttribs({'net' => $net}, {tftpserver => $ipaddr}); | ||||
| 							} | ||||
|                         	last; | ||||
|                     	} | ||||
|                 	} | ||||
|             	} | ||||
|  | ||||
|             	#Nothing much sane to do for the other fields at the moment? | ||||
|         	} | ||||
|         	elsif ($ent[3] eq 'UG') | ||||
|         	{ | ||||
|  | ||||
|             	#TODO: networks through gateway. and how we might care.. | ||||
|         	} | ||||
|         	else | ||||
|         	{ | ||||
|  | ||||
|             	#TODO: anything to do with such entries? | ||||
|         	} | ||||
| 			 | ||||
| 			if ($::DISPLAY) { | ||||
| 				xCAT::MsgUtils->message("I", $rsp, $callback); | ||||
| 			} | ||||
|     	} | ||||
| 	} | ||||
|  | ||||
| 	$nettab->commit; | ||||
| } | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| =head3  makenetworks_usage | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #----------------------------------------------------------------------------- | ||||
|  | ||||
| sub makenetworks_usage | ||||
| { | ||||
| 	my $callback = shift; | ||||
|  | ||||
|     my $rsp; | ||||
| 	push @{$rsp->{data}}, "\nUsage: makenetworks - Gather cluster network information and add it to the xCAT database.\n"; | ||||
| 	push @{$rsp->{data}}, "  makenetworks [-h|--help ]\n"; | ||||
| 	push @{$rsp->{data}}, "  makenetworks [-v|--version]\n"; | ||||
| 	push @{$rsp->{data}}, "  makenetworks [-V|--verbose] [-d|--display]\n"; | ||||
|     xCAT::MsgUtils->message("I", $rsp, $callback); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| 1; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user