mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	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:
		@@ -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, "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user