enhance node info parsing mechanism: add more checks before import

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14792 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
leiaibj 2013-01-08 04:47:39 +00:00
parent 344b3ca89b
commit c74580a8a1
2 changed files with 106 additions and 28 deletions

View File

@ -763,3 +763,78 @@ sub get_nodes_cmm
return \%returncmm
}
#-------------------------------------------------------------------------------
=head3 parse_nodeinfo_file
Description: Parse node info file content. And put node info into 2 global
vals: @::profiledNodeObjNames and %::profiledNodeAttrs.
@::profiledNodeObjNames: recording all nodes' names.
%::profiledNodeAttrs: recording all nodes' attributes.
Arguments: $filedata: node info file content string.
Returns: ($retcode, $msgstr).
$retcode = 1. Parse success, the format of this file is OK.
$retcode = 0. Parse failed, there are some errors in this file.
Detailed errors will be set in $msgstr.
=cut
#-------------------------------------------------------------------------------
sub parse_nodeinfo_file
{
my($class, $filedata) = @_;
@::profiledNodeObjNames = ();
%::profiledNodeAttrs = ();
my @lines = split /\n/, $filedata;
my $obj_found = 0;
my ($objname, $append);
foreach my $line (@lines){
# skip blank and comment lines
next if ($line =~ /^\s*$/ || $line =~ /^\s*#/);
# The line ends with :
if (grep(/:\s*$/, $line)){
($objname, $append) = split(/:/, $line);
$objname =~ s/^\s*//; # Remove any leading whitespace
$objname =~ s/\s*$//; # Remove any trailing whitespace
# OK we've found one object.
if ($objname){
$obj_found = 1;
push(@::profiledNodeObjNames, $objname);
}else{
return 0, "No node name defined in line \'$line\'";
}
} # The line has =
elsif (($line =~ /^\s*(.*?)\s*=\s*(.*)\s*/)){
# No one object clarified yet. So this file format is illegal.
if (! $obj_found){
return 0, "No node defined before line \'$line\'";
}
my $attr = $1;
my $val = $2;
$attr =~ s/^\s*//; # Remove any leading whitespace
$attr =~ s/\s*$//; # Remove any trailing whitespace
$val =~ s/^\s*//;
$val =~ s/\s*$//;
# remove spaces and quotes
$val =~ s/^\s*"\s*//;
$val =~ s/\s*"\s*$//;
if($attr && $val){
$::profiledNodeAttrs{$objname}{$attr} = $val;
}else{
return 0, "Line \'$line\' does not contain a valid key and value";
}
} #invalid line.
else{
return 0, "Invalid Line \'$line\' found";
}
}
return 1, "";
}

View File

@ -15,7 +15,6 @@ use warnings;
use Getopt::Long qw(:config no_ignore_case);
use Data::Dumper;
require xCAT::Table;
require xCAT::DBobjUtils;
require xCAT::Utils;
require xCAT::TableUtils;
require xCAT::NetworkUtils;
@ -24,9 +23,9 @@ require xCAT::ProfiledNodeUtils;
# Globals.
# These 2 global variables are for storing the parse result of hostinfo file.
# These 2 global varialbes are set in lib xCAT::DBobjUtils->readFileInput.
#%::FILEATTRS;
#@::fileobjnames;
# These 2 global varialbes are set in lib xCAT::ProfiledNodeUtils->parse_nodeinfo_file.
#%::profiledNodeAttrs;
#@::profiledNodeObjNames;
# All database records.
my %allhostnames;
@ -347,10 +346,16 @@ Usage:
setrsp_errormsg($retstr_read);
return;
}
my ($parse_ret, $parse_str) = xCAT::ProfiledNodeUtils->parse_nodeinfo_file($retstr_read);
if (! $parse_ret){
setrsp_progress("Failed to validate node information file.");
setrsp_errormsg($parse_str);
return;
}
# Parse and validate the hostinfo string. The real hostnames will be generated here.
xCAT::MsgUtils->message('S', "Parsing hostinfo string and validate it.");
my ($hostinfo_dict_ref, $invalid_records_ref) = parse_hosts_string($retstr_read);
my ($hostinfo_dict_ref, $invalid_records_ref) = validate_node_entries();
my %hostinfo_dict = %$hostinfo_dict_ref;
my @invalid_records = @$invalid_records_ref;
if (@invalid_records){
@ -1133,7 +1138,9 @@ sub findme{
}
}
my ($hostinfo_dict_ref, $invalid_records_ref) = parse_hosts_string($raw_hostinfo_str);
xCAT::ProfiledNodeUtils->parse_nodeinfo_file($raw_hostinfo_str);
my ($hostinfo_dict_ref, $invalid_records_ref) = validate_node_entries();
my %hostinfo_dict = %$hostinfo_dict_ref;
# Create the real hostinfo string in stanza file format.
xCAT::MsgUtils->message('S', "Profiled nodes discover: Generating new hostinfo string.\n");
@ -1374,18 +1381,17 @@ sub read_and_generate_hostnames{
#-------------------------------------------------------
=head3 parse_hosts_string
=head3 validate_node_entries
Description : Parse the hostinfo string and validate it.
Arguments : filecontent - The content of hostinfo file.
Description : Validate the node entrie and generate proper attributes.
Arguments : N/A
Returns : (hostinfo_dict, invalid_records)
hostinfo_dict - Reference of hostinfo dict. Key are hostnames and values is an attributes dict.
invalid_records - Reference of invalid records list.
=cut
#-------------------------------------------------------
sub parse_hosts_string{
my $filecontent = shift;
sub validate_node_entries{
my %hostinfo_dict;
my @invalid_records;
@ -1394,14 +1400,11 @@ sub parse_hosts_string{
my $nameformattype = xCAT::ProfiledNodeUtils->get_hostname_format_type($nameformat);
my %freehostnames;
# Parse hostinfo file string.
xCAT::DBobjUtils->readFileInput($filecontent);
# Record duplicated items.
# We should go through list @::fileobjnames first as %::FILEATTRS is just a hash,
# We should go through list @::profiledNodeObjNames first as %::profiledNodeAttrs is just a hash,
# it not tells whether there are some duplicated hostnames in the hostinfo string.
my %hostnamedict;
foreach my $hostname (@::fileobjnames){
foreach my $hostname (@::profiledNodeObjNames){
if (exists $hostnamedict{$hostname}){
push @invalid_records, [$hostname, "Duplicated hostname defined"];
} else{
@ -1422,18 +1425,18 @@ sub parse_hosts_string{
my @chassislist = keys %allchassis;
my $chassisrackref = xCAT::ProfiledNodeUtils->get_racks_for_chassises(\@chassislist);
foreach my $attr (keys %::FILEATTRS){
my $errmsg = validate_node_entry($attr, $::FILEATTRS{$attr});
foreach my $attr (keys %::profiledNodeAttrs){
my $errmsg = validate_node_entry($attr, $::profiledNodeAttrs{$attr});
# Check whether specified IP is in our prov network, static range.
if ($::FILEATTRS{$attr}->{'ip'}){
unless (grep{ $_ eq $::FILEATTRS{$attr}->{'ip'}} @$freeprovipsref){
$errmsg .= "Specified IP address $::FILEATTRS{$attr}->{'ip'} not in static range of provision network $provnet";
if ($::profiledNodeAttrs{$attr}->{'ip'}){
unless (grep{ $_ eq $::profiledNodeAttrs{$attr}->{'ip'}} @$freeprovipsref){
$errmsg .= "Specified IP address $::profiledNodeAttrs{$attr}->{'ip'} not in static range of provision network $provnet";
}
}
# Set rack info for blades too.
if ($::FILEATTRS{$attr}->{'chassis'}){
$::FILEATTRS{$attr}->{'rack'} = $chassisrackref->{$::FILEATTRS{$attr}->{'chassis'}};
if ($::profiledNodeAttrs{$attr}->{'chassis'}){
$::profiledNodeAttrs{$attr}->{'rack'} = $chassisrackref->{$::profiledNodeAttrs{$attr}->{'chassis'}};
}
if ($errmsg) {
if ($attr =~ /^TMPHOSTS/){
@ -1451,13 +1454,13 @@ sub parse_hosts_string{
my $numricformat;
# Need convert hostname format into numric format first.
if ($nameformattype eq "rack"){
if (! exists $::FILEATTRS{$attr}{"rack"}){
if (! exists $::profiledNodeAttrs{$attr}{"rack"}){
push @invalid_records, ["__hostname__", "Rack information is not specified. You must enter the required rack information."];
next;
}
$numricformat = xCAT::ProfiledNodeUtils->rackformat_to_numricformat($nameformat, $::FILEATTRS{$attr}{"rack"});
$numricformat = xCAT::ProfiledNodeUtils->rackformat_to_numricformat($nameformat, $::profiledNodeAttrs{$attr}{"rack"});
if(! $numricformat){
push @invalid_records, ["__hostname__", "The rack number of rack $::FILEATTRS{$attr}{'rack'} does not match hostname format $nameformat"];
push @invalid_records, ["__hostname__", "The rack number of rack $::profiledNodeAttrs{$attr}{'rack'} does not match hostname format $nameformat"];
}
} else{
# pure numric hostname format
@ -1491,9 +1494,9 @@ sub parse_hosts_string{
$nexthostname = shift @$hostnamelistref;
}
$hostinfo_dict{$nexthostname} = $::FILEATTRS{$attr};
$hostinfo_dict{$nexthostname} = $::profiledNodeAttrs{$attr};
} else{
$hostinfo_dict{$attr} = $::FILEATTRS{$attr};
$hostinfo_dict{$attr} = $::profiledNodeAttrs{$attr};
}
}
return (\%hostinfo_dict, \@invalid_records);