From 546bf507ab64c94ff9f372744bf82f91a84d6afb Mon Sep 17 00:00:00 2001 From: daniceexi Date: Wed, 22 May 2013 14:58:46 +0000 Subject: [PATCH] support the predefined bmc is set in the hosts.otherinterfaces git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@16393 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/xcat/plugins/seqdiscovery.pm | 353 +++++++++++++------ 1 file changed, 248 insertions(+), 105 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/seqdiscovery.pm b/xCAT-server/lib/xcat/plugins/seqdiscovery.pm index 9c96b3a3b..06e8d7857 100644 --- a/xCAT-server/lib/xcat/plugins/seqdiscovery.pm +++ b/xCAT-server/lib/xcat/plugins/seqdiscovery.pm @@ -41,6 +41,9 @@ sub handled_commands { } } +=head3 findme + Handle the request form node to map and define the request to a node +=cut sub findme { my $request = shift; my $callback = shift; @@ -82,6 +85,7 @@ sub findme { else{ $arptable = `/sbin/arp -n`; } + my @arpents = split /\n/,$arptable; foreach (@arpents) { if (m/^($ip)\s+\S+\s+(\S+)\s/) { @@ -127,20 +131,23 @@ sub findme { if ($node) { my $skiphostip; my $skipbmcip; - my @newhosts = ($node); # check the host ip and bmc my $hosttab = xCAT::Table->new('hosts'); unless ($hosttab) { xCAT::MsgUtils->message("S", "Discovery Error: Could not open table: hosts."); } - my $hostip = $hosttab->getNodeAttribs($node, ['ip']); - if ($hostip->{'ip'}) { - $skiphostip = 1; + my $hostip = getpredefips([$node], "host"); + foreach (keys %$hostip) { + if ($hostip->{$_} eq "$node") { + $skiphostip = 1; + } } - my $bmcip = $hosttab->getNodeAttribs($node."-bmc", ['ip']); - if ($bmcip->{'ip'}) { - $skipbmcip = 1; + my $bmcip = getpredefips([$node], "bmc"); + foreach (keys %$bmcip) { + if ($bmcip->{$_} eq "$node-bmc") { + $skipbmcip = 1; + } } my $ipmitab = xCAT::Table->new('ipmi'); @@ -148,7 +155,7 @@ sub findme { xCAT::MsgUtils->message("S", "Discovery Error: Could not open table: ipmi."); } - # set the host ip and bmc if needed + # set the host ip if the node does not have unless ($skiphostip) { my $hostip = getfreeips($param{'hostiprange'}, \@allnodes, "host"); unless ($hostip) { @@ -159,8 +166,8 @@ sub findme { $hosttab->commit(); } + # set the bmc ip if the node does not have my $bmcname = $node."-bmc"; - push @newhosts, $bmcname; unless ($skipbmcip) { my $bmcip = getfreeips($param{'bmciprange'}, \@allnodes, "bmc"); unless ($bmcip) { @@ -169,11 +176,13 @@ sub findme { } $hosttab->setNodeAttribs($bmcname, {ip => $bmcip}); $hosttab->commit(); + + # set the bmc to the ipmi table + $ipmitab->setNodeAttribs($node, {bmc => $bmcname}); } - # set the bmc to the ipmi table - $ipmitab->setNodeAttribs($node, {bmc => $bmcname}); # update the host ip pair to /etc/hosts, it's necessary for discovered and makedhcp commands + my @newhosts = ($node, $node."-bmc"); if (@newhosts) { my $req; $req->{command}=['makehosts']; @@ -234,15 +243,16 @@ sub findme { } if (defined ($param{'groups'})) { $nltab->setNodeAttribs($node, {groups=>$param{'groups'}}); - if ($bmcname) { + unless ($skipbmcip) { $nltab->setNodeAttribs($bmcname, {groups=>$param{'groups'}.",bmc"}); } } else { + # just set the groups attribute when there was no groups value was set my $nlent = $nltab->getNodeAttribs($node,['groups']); if (!$nlent || !$nlent->{'groups'}) { $nltab->setNodeAttribs($node, {groups=>"all"}); } - if ($bmcname) { + unless ($skipbmcip) { $nlent = $nltab->getNodeAttribs($bmcname,['groups']); if (!$nlent || !$nlent->{'groups'}) { $nltab->setNodeAttribs($bmcname, {groups=>"all,bmc"}); @@ -250,6 +260,17 @@ sub findme { } } + # set the mgt for the node + my $hmtab = xCAT::Table->new('nodehm'); + unless ($hmtab) { + xCAT::MsgUtils->message("S", "Discovery Error: Could not open table: nodehm."); + } + my $hment = $hmtab->getNodeAttribs($node,['mgt']); + if (!$hment || !$hment->{'mgt'}) { + $hmtab->setNodeAttribs($node, {mgt=>"ipmi"}); + } + + # call the discovered command to update the discovery request to a node $request->{command}=['discovered']; $request->{noderange} = [$node]; $request->{discoverymethod} = ['sequential']; @@ -440,63 +461,58 @@ Usage: xCAT::MsgUtils->message("I", $rsp, $callback); if ($::VERBOSE) { # dispaly the free nodes - my $hoststb = xCAT::Table->new('hosts'); - if ($hoststb) { - my $prehostip = $hoststb->getNodesAttribs(\@freenodes, ['ip']); - my %prehostips; - foreach (keys %$prehostip) { - if (defined($prehostip->{$_}->[0]->{'ip'})) { - $prehostips{$prehostip->{$_}->[0]->{'ip'}} = 1; - } - } - my @freebmcs; - foreach (@freenodes) { - push @freebmcs, $_.'-bmc'; - } - my $prebmcip = $hoststb->getNodesAttribs(\@freebmcs, ['ip']); - my %prebmcips; - foreach (keys %$prebmcip) { - if (defined($prebmcip->{$_}->[0]->{'ip'})) { - $prebmcips{$prebmcip->{$_}->[0]->{'ip'}} = 1; - } - } - - my $vrsp; - push @{$vrsp->{data}}, "\n====================Free Nodes==================="; - push @{$vrsp->{data}}, sprintf("%-20s%-20s%-20s", "NODE", "HOST IP", "BMC IP"); - - my $index = 0; - foreach (@freenodes) { - my $hostip; - my $bmcip; - if (defined ($prehostip->{$_}->[0]) && $prehostip->{$_}->[0]->{'ip'}) { - $hostip = $prehostip->{$_}->[0]->{'ip'}; - } else { - while (($hostip = shift @freehostips)) { - if (!defined($prehostips{$hostip})) { last;} - } - unless ($hostip) { - $hostip = "--no free--"; - } - } - - if (defined ($prebmcip->{$_."-bmc"}->[0]) && $prebmcip->{$_."-bmc"}->[0]->{'ip'}) { - $bmcip = $prebmcip->{$_."-bmc"}->[0]->{'ip'}; - } else { - while (($bmcip = shift @freebmcips)) { - if (!defined($prebmcips{$bmcip})) { last;} - } - unless ($bmcip) { - $bmcip = "--no free--"; - } - } - - push @{$vrsp->{data}}, sprintf("%-20s%-20s%-20s", $_, $hostip, $bmcip); - $index++; - } - xCAT::MsgUtils->message("I", $vrsp, $callback); + # get predefined host ip + my %prehostips; + my $prehosts = getpredefips(\@freenodes, "host"); #pre{ip} = nodename + foreach (keys %$prehosts) { + $prehostips{$prehosts->{$_}} = $_; #pre{nodename} = ip } + + # get predefined bmc ip + my %prebmcips; + my $prebmcs = getpredefips(\@freenodes, "bmc"); #pre{ip} = bmcname + foreach (keys %$prebmcs) { + $prebmcips{$prebmcs->{$_}} = $_; #pre{bmcname} = ip + } + + my $vrsp; + push @{$vrsp->{data}}, "\n====================Free Nodes==================="; + push @{$vrsp->{data}}, sprintf("%-20s%-20s%-20s", "NODE", "HOST IP", "BMC IP"); + + my $index = 0; + foreach (@freenodes) { + my $hostip; + my $bmcip; + # if predefined, use it; otherwise pop out one from the free ip list + if (defined ($prehostips{$_})) { + $hostip = $prehostips{$_}; + } else { + while (($hostip = shift @freehostips)) { + if (!defined($prehosts->{$hostip})) { last;} + } + unless ($hostip) { + $hostip = "--no free--"; + } + } + + # if predefined, use it; otherwise pop out one from the free ip list + if (defined ($prebmcips{$_."-bmc"})) { + $bmcip = $prebmcips{$_."-bmc"}; + } else { + while (($bmcip = shift @freebmcips)) { + if (!defined($prebmcs->{$bmcip})) { last;} + } + unless ($bmcip) { + $bmcip = "--no free--"; + } + } + + push @{$vrsp->{data}}, sprintf("%-20s%-20s%-20s", $_, $hostip, $bmcip); + $index++; + } + xCAT::MsgUtils->message("I", $vrsp, $callback); + } } @@ -1075,6 +1091,7 @@ sub getfreenodes () { return; } + # if mac address has been set, the node is not free my $nlent = $nltb->getNodesAttribs(\@nodes,['groups']); my $macent = $mactb->getNodesAttribs(\@nodes,['mac']); foreach my $node (@nodes) { @@ -1100,65 +1117,156 @@ sub getfreenodes () { } } +=head3 getpredefips + Get the nodes which have ip predefined + arg1 - a refenrece to the array of nodes + arg2 - type: host, bmc + + return: hash {ip} = node +=cut +sub getpredefips { + my $freenode = shift; + my $type = shift; # type: host, bmc + + my $hoststb = xCAT::Table->new('hosts'); + unless ($hoststb) { + xCAT::MsgUtils->message("S", "Discovery Error: Could not open table: hosts."); + } + + my %predefips; # to have the ip which prefined to the nodes + if ($type eq "bmc") { + # Find the bmc ip which defined in the ipmi.bmc as an ip address instead of name as 'node-bmc' + my $ipmitab = xCAT::Table->new('ipmi'); + if ($ipmitab) { + my $ipmient = $ipmitab->getNodesAttribs($freenode, ['bmc']); + foreach (@$freenode) { + if (defined($ipmient->{$_}->[0]->{'bmc'}) && ($ipmient->{$_}->[0]->{'bmc'} =~ /\d+\.\d+\.\d+\.\d+/)) { + $predefips{$ipmient->{$_}->[0]->{'bmc'}} = $_."-bmc"; + } + } + } + + # get the node list of the bmc as 'node-bmc' format + my @freebmc; + foreach (@$freenode) { + push @freebmc, $_.'-bmc'; + } + + # get the predefined bmcs which ip has been set in the hosts.ip + my $freenodeent = $hoststb->getNodesAttribs(\@freebmc, ['ip']); + foreach (@freebmc) { + my $nodeip = xCAT::NetworkUtils->getipaddr($_); + if ($nodeip) { + $predefips{$nodeip} = $_; + } else { + if (defined($freenodeent->{$_}->[0]) && $freenodeent->{$_}->[0]->{'ip'}){ + $predefips{$freenodeent->{$_}->[0]->{'ip'}} = $_; + } + } + } + + # get the predefined bmcs which bmc has been set in the hosts.otherinterfaces + $freenodeent = $hoststb->getNodesAttribs($freenode, ['otherinterfaces']); + foreach (@$freenode) { + # for bmc node, search the hosts.otherinterface to see whether there's perdefined ip for bmc + my $bmcip = getbmcip_otherinterfaces($_, $freenodeent->{$_}->[0]->{'otherinterfaces'}); + if ($bmcip) { + $predefips{$bmcip} = $_."-bmc"; + } + } + } elsif ($type eq "host") { + # get the predefined node which ip has been set in the hosts.ip + my $freenodeent = $hoststb->getNodesAttribs($freenode, ['ip']); + + foreach (@$freenode) { + my $nodeip = xCAT::NetworkUtils->getipaddr($_); + if ($nodeip) { + $predefips{$nodeip} = $_; + } else { + if (defined($freenodeent->{$_}->[0]) && $freenodeent->{$_}->[0]->{'ip'}){ + $predefips{$freenodeent->{$_}->[0]->{'ip'}} = $_; + } + } + } + } + + return \%predefips; +} =head3 getfreeips Get the free ips base on the user specified ip range arg1 - the ip range. Two format are suported: 192.168.1.1-192.168.2.50; 192.168.[1-2].[10-100] - arg2 - "all': return all the free nodes; otherwise just return one. + arg2 - all the free nodes + arg3 - type: host, bmc + arg4 - "all': return free ips for all the free nodes; otherwise just return the first one. + + return: array of all free ips or one ip base on the arg4 =cut -sub getfreeips () { +sub getfreeips { my $iprange = shift; my $freenode = shift; my $type = shift; # type: host, bmc my $all = shift; my @freeips; - my %predefips; # to have the ip which assigned to a node which in $freenode + my %predefips; # to have the ip which prefined to the nodes - # get all used ip from hosts table my $hoststb = xCAT::Table->new('hosts'); unless ($hoststb) { xCAT::MsgUtils->message("S", "Discovery Error: Could not open table: hosts."); } - if ($type eq "bmc") { - - # Find the bmc ip which defined in the ipmi.bmc as an ip address instead of name as 'node-bmc' - #my $ipmitab = xCAT::Table->new('ipmi'); - #if ($ipmitab) { - # my $ipmient = $ipmitab->getNodeAttribs($freenode, ['bmc']); - # foreach (@$freenode) { - # if (defined($ipmient->{$_}) && ($ipmient->{$_}->{'bmc'} =~ /\d+\.\d+\.\d+\.\d+/)) { - # $predefips{$ipmient->{$_}->{'bmc'}} = 1; - # } - # } - #} - - # replace the $freenode with the bmc name as 'node-bmc' format - my @freebmc; - foreach (@$freenode) { - push @freebmc, $_.'-bmc'; - } - $freenode = \@freebmc; - } - - my $freenodeent = $hoststb->getNodesAttribs($freenode, ['ip']); - - foreach (@$freenode) { - if (defined($freenodeent->{$_}->[0]) && $freenodeent->{$_}->[0]->{'ip'}){ - $predefips{$freenodeent->{$_}->[0]->{'ip'}} = 1; - } - } - - my @hostsent = $hoststb->getAllNodeAttribs(['node', 'ip']); + my @freebmc; my %usedips = (); - foreach my $host (@hostsent) { - if (defined ($host->{'ip'}) && !$predefips{$host->{'ip'}}) { - $usedips{$host->{'ip'}} = 1; + if ($type eq "bmc") { + # get the host ip for all predefind nodes from $freenode + %predefips = %{getpredefips($freenode, "bmc")}; + + # get all the used ips, the predefined ip should be ignored + my @hostsent = $hoststb->getAllNodeAttribs(['node', 'ip', 'otherinterfaces']); + foreach my $host (@hostsent) { + # handle the case that node-bmc has an entry in the hosts table + my $nodeip = xCAT::NetworkUtils->getipaddr($_); + if ($nodeip) { + unless ($predefips{$nodeip}) { + $usedips{$nodeip} = 1; + } + } else { + if (defined ($host->{'ip'}) && !$predefips{$host->{'ip'}}) { + $usedips{$host->{'ip'}} = 1; + } + } + # handle the case that the bmc<->ip mapping is specified in hosts.otherinterfaces + if (defined($host->{'otherinterfaces'})) { + my $bmcip = getbmcip_otherinterfaces($host, $host->{'otherinterfaces'}); + unless ($predefips{$bmcip}) { + $usedips{$bmcip} = 1; + } + } + } + } elsif ($type eq "host") { + # get the bmc ip for all predefind nodes from $freenode + %predefips = %{getpredefips($freenode, "host")}; + + # get all the used ips, the predefined ip should be ignored + my @hostsent = $hoststb->getAllNodeAttribs(['node', 'ip']); + foreach my $host (@hostsent) { + my $nodeip = xCAT::NetworkUtils->getipaddr($_); + if ($nodeip) { + unless ($predefips{$nodeip}) { + $usedips{$nodeip} = 1; + } + } else { + if (defined ($host->{'ip'}) && !$predefips{$host->{'ip'}}) { + $usedips{$host->{'ip'}} = 1; + } + } } } + # to calculate the free IP. free ip = 'ip in the range' - 'used ip' if ($iprange =~ /(\d+\.\d+\.\d+\.\d+)-(\d+\.\d+\.\d+\.\d+)/) { + # if ip range format is 192.168.1.0-192.168.1.200 my ($startip, $endip) = ($1, $2); my $startnum = xCAT::NetworkUtils->ip_to_int($startip); my $endnum = xCAT::NetworkUtils->ip_to_int($endip); @@ -1195,4 +1303,39 @@ sub getfreeips () { } } +=head3 getbmcip_otherinterfaces + Parse the value in the hosts.otherinterfaces + arg1 - node + arg2 - value in the hosts.otherinterfaces + + return: the ip of the node -bmc +=cut +sub getbmcip_otherinterfaces +{ + my $node = shift; + my $otherinterfaces = shift; + + my @itf_pairs = split(/,/, $otherinterfaces); + foreach (@itf_pairs) + { + my ($itf, $ip); + if ($_ =~ /!/) { + ($itf, $ip) = split(/!/, $_); + } else { + ($itf, $ip) = split(/:/, $_); + } + + if ($itf =~ /^-/) + { + $itf = $node . $itf; + } + + if ($itf eq "$node-bmc") { + return xCAT::NetworkUtils->getipaddr($ip); + } + } + + return; +} + 1;