diff --git a/perl-xCAT/xCAT/ProfiledNodeUtils.pm b/perl-xCAT/xCAT/ProfiledNodeUtils.pm index 60b532c75..aa6190970 100644 --- a/perl-xCAT/xCAT/ProfiledNodeUtils.pm +++ b/perl-xCAT/xCAT/ProfiledNodeUtils.pm @@ -827,6 +827,8 @@ sub parse_nodeinfo_file my @lines = split /\n/, $filedata; my $obj_found = 0; + my $attr_found = 0; + my $null_obj; my ($objname, $append); foreach my $line (@lines){ @@ -835,6 +837,8 @@ sub parse_nodeinfo_file # The line ends with : if (grep(/:\s*$/, $line)){ + $attr_found = 0; + $null_obj = $line; ($objname, $append) = split(/:/, $line); $objname =~ s/^\s*//; # Remove any leading whitespace $objname =~ s/\s*$//; # Remove any trailing whitespace @@ -852,6 +856,7 @@ sub parse_nodeinfo_file if (! $obj_found){ return 0, "No node defined before line \'$line\'"; } + $attr_found = 1; my $attr = $1; my $val = $2; @@ -875,6 +880,81 @@ sub parse_nodeinfo_file return 0, "Invalid Line \'$line\' found"; } } + + # Defined object has no attributes + if (! $attr_found){ + return 0, "Invalid Line \'$null_obj\' found"; + } + return 1, ""; } +#------------------------------------------------------------------------------- +=head3 check_nicips + Description: Check if the nicips defined in MAC file is correct + format + Arguments: $installnic: the installnic defined in networkprofile + $netprofileattrsref: the attributes of all nics in networkprofile + $freeipshash: the hash of networks' staticrange + $nicips: the string of nicips defined in MAC file + Returns: ($retcode, $output, $errmsg). + $retcode = 1. Parse failed, there are some errors in nicips string. Detailed errors will be set in $errmsg. + $retcode = 0. Parse success, the format of nicips is OK.. + +=cut +#------------------------------------------------------------------------------- +sub check_nicips{ + my $class = shift; + my $installnic = shift; + my $netprofileattrsref = shift; + my $freeipshash = shift; + my $othernics = shift; + + my $errmsg = ""; + my %nics_hash = (); + my %netprofileattr = %$netprofileattrsref; + + foreach my $nic_ips (split(/,/, $othernics)) { + my @nic_and_ips = (); + my $nic = ""; + my $nic_ip = ""; + if($nic_ips =~ /!/ and $nic_ips !~ /!$/) { + @nic_and_ips = split(/!/, $nic_ips); + my $len = @nic_and_ips; + $nic = $nic_and_ips[0]; + $nic_ip = $nic_and_ips[1]; + + if (exists $nics_hash{$nic} or $len ne 2) { + $errmsg = "The specified nicips is incorrect. It must be formatted correctly, in the form: !,!,..."; + return (1, "", $errmsg); + } + + # Check whether other interfaces contain provision nic + if ($nic eq $installnic) { + $errmsg = "The specified nicips cannot contain NICs used for provisioning."; + return (1, "", $errmsg); + } + + # Check whether this interface is defined in networkprofile + unless (exists $netprofileattr{$nic}){ + $errmsg = "The specified nicips contains NICs that are not defined in the network profile."; + return (1, "", $errmsg); + } + + # Check whether specified IP is in each network's static range + my $nicnetwork = $netprofileattr{$nic}{'network'}; + my $freeipsref = $freeipshash->{$nicnetwork}; + unless (grep{ $_ eq $nic_ip} @$freeipsref){ + $errmsg = "Specified IP address $nic_ip not in static range of network $netprofileattr{$nic}{'network'}"; + return (1, "", $errmsg); + } + }else { + $errmsg = "The specified nicips is incorrect. It must be formatted correctly, in the form: !,!,..."; + return (1, "", $errmsg); + } + $nics_hash{$nic} = $nic_ip; + } + + return (0, \%nics_hash, ""); +} + diff --git a/xCAT-client/pods/man1/nodeimport.1.pod b/xCAT-client/pods/man1/nodeimport.1.pod index ab4255617..4703b1d1c 100644 --- a/xCAT-client/pods/man1/nodeimport.1.pod +++ b/xCAT-client/pods/man1/nodeimport.1.pod @@ -134,6 +134,10 @@ B> This is an optional item. Description: Specify the IP address used for provisioning a node, where is in the form xxx.xxx.xxx.xxx. If this item is not included, the IP address used to provision the node is generated automatically according to the Network Profile used by the node. +B> This is an optional item. + +Description: Lists the IP address for each network interface configuration (NIC) used by the node, excluding the provisioning network, where is in the form !,!,.... For example, if you have 2 network interfaces configured, the nicips attribute should list both network interfaces: nicips=eth1!10.10.10.11,bmc!192.168.10.3. If the nicips attribute is not specified, the IP addresses are generated automatically according to the network profile. + B> This is an optional item. Description: node location info. Specify the rack name which this node will be placed into. If not specify this item, there will be no node location info set for this node. this item must be specified together with height + unit. diff --git a/xCAT-server/lib/xcat/plugins/profilednodes.pm b/xCAT-server/lib/xcat/plugins/profilednodes.pm index 5c89f59cf..ff650f532 100644 --- a/xCAT-server/lib/xcat/plugins/profilednodes.pm +++ b/xCAT-server/lib/xcat/plugins/profilednodes.pm @@ -38,6 +38,7 @@ my %allracks; my %allchassis; # The array of all chassis which is special CMM my %allcmmchassis; +my %allothernics; # Define parameters for xcat requests. my $request; @@ -1501,13 +1502,31 @@ sub gen_new_hostinfo_string{ if ($netname){ $freeipsref = $freeipshash{$netname}; } + + # Not generate IP if exists other nics + if (exists $allothernics{$item}->{$_}) { + my $avaiableip = $allothernics{$item}->{$_}; + if (exists $allips{$avaiableip}){ + return 0, "The specified nicips IP address $avaiableip is already in use."; + }else{ + $ipshash{$_} = $avaiableip; + $allips{$avaiableip} = 0; + next; + } + } + + # If generated IP is already used, re-generate free ip my $nextip = shift @$freeipsref; + while (exists $allips{$nextip}){ + $nextip = shift @$freeipsref; + } + if (!$nextip){ return 0, "There are no more IP addresses available in the static network range of network $netname for interface $_"; }else{ $ipshash{$_} = $nextip; $allips{$nextip} = 0; - } + } } # Generate IP address if no IP specified. if (! exists $hostinfo_dict{$item}{"ip"}) { @@ -1659,9 +1678,28 @@ sub validate_node_entries{ $rank = $args_dict{'rank'}; } - my $provnet = xCAT::ProfiledNodeUtils->get_netprofile_provisionnet($args_dict{networkprofile}); - my @allknownips = keys %allips; - my $freeprovipsref = xCAT::ProfiledNodeUtils->get_allocable_staticips_innet($provnet); + # Get all nics attribute in networkprofile + my $networkprofile = $args_dict{networkprofile}; + my $netprofileattrsref = xCAT::ProfiledNodeUtils->get_nodes_nic_attrs([$networkprofile])->{$networkprofile}; + my %netprofileattr = %$netprofileattrsref; + + # Get install nic and provision network + my $noderestab = xCAT::Table->new('noderes'); + my $nodereshashref = $noderestab->getNodeAttribs($networkprofile, ['installnic']); + my %nodereshash = %$nodereshashref; + my $installnic = $nodereshash{'installnic'}; + my $provnet = $netprofileattr{$installnic}{"network"}; + $noderestab->close(); + + # Get all nics' static range + my %freeipshash = (); + foreach (keys %netprofileattr){ + my $netname = $netprofileattr{$_}{'network'}; + if($netname and (! exists $freeipshash{$netname})) { + $freeipshash{$netname} = xCAT::ProfiledNodeUtils->get_allocable_staticips_innet($netname); + } + } + my $freeprovipsref = $freeipshash{$provnet}; # get all chassis's rack info. my @chassislist = keys %allchassis; @@ -1675,7 +1713,19 @@ sub validate_node_entries{ $errmsg .= "Specified IP address $::profiledNodeAttrs{$attr}->{'ip'} not in static range of provision network $provnet"; } } - + + # Check nicips + my $nic_and_ips; + if ($::profiledNodeAttrs{$attr}->{'nicips'}) { + my ($ret, $othernicsref, $outputmsg) = xCAT::ProfiledNodeUtils->check_nicips($installnic, $netprofileattrsref, \%freeipshash,$::profiledNodeAttrs{$attr}->{'nicips'}); + if ($ret) { + $errmsg .= $outputmsg; + }else { + $nic_and_ips = $othernicsref; + } + delete $::profiledNodeAttrs{$attr}->{'nicips'}; + } + # Set rack info for blades too. if ($::profiledNodeAttrs{$attr}->{'chassis'}){ $::profiledNodeAttrs{$attr}->{'rack'} = $chassisrackref->{$::profiledNodeAttrs{$attr}->{'chassis'}}; @@ -1688,7 +1738,8 @@ sub validate_node_entries{ } next; } - + + my $definedhostname = ""; # We need generate hostnames for this entry. if ($attr =~ /^TMPHOSTS/) { @@ -1736,11 +1787,18 @@ sub validate_node_entries{ $nexthostname = shift @$hostnamelistref; } + $definedhostname = $nexthostname; $hostinfo_dict{$nexthostname} = $::profiledNodeAttrs{$attr}; } else{ + $definedhostname = $attr; $hostinfo_dict{$attr} = $::profiledNodeAttrs{$attr}; } + + if ($nic_and_ips){ + $allothernics{$definedhostname} = $nic_and_ips; + } } + return (\%hostinfo_dict, \@invalid_records); } @@ -1859,6 +1917,8 @@ sub validate_node_entry{ if (!($node_entry{$_} =~ /^[1-9]\d*$/)){ $errmsg .= "Specified slotid $node_entry{$_} is invalid"; } + }elsif ($_ eq "nicips"){ + # Support Multi-Nic }else{ $errmsg .= "Invalid attribute $_ specified\n"; }