From 973597d493c295e63096dcf187edebefaa4c7d11 Mon Sep 17 00:00:00 2001 From: bp-sawyers Date: Mon, 20 May 2013 13:12:54 +0000 Subject: [PATCH] Add genericrange option to noderange function so we can remove NameRange.pm git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@16363 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/NameRange.pm | 271 --------------------- perl-xCAT/xCAT/NodeRange.pm | 81 +++--- xCAT-server/lib/xcat/plugins/rollupdate.pm | 10 +- 3 files changed, 55 insertions(+), 307 deletions(-) delete mode 100644 perl-xCAT/xCAT/NameRange.pm diff --git a/perl-xCAT/xCAT/NameRange.pm b/perl-xCAT/xCAT/NameRange.pm deleted file mode 100644 index 29a7ae9fc..000000000 --- a/perl-xCAT/xCAT/NameRange.pm +++ /dev/null @@ -1,271 +0,0 @@ -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html -package xCAT::NameRange; -require xCAT::Table; -require Exporter; -use strict; - -#Perl implementation of namerange -# NOTE: This is identical to xCAT::NodeRange except that no -# database access occurs, no nodes are verified, and -# no nodegroups are expanded. -# Made a new utility since NodeRange is used EVERYWHERE in -# xCAT code and did not want to risk de-stabilizing existing code. -our @ISA = qw(Exporter); -our @EXPORT = qw(namerange); - -my $recurselevel=0; - - -sub subnodes (\@@) { - #Subtract set of nodes from the first list - my $nodes = shift; - my $node; - foreach $node (@_) { - @$nodes = (grep(!/^$node$/,@$nodes)); - } -} - -sub expandatom { - my $atom = shift; - my @nodes= (); - if ($atom =~ /^\(.*\)$/) { # handle parentheses by recursively calling namerange() - $atom =~ s/^\((.*)\)$/$1/; - $recurselevel++; - return namerange($atom); - } - if ($atom =~ /@/) { - $recurselevel++; - return namerange($atom); - } - - if ($atom =~ m/^\//) { # A regular expression - not supported in namerange - return ($atom); - } - - if ($atom =~ m/(.*)\[(.*)\](.*)/) { # square bracket range - #for the time being, we are only going to consider one [] per atom - #xcat 1.2 does no better - my @subelems = split(/([\,\-\:])/,$2); - my $subrange=""; - while (my $subelem = shift @subelems) { - my $subop=shift @subelems; - $subrange=$subrange."$1$subelem$3$subop"; - } - foreach (split /,/,$subrange) { - my @newnodes=expandatom($_); - @nodes=(@nodes,@newnodes); - } - return @nodes; - } - - if ($atom =~ m/\+/) { # process the + operator - $atom =~ m/^([^0-9]*)([0-9]+)([^\+]*)\+([0-9]+)/; - my $pref=$1; - my $startnum=$2; - my $suf=$3; - my $end=$4+$startnum; - my $endnum = sprintf("%d",$end); - if (length ($startnum) > length ($endnum)) { - $endnum = sprintf("%0".length($startnum)."d",$end); - } - foreach ("$startnum".."$endnum") { - my @addnodes=expandatom($pref.$_.$suf); - @nodes=(@nodes,@addnodes); - } - return (@nodes); - } - - if ($atom =~ m/[-:]/) { # process the minus range operator - my $left; - my $right; - if ($atom =~ m/:/) { - ($left,$right)=split /:/,$atom; - } else { - my $count= ($atom =~ tr/-//); - if (($count % 2)==0) { #can't understand even numbers of - in range context - # we might not really be in range context - return ($atom); - } - my $expr="([^-]+?".("-[^-]*"x($count/2)).")-(.*)"; - $atom =~ m/$expr/; - $left=$1; - $right=$2; - } - if ($left eq $right) { #if they said node1-node1 for some strange reason - return expandatom($left); - } - my @leftarr=split(/(\d+)/,$left); - my @rightarr=split(/(\d+)/,$right); - if (scalar(@leftarr) != scalar(@rightarr)) { #Mismatch formatting.. - # guess it's meant to be a nodename - return ($atom); - } - my $prefix = ""; - my $suffix = ""; - foreach (0..$#leftarr) { - my $idx = $_; - if ($leftarr[$idx] =~ /^\d+$/ and $rightarr[$idx] =~ /^\d+$/) { #pure numeric component - if ($leftarr[$idx] ne $rightarr[$idx]) { #We have found the iterator (only supporting one for now) - my $prefix = join('',@leftarr[0..($idx-1)]); #Make a prefix of the pre-validated parts - my $luffix; #However, the remainder must still be validated to be the same - my $ruffix; - if ($idx eq $#leftarr) { - $luffix=""; - $ruffix=""; - } else { - $ruffix = join('',@rightarr[($idx+1)..$#rightarr]); - $luffix = join('',@leftarr[($idx+1)..$#leftarr]); - } - if ($luffix ne $ruffix) { #the suffixes mismatched.. - return ($atom); - } - foreach ($leftarr[$idx]..$rightarr[$idx]) { - my @addnodes=expandatom($prefix.$_.$luffix); - @nodes=(@nodes,@addnodes); - } - return (@nodes); #the return has been built, return, exiting loop and all - } - } elsif ($leftarr[$idx] ne $rightarr[$idx]) { - return ($atom); - } - $prefix .= $leftarr[$idx]; #If here, it means that the pieces were the same, but more to come - } - #I cannot conceive how the code could possibly be here, but whatever it is, it must be questionable - return ($atom); - } - - return ($atom); -} - -sub namerange { - #We for now just do left to right operations - my $range=shift; - my %nodes = (); - my %delnodes = (); - my $op = ","; - my @elems = split(/(,(?![^[]*?])(?![^\(]*?\)))/,$range); # commas outside of [] or () - if (scalar(@elems)==1) { - @elems = split(/(@(?![^\(]*?\)))/,$range); # only split on @ when no , are present (inner recursion) - } - - while (my $atom = shift @elems) { - if ($atom =~ /^-/) { # if this is an exclusion, strip off the minus, but remember it - $atom = substr($atom,1); - $op = $op."-"; - } - - if ($atom =~ /^\^(.*)$/) { # get a list of nodes from a file - open(NRF,$1); - while () { - my $line=$_; - unless ($line =~ m/^[\^#]/) { - $line =~ m/^([^: ]*)/; - my $newrange = $1; - chomp($newrange); - $recurselevel++; - my @filenodes = namerange($newrange); - foreach (@filenodes) { - $nodes{$_}=1; - } - } - } - close(NRF); - next; - } - - my %newset = map { $_ =>1 } expandatom($atom); # expand the atom and make each entry in the resulting array a key in newset - - if ($op =~ /@/) { # compute the intersection of the current atom and the node list we have received before this - foreach (keys %nodes) { - unless ($newset{$_}) { - delete $nodes{$_}; - } - } - } elsif ($op =~ /,-/) { # add the nodes from this atom to the exclude list - foreach (keys %newset) { - $delnodes{$_}=1; #delay removal to end - } - } else { # add the nodes from this atom to the total node list - foreach (keys %newset) { - $nodes{$_}=1; - } - } - $op = shift @elems; - - } # end of main while loop - - # Now remove all the exclusion nodes - foreach (keys %nodes) { - if ($delnodes{$_}) { - delete $nodes{$_}; - } - } - if ($recurselevel) { - $recurselevel--; - } - return sort (keys %nodes); - -} - - -1; - -=head1 NAME - -xCAT::NameRange - Perl module for xCAT namerange expansion - -=head1 SYNOPSIS - - use xCAT::NameRange; - my @nodes=namerange("storage@rack1,node[1-200],^/tmp/nodelist,node300-node400,node401+10,500-550"); - -=head1 DESCRIPTION - -namerange interprets xCAT noderange formatted strings and returns a list of -names. The following two operations are supported on elements, and interpreted -left to right: - - , union next element with everything to the left. - - @ take intersection of element to the right with everything on the left - (i.e. mask out anything to the left not belonging to what is described to - the right) - -Each element can be a number of things: - - A node name, i.e.: - -=item * node1 - -A hyphenated node range (only one group of numbers may differ between the left and right hand side, and those numbers will increment in a base 10 fashion): - -node1-node200 node1-compute-node200-compute -node1:node200 node1-compute:node200-compute - -A namerange denoted by brackets: - -node[1-200] node[001-200] - -A regular expression describing the namerange: - -/d(1.?.?|200) - -A node plus offset (this increments the first number found in nodename): - -node1+199 - -And most of the above substituting groupnames. -3C -3C - -NameRange tries to be intelligent about detecting padding, so you can: -node001-node200 -And it will increment according to the pattern. - - -=head1 COPYRIGHT - -Copyright 2007 IBM Corp. All rights reserved. - - -=cut diff --git a/perl-xCAT/xCAT/NodeRange.pm b/perl-xCAT/xCAT/NodeRange.pm index b280abbeb..301fffe90 100644 --- a/perl-xCAT/xCAT/NodeRange.pm +++ b/perl-xCAT/xCAT/NodeRange.pm @@ -180,7 +180,14 @@ sub nodesbycriteria { return \%critnodes; } -sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels5.3) +# Expand one part of the noderange from the noderange() function. Initially, one part means the +# substring between commas in the noderange. But expandatom also calls itself recursively to +# further expand some parts. +# Input args: +# - atom to expand +# - verify: whether or not to require that the resulting nodenames exist in the nodelist table +# - options: genericrange - a purely syntactical expansion of the range, not using the db at all, e.g not expanding group names +sub expandatom { my $atom = shift; if ($recurselevel > 4096) { die "NodeRange seems to be hung on evaluating $atom, recursion limit hit"; } unless (scalar(@allnodeset) and (($allnodesetstamp+5) > time())) { #Build a cache of all nodes, some corner cases will perform worse, but by and large it will do better. We could do tests to see where the breaking points are, and predict how many atoms we have to evaluate to mitigate, for now, implement the strategy that keeps performance from going completely off the rails @@ -190,26 +197,27 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels %allnodehash = map { $_->{node} => 1 } @allnodeset; } my $verify = (scalar(@_) >= 1 ? shift : 1); - my %args = @_; + my %options = @_; # additional options my @nodes= (); #TODO: these env vars need to get passed by the client to xcatd my $nprefix=(defined ($ENV{'XCAT_NODE_PREFIX'}) ? $ENV{'XCAT_NODE_PREFIX'} : 'node'); my $nsuffix=(defined ($ENV{'XCAT_NODE_SUFFIX'}) ? $ENV{'XCAT_NODE_SUFFIX'} : ''); - if (not $args{genericrange} and $allnodehash{$atom}) { #The atom is a plain old nodename + + if (not $options{genericrange} and $allnodehash{$atom}) { #The atom is a plain old nodename return ($atom); } if ($atom =~ /^\(.*\)$/) { # handle parentheses by recursively calling noderange() $atom =~ s/^\((.*)\)$/$1/; $recurselevel++; - return noderange($atom); + return noderange($atom,$verify,1,%options); } if ($atom =~ /@/) { $recurselevel++; - return noderange($atom); + return noderange($atom,$verify,1,%options); } # Try to match groups? - unless ($args{genericrange}) { + unless ($options{genericrange}) { unless ($grptab) { $grptab = xCAT::Table->new('nodegroup'); } @@ -273,6 +281,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels } } + # node selection based on db attribute values (nodetype.os==rhels5.3) if ($atom =~ m/[=~]/) { #TODO: this is the clunky, slow code path to acheive the goal. It also is the easiest to write, strange coincidence. Aggregating multiples would be nice my @nodes; foreach (@allnodeset) { @@ -290,7 +299,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels } if ($atom =~ m/^[0-9]+\z/) { # if only numbers, then add the prefix my $nodename=$nprefix.$atom.$nsuffix; - return expandatom($nodename,$verify,%args); + return expandatom($nodename,$verify,%options); } my $nodelen=@nodes; if ($nodelen > 0) { @@ -298,7 +307,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels } if ($atom =~ m/^\//) { # A regular expression - unless ($verify) { # If not in verify mode, regex makes zero possible sense + if ($verify==0 or $options{genericrange}) { # If not in verify mode, regex makes zero possible sense return ($atom); } #TODO: check against all groups @@ -312,25 +321,29 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels } if ($atom =~ m/(.+?)\[(.+?)\](.*)/) { # square bracket range - # if there are more than 1 [], we picked off just the 1st. if there is another, we will process it later - my @subelems = split(/([\,\-\:])/,$2); + # if there is more than 1 set of [], we picked off just the 1st. If there more sets of [], we will expand + # the 1st set and create a new set of atom by concatenating each result in the 1st expandsion with the rest + # of the brackets. Then call expandatom() recursively on each new atom. + my @subelems = split(/([\,\-\:])/,$2); # $2 is the range inside the 1st set of brackets my $subrange=""; - my $subelem; - my $start = $1; - my $ending = $3; - my $morebrackets = $ending =~ /\[.+?\]/; # if there are more brackets, we have to expand just the 1st part, then add the 2nd part later - while (scalar @subelems) { - my $subelem = shift @subelems; + my $subelem; + my $start = $1; # the text before the 1st set of brackets + my $ending = $3; # the text after the 1st set of brackets (could contain more brackets) + my $morebrackets = $ending =~ /\[.+?\]/; # if there are more brackets, we have to expand just the 1st part, then add the 2nd part later + while (scalar @subelems) { # this while loop turns something like a[1-3] into a1-a3 because another section of expand atom knows how to expand that + my $subelem = shift @subelems; my $subop=shift @subelems; $subrange=$subrange."$start$subelem" . ($morebrackets?'':$ending) . "$subop"; } - foreach (split /,/,$subrange) { - my @newnodes=expandatom($_, ($morebrackets?0:$verify), genericrange=>$morebrackets); + foreach (split /,/,$subrange) { # this foreach is in case there were commas inside the brackets originally, e.g.: a[1,3,5]b[1-2] + # this expandatom just expands the part of the noderange that contains the 1st set of brackets + # e.g. if noderange is a[1-2]b[1-2] it will create newnodes of a1 and a2 + my @newnodes=expandatom($_, ($morebrackets?0:$verify), genericrange=>($morebrackets||$options{genericrange})); if (!$morebrackets) { push @nodes,@newnodes; } else { - # for each of the new nodes, add the 2nd brackets and then expand + # for each of the new nodes (prefixes), add the rest of the brackets and then expand recursively foreach my $n (@newnodes) { - push @nodes, expandatom("$n$ending", $verify, %args); + push @nodes, expandatom("$n$ending", $verify, %options); } } } @@ -352,7 +365,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels $suf=$nsuffix; } foreach ("$startnum".."$endnum") { - my @addnodes=expandatom($pref.$_.$suf,$verify,%args); + my @addnodes=expandatom($pref.$_.$suf,$verify,%options); @nodes=(@nodes,@addnodes); } return (@nodes); @@ -379,7 +392,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels $right=$2; } if ($left eq $right) { #if they said node1-node1 for some strange reason - return expandatom($left,$verify,%args); + return expandatom($left,$verify,%options); } my @leftarr=split(/(\d+)/,$left); my @rightarr=split(/(\d+)/,$right); @@ -416,7 +429,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels } } foreach ($leftarr[$idx]..$rightarr[$idx]) { - my @addnodes=expandatom($prefix.$_.$luffix,$verify,%args); + my @addnodes=expandatom($prefix.$_.$luffix,$verify,%options); push @nodes,@addnodes; } return (@nodes); #the return has been built, return, exiting loop and all @@ -464,7 +477,7 @@ sub retain_cache { #A semi private operation to be used *ONLY* in the interestin %allgrphash=(); } } -sub extnoderange { #An extended noderange function. Needed as the more straightforward function return format too simple for this. +sub extnoderange { #An extended noderange function. Needed by the GUI as the more straightforward function return format too simple for this. my $range = shift; my $namedopts = shift; my $verify=1; @@ -490,7 +503,7 @@ sub extnoderange { #An extended noderange function. Needed as the more straight return $return; } sub abbreviate_noderange { - #takes a list of nodes or a string and abbreviates + #takes a list of nodes or a string and reduces it by replacing a list of nodes that make up a group with the group name itself my $nodes=shift; my %grouphash; my %sizedgroups; @@ -536,16 +549,20 @@ sub abbreviate_noderange { return (join ',',keys %targetelems,keys %nodesleft); } +# Expand the given noderange +# Input args: +# - noderange to expand +# - verify: whether or not to require that the resulting nodenames exist in the nodelist table +# - exsitenode: whether or not to honor site.excludenodes to automatically exclude those nodes from all noderanges +# - options: genericrange - a purely syntactical expansion of the range, not using the db at all, e.g not expanding group names sub noderange { $missingnodes=[]; #We for now just do left to right operations my $range=shift; $range =~ s/['"]//g; my $verify = (scalar(@_) >= 1 ? shift : 1); - - #excludenodes attribute in site table, - #these nodes should be excluded for any xCAT commands - my $exsitenode = (scalar(@_) >= 1 ? shift : 1); + my $exsitenode = (scalar(@_) >= 1 ? shift : 1); # if 1, honor site.excludenodes + my %options = @_; # additional options unless ($nodelist) { $nodelist =xCAT::Table->new('nodelist',-create =>1); @@ -580,7 +597,7 @@ sub noderange { my $newrange = $1; chomp($newrange); $recurselevel++; - my @filenodes = noderange($newrange); + my @filenodes = noderange($newrange,$verify,$exsitenode,%options); foreach (@filenodes) { $nodes{$_}=1; } @@ -590,7 +607,7 @@ sub noderange { next; } - my %newset = map { $_ =>1 } expandatom($atom,$verify); # expand the atom and make each entry in the resulting array a key in newset + my %newset = map { $_ =>1 } expandatom($atom,$verify,%options); # expand the atom and make each entry in the resulting array a key in newset if ($op =~ /@/) { # compute the intersection of the current atom and the node list we have received before this foreach (keys %nodes) { @@ -617,7 +634,7 @@ sub noderange { my $badnoderange = 0; my @badnodes = (); if ($::XCATSITEVALS{excludenodes}) { - @badnodes = noderange($::XCATSITEVALS{excludenodes}, 1, 0); + @badnodes = noderange($::XCATSITEVALS{excludenodes}, 1, 0, %options); foreach my $bnode (@badnodes) { if (!$delnodes{$bnode}) { $delnodes{$bnode} = 1; diff --git a/xCAT-server/lib/xcat/plugins/rollupdate.pm b/xCAT-server/lib/xcat/plugins/rollupdate.pm index 696262021..c038d371b 100644 --- a/xCAT-server/lib/xcat/plugins/rollupdate.pm +++ b/xCAT-server/lib/xcat/plugins/rollupdate.pm @@ -14,7 +14,6 @@ BEGIN } require xCAT::NodeRange; -require xCAT::NameRange; require xCAT::Table; require xCAT::Utils; require xCAT::TableUtils; @@ -583,7 +582,8 @@ sub rollupdate { } foreach my $mgline ( @{ $::FILEATTRS{'mapgroups'} } ) { - my @ugnamelist = xCAT::NameRange::namerange( $mgline, 0 ); + #my @ugnamelist = xCAT::NameRange::namerange( $mgline, 0 ); + my @ugnamelist = xCAT::NodeRange::noderange( $mgline, 0, 1, genericrange=>1 ); foreach my $ugname (@ugnamelist) { @{ $updategroup{$ugname} } = xCAT::NodeRange::noderange($ugname); if ( xCAT::NodeRange::nodesmissed() ) { @@ -1756,7 +1756,8 @@ sub create_LL_mutex_resources { my @ugnames; foreach my $mxpart ( @mxparts ) { my $mxindex2 = $mxindex; - my @ugnamelist = xCAT::NameRange::namerange( $mxpart, 0 ); + #my @ugnamelist = xCAT::NameRange::namerange( $mxpart, 0 ); + my @ugnamelist = xCAT::NodeRange::noderange( $mxpart, 0, 1, genericrange=>1 ); foreach my $ugname (@ugnamelist) { $::MUTEX[$mxindex2][$mxpi] = $ugname; $mxindex2++; @@ -1780,7 +1781,8 @@ sub create_LL_mutex_resources { foreach my $mxnodegrp_range ( @{ $::FILEATTRS{'nodegroup_mutex'} } ) { my $mx_count = $::FILEATTRS{'nodegroup_mutex_count'}[$fileattrs_index]; - foreach my $mxnodegroup ( xCAT::NameRange::namerange( $mxnodegrp_range, 0 ) ) { + #foreach my $mxnodegroup ( xCAT::NameRange::namerange( $mxnodegrp_range, 0 ) ) { + foreach my $mxnodegroup ( xCAT::NodeRange::noderange( $mxnodegrp_range, 0, 1, genericrange=>1 ) ) { my $mxpi = 0; mxnode_loop: foreach my $mxnode ( xCAT::NodeRange::noderange($mxnodegroup) ) { foreach my $ugname ( keys %{$updategroup} ) {