rollupdate - add support for translatenames
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@10012 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -20,6 +20,10 @@ require Data::Dumper; | ||||
| require Getopt::Long; | ||||
| require xCAT::MsgUtils; | ||||
| require File::Path; | ||||
| use Text::Balanced qw(extract_bracketed); | ||||
| use Safe; | ||||
| my $evalcpt = new Safe; | ||||
|  | ||||
| use strict; | ||||
| use warnings; | ||||
|  | ||||
| @@ -559,6 +563,7 @@ sub rollupdate { | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     # | ||||
|     # Build and submit scheduler jobs | ||||
|     # | ||||
| @@ -643,6 +648,15 @@ sub ll_jobs { | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # Translate xCAT names to LL names | ||||
|     $::XLATED = {}; | ||||
|     if (defined($::FILEATTRS{translatenames}[0])) { | ||||
|        foreach my $xlate_stanza( @{ $::FILEATTRS{'translatenames'} } ) { | ||||
|           translate_names($xlate_stanza); | ||||
|        } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     # Create LL floating resources for mutual exclusion support | ||||
|     #   and max_updates | ||||
|     if (&create_LL_mutex_resources($updategroup,$::updateall) > 0) { | ||||
| @@ -774,16 +788,22 @@ sub ll_jobs { | ||||
|         my ( $nodelist, $machinelist ); | ||||
|         my $machinecount = 0; | ||||
|         foreach my $node ( @{ $updategroup->{$ugname} } ) { | ||||
|             if ( defined( $machines{$node} ) | ||||
|                  && ( $machines{$node}{'mstatus'} eq "1" ) ) { | ||||
|                 $machinelist .= " $machines{$node}{'mname'}"; | ||||
|             my $xlated_node; | ||||
|             if ( defined ($::XLATED{$node}) ){ | ||||
|                $xlated_node = $::XLATED{$node}; | ||||
|             } else { | ||||
|                $xlated_node = $node; | ||||
|             } | ||||
|             if ( defined( $machines{$xlated_node} ) | ||||
|                  && ( $machines{$xlated_node}{'mstatus'} eq "1" ) ) { | ||||
|                 $machinelist .= " $machines{$xlated_node}{'mname'}"; | ||||
|                 $machinecount++; | ||||
|                 $nodelist .= ",$node"; | ||||
|             } elsif ( $run_if_down eq 'yes' ) { | ||||
|                 if ( defined( $machines{$node} ) ) { | ||||
|                 if ( defined( $machines{$xlated_node} ) ) { | ||||
|                    # llmkres -D will allow reserving down nodes as long | ||||
|                    # as they are present in the machine list | ||||
|                     $machinelist .= " $machines{$node}{'mname'}"; | ||||
|                     $machinelist .= " $machines{$xlated_node}{'mname'}"; | ||||
|                     $machinecount++; | ||||
|                 } | ||||
|                 $nodelist .= ",$node"; | ||||
| @@ -833,6 +853,11 @@ sub ll_jobs { | ||||
|         if (defined($::FILEATTRS{bringuptimeout}[0])){ | ||||
|             push (@ugdflines, "bringuptimeout=$::FILEATTRS{bringuptimeout}[0]\n"); | ||||
|         }  | ||||
|         if (defined($::FILEATTRS{translatenames}[0])){ | ||||
|             foreach my $xlate_stanza( @{ $::FILEATTRS{'translatenames'} } ) { | ||||
|                 push (@ugdflines, "translatenames=$xlate_stanza\n"); | ||||
|             } | ||||
|         }  | ||||
|         if (defined($::FILEATTRS{skipshutdown}[0])){ | ||||
|             push (@ugdflines, "skipshutdown=$::FILEATTRS{skipshutdown}[0]\n"); | ||||
|         }  | ||||
| @@ -884,7 +909,8 @@ sub ll_jobs { | ||||
|             }            | ||||
|  | ||||
|             # Build reservation callback script  | ||||
|             my @rcblines; | ||||
|              | ||||
| my @rcblines; | ||||
|             my $rcbcmd = $::FILEATTRS{'reservationcallback'}[0]; | ||||
|             if (!defined($rcbcmd)){ $rcbcmd = "$::XCATROOT/bin/runrollupdate"; } | ||||
|             push (@rcblines, "#!/bin/sh \n"); | ||||
| @@ -953,6 +979,7 @@ sub ll_jobs { | ||||
|                 if ( $jcline =~ /Feature/ ) { | ||||
|                     $jcline =~ s/\"\s+/\"/g; | ||||
|                     $jcline =~ s/\s+\"/\"/g; | ||||
|                     $jcline =~ s/\=\"/\= \"/g; | ||||
|                 } | ||||
|                 if ($lastcount) { | ||||
|                     $jcline2 = $jcline; | ||||
| @@ -1191,6 +1218,117 @@ sub check_policy { | ||||
|  | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| =head3   translate_names | ||||
|  | ||||
|         Translate xCAT node names to scheduler names as requested by the user | ||||
|  | ||||
|         Arguments:  $instructions - translation instructions of the form: | ||||
|                       <xcat_noderange>:/<pattern>/<replacement>/ | ||||
|                     OR | ||||
|                       <xcat_noderange>:|<pattern>|<replacement>| | ||||
|         Returns:  | ||||
|         Globals: | ||||
|                 hash:  $::XLATED{$node}=$xlated_name                 | ||||
|                 AND    $::XLATED{$xlated_name}=$node | ||||
|                 to allow easy lookup in either direction | ||||
|         Error: | ||||
|         Example: | ||||
|  | ||||
|         Comments: | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #----------------------------------------------------------------------------- | ||||
| # This is a utility function to create a number out of a string, useful for things like round robin algorithms on unnumbered nodes | ||||
| sub mknum { | ||||
|     my $string = shift; | ||||
|     my $number=0; | ||||
|     foreach (unpack("C*",$string)) { #do big endian, then it would make 'fred' and 'free' be one number apart | ||||
|         $number += $_; | ||||
|     } | ||||
|     return $number; | ||||
| } | ||||
| $evalcpt->share('&mknum'); | ||||
| $evalcpt->permit('require'); | ||||
|  | ||||
| sub translate_names{ | ||||
|   my $instructions = shift; | ||||
|  | ||||
|   my ($nr,$regexps) = split( /\:/, $instructions ); | ||||
|   my @xCATnodes = xCAT::NodeRange::noderange($nr); | ||||
|  | ||||
|   foreach my $xCATnode (@xCATnodes) { | ||||
|         my $xlated_node = $xCATnode; | ||||
|         my $datum = $regexps; | ||||
|   # The following is based on code copied from Table::getNodeAttribs | ||||
|         if ($datum =~ /^\/[^\/]*\/[^\/]*\/$/) | ||||
|         { | ||||
|             my $exp = substr($datum, 1); | ||||
|             chop $exp; | ||||
|             my @parts = split('/', $exp, 2); | ||||
|             $xlated_node =~ s/$parts[0]/$parts[1]/; | ||||
|             $datum = $xlated_node; | ||||
|         } | ||||
|         elsif ($datum =~ /^\|.*\|.*\|$/) | ||||
|        { | ||||
|             #Perform arithmetic and only arithmetic operations in bracketed issues on the right. | ||||
|             #Tricky part:  don't allow potentially dangerous code, only eval if | ||||
|             #to-be-evaled expression is only made up of ()\d+-/%$ | ||||
|             #Futher paranoia?  use Safe module to make sure I'm good | ||||
|             my $exp = substr($datum, 1); | ||||
|             chop $exp; | ||||
|             my @parts = split('\|', $exp, 2); | ||||
|             my $curr; | ||||
|             my $next; | ||||
|             my $prev; | ||||
|             my $retval = $parts[1]; | ||||
|             ($curr, $next, $prev) = | ||||
|               extract_bracketed($retval, '()', qr/[^()]*/); | ||||
|  | ||||
|             unless($curr) { #If there were no paramaters to save, treat this one like a plain regex | ||||
|                undef $@; #extract_bracketed would have set $@ if it didn't return, undef $@ | ||||
|                $retval = $xlated_node; | ||||
|                $retval =~ s/$parts[0]/$parts[1]/; | ||||
|                $datum = $retval; | ||||
|                unless ($datum =~ /^$/) { # ignore blank translations | ||||
|                  $xlated_node=$datum; | ||||
|                } | ||||
|                next; #skip the redundancy that follows otherwise | ||||
|             } | ||||
|             while ($curr) | ||||
|             { | ||||
|  | ||||
|                 #my $next = $comps[0]; | ||||
|                 my $value = $xlated_node; | ||||
|                 $value =~ s/$parts[0]/$curr/; | ||||
| #                $value = $evalcpt->reval('use integer;'.$value); | ||||
|                 $value = $evalcpt->reval($value); | ||||
|                 $retval = $prev . $value . $next; | ||||
|                 #use text::balanced extract_bracketed to parse each atom, make sure nothing but arith operators, parens, and numbers are in it to guard against code execution | ||||
|                 ($curr, $next, $prev) = | ||||
|                   extract_bracketed($retval, '()', qr/[^()]*/); | ||||
|             } | ||||
|             undef $@; | ||||
|             #At this point, $retval is the expression after being arithmetically contemplated, a generated regex, and therefore | ||||
|             #must be applied in total | ||||
|             my $answval = $xlated_node; | ||||
|             $answval =~ s/$parts[0]/$retval/; | ||||
|             $datum = $answval; #$retval; | ||||
|         } | ||||
|         unless ($datum =~ /^$/) { | ||||
|             $::XLATED{$xCATnode}=$datum; | ||||
|             $::XLATED{$datum}=$xCATnode; | ||||
|         } | ||||
|  | ||||
|   } | ||||
| #  print Dumper($::XLATED); | ||||
|   return ; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| =head3   set_LL_feature | ||||
| @@ -1788,9 +1926,15 @@ sub runrollupdate { | ||||
|                  ($::DATAATTRS{skipshutdown}[0] eq "1") ) ) { | ||||
|         $skipshutdown = 1; | ||||
|     }  | ||||
|     $::XLATED = {}; | ||||
|     if (defined($::DATAATTRS{translatenames}[0])) { | ||||
|        foreach my $xlate_stanza( @{ $::DATAATTRS{'translatenames'} } ) { | ||||
|           translate_names($xlate_stanza); | ||||
|        } | ||||
|     } | ||||
|  | ||||
|     # make sure nodes are in correct state | ||||
|     my $hostlist = &get_hostlist; | ||||
|     my $hostlist = &get_hostlist(); | ||||
|     if (! $hostlist ) { | ||||
|         if ($::VERBOSE) {  | ||||
|             open (RULOG, ">>$::LOGDIR/$::LOGFILE"); | ||||
| @@ -1804,7 +1948,7 @@ sub runrollupdate { | ||||
|     } | ||||
|  | ||||
|     my $nltab = xCAT::Table->new('nodelist'); | ||||
|     my @nodes = split( /\,/, $hostlist ); | ||||
|     my @nodes = split( /\,/, $hostlist );     | ||||
|     my $appstatus=xCAT::Utils->getAppStatus(\@nodes,"RollingUpdate"); | ||||
|     foreach my $node (@nodes) { | ||||
|         unless ( defined($appstatus->{$node}) | ||||
| @@ -2054,16 +2198,25 @@ sub runrollupdate { | ||||
|         my $totalwait = 0; | ||||
|         my %ll_res; | ||||
|         while ($not_done && $totalwait < ($statustimeout * 60)) { | ||||
|             my @query_bootnodes; | ||||
|             foreach my $bn (keys %ll_res) { | ||||
|                 if ( ! ($ll_res{$bn}{removed}) ) { | ||||
|                     push (@query_bootnodes,$bn); | ||||
|                 } | ||||
|             } | ||||
|             if ( ! @query_bootnodes ) { | ||||
|                 @query_bootnodes = @bootnodes; | ||||
|             } | ||||
|             if ($::VERBOSE) {  | ||||
|                  open (RULOG, ">>$::LOGDIR/$::LOGFILE"); | ||||
|                  print RULOG localtime()." $::ug_name:  Checking ".join(",",@bootnodes)." xCAT database $statusattr for value $statusval \n"; | ||||
|                  print RULOG localtime()." $::ug_name:  Checking ".join(",",@query_bootnodes)." xCAT database $statusattr for value $statusval \n"; | ||||
|                  close (RULOG); | ||||
|             } | ||||
|             my $nltab_stats = | ||||
|                 $nltab->getNodesAttribs( \@bootnodes, [ 'node', $statusattr ] ); | ||||
|             %ll_res = (); | ||||
|                 $nltab->getNodesAttribs( \@query_bootnodes, [ 'node', $statusattr ] ); | ||||
| #           %ll_res = (); | ||||
|             $not_done = 0; | ||||
|             foreach my $bn (@bootnodes) { | ||||
|             foreach my $bn (@query_bootnodes) { | ||||
|                 if ( $nltab_stats->{$bn}->[0]->{$statusattr} !~ /$statusval/ ) { | ||||
|                   $ll_res{$bn}{not_done}=1; | ||||
|                   $not_done = 1; | ||||
| @@ -2075,9 +2228,14 @@ sub runrollupdate { | ||||
|                 ($::ll_reservation_id)){  | ||||
|                 my @remove_res; | ||||
|                 foreach my $bn (keys %ll_res) { | ||||
|                     if ($ll_res{$bn}{remove} && ! $ll_res{$bn}{removed} ){ | ||||
|                         push (@remove_res,$bn); | ||||
|                     if (($ll_res{$bn}{remove}) && (! $ll_res{$bn}{removed}) ){ | ||||
|                         if ( defined($::XLATED{$bn}) ) { | ||||
|                             push (@remove_res,$::XLATED{$bn}); | ||||
|                         } else { | ||||
|                             push (@remove_res,$bn); | ||||
|                         } | ||||
|                         $ll_res{$bn}{removed} = 1; | ||||
|                         $ll_res{$bn}{not_done} = 0; | ||||
|                     } | ||||
|                 } | ||||
|                 if (@remove_res) { | ||||
| @@ -2086,8 +2244,12 @@ sub runrollupdate { | ||||
|                 } | ||||
|             } | ||||
|             if ($not_done) { | ||||
|                 sleep(20); | ||||
|                 $totalwait += 20; | ||||
|                 if ($::TEST) {  | ||||
|                     $not_done = 0;  | ||||
|                 } else { | ||||
|                     sleep(20); | ||||
|                     $totalwait += 20; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if ($not_done) {  | ||||
| @@ -2109,10 +2271,19 @@ sub runrollupdate { | ||||
|                         push (@error_nodes,$bn); | ||||
|                     } | ||||
|                 } | ||||
|                 open (RULOG, ">>$::LOGDIR/$::LOGFILE"); | ||||
|                 print RULOG "\n"; | ||||
|                 print RULOG localtime()." ERROR:  bringuptimeout exceeded for the following nodes: \n"; | ||||
|                 print RULOG join(",",@error_nodes); | ||||
|                 print RULOG "\n"; | ||||
|                 xCAT::Utils->setAppStatus(\@error_nodes,"RollingUpdate","ERROR_bringuptimeout_exceeded"); | ||||
|                 if ( defined($remaining_nodes[0]) ) { | ||||
|                 if ( @remaining_nodes ) { | ||||
|                   print RULOG localtime()." ERROR:  bringuptimeout exceeded for some nodes in a preceding bringuporder.  The following nodes will not be powered on: \n"; | ||||
|                   print RULOG join(",",@remaining_nodes); | ||||
|                   print RULOG "\n"; | ||||
|                   xCAT::Utils->setAppStatus(\@remaining_nodes,"RollingUpdate","ERROR_bringuptimeout_exceeded_for_previous_node"); | ||||
|                 } | ||||
|                 close (RULOG); | ||||
|             } | ||||
|             last; | ||||
|         } | ||||
| @@ -2237,7 +2408,16 @@ sub get_hostlist { | ||||
|         print RULOG localtime()." Hostlist:  $status_fields[22] \n"; | ||||
|         close (RULOG); | ||||
|     } | ||||
|     return $status_fields[22]; | ||||
|     my $return_list; | ||||
|     foreach my $machine (split( /\,/, $status_fields[22])) { | ||||
|        if ( defined($::XLATED{$machine}) ) { | ||||
|            $return_list = $return_list.','.$::XLATED{$machine}; | ||||
|        } else { | ||||
|            $return_list = $return_list.','.$machine; | ||||
|        } | ||||
|     } | ||||
|     $return_list =~ s/^,//; | ||||
|     return $return_list; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -2609,8 +2789,10 @@ sub llreconfig { | ||||
|     my $runlocal=0; | ||||
|     foreach my $m (@llms) { | ||||
|        my ($sm,$rest) = split(/\./,$m); | ||||
|        my $xlated_sm = $sm; | ||||
|        if ( defined ($::XLATED{$sm}) ) { $xlated_sm = $::XLATED{$sm}; } | ||||
|        if (xCAT::Utils->thishostisnot($m)) { | ||||
|            push(@llnodes, $sm) unless $have{$sm}++; | ||||
|            push(@llnodes, $xlated_sm) unless $have{$sm}++; | ||||
|        } else { | ||||
|            $runlocal=1; | ||||
|        } | ||||
| @@ -2634,7 +2816,7 @@ sub llreconfig { | ||||
|     if ( scalar(@llnodes) > 0 ) { | ||||
|         if ($::VERBOSE) { | ||||
|             open (RULOG, ">>$::LOGDIR/$::LOGFILE"); | ||||
|             print RULOG localtime()." Running command \'xdsh $llcms $llrms $cmd\'\n"; | ||||
|             print RULOG localtime()." Running command \'xdsh ".join(',',@llnodes)." $cmd\'\n"; | ||||
|             close (RULOG); | ||||
|         } | ||||
|         if ($::TEST) { | ||||
|   | ||||
| @@ -122,6 +122,23 @@ mutex_count=2 | ||||
| #      nodegroup_mutex=block2IO | ||||
| #      nodegroup_mutex=block3IO | ||||
|  | ||||
| # translatenames: | ||||
| # If your scheduler will be using names for nodes that are different from | ||||
| # xCAT node names (e.g. the scheduler is using a different administrative | ||||
| # network), you will need to tell xCAT how to translate from xCAT node names | ||||
| # to the node names registered with your scheduler. | ||||
| # | ||||
| # Syntax: | ||||
| #  translatenames=<xCAT_noderange>:/<pattern>/<replacement>/ | ||||
| # where <pattern> and <replacement> are perl regular expressions to | ||||
| # be performed on the node names in <xCAT_noderange>. | ||||
| # See the xcatdb man page for more details on using regular expressions. | ||||
| # Multiple translatenames statements are allowed.  If an xCAT nodename | ||||
| # exists in more than one xCAT_noderange, the last translated value | ||||
| # will be used. | ||||
| #translatenames=service:|bb(\d+)s(\d+)|bb($1)sn($2)| | ||||
| #translatenames=compute:/\z/-hf2/ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -68,6 +68,24 @@ updateall_nodes=compute | ||||
| updateall_nodecount=3 | ||||
|  | ||||
|  | ||||
| # translatenames: | ||||
| # If your scheduler will be using names for nodes that are different from | ||||
| # xCAT node names (e.g. the scheduler is using a different administrative | ||||
| # network), you will need to tell xCAT how to translate from xCAT node names | ||||
| # to the node names registered with your scheduler. | ||||
| # | ||||
| # Syntax: | ||||
| #  translatenames=<xCAT_noderange>:/<pattern>/<replacement>/ | ||||
| # where <pattern> and <replacement> are perl regular expressions to | ||||
| # be performed on the node names in <xCAT_noderange>. | ||||
| # See the xcatdb man page for more details on using regular expressions. | ||||
| # Multiple translatenames statements are allowed.  If an xCAT nodename | ||||
| # exists in more than one xCAT_noderange, the last translated value | ||||
| # will be used. | ||||
| #translatenames=service:|bb(\d+)s(\d+)|bb($1)sn($2)| | ||||
| #translatenames=compute:/\z/-hf2/ | ||||
|  | ||||
|  | ||||
|  | ||||
| # Scheduler Feature values  | ||||
| #    Node feature values that will be changed in the scheduler during the | ||||
|   | ||||
| @@ -91,6 +91,23 @@ updategroup=ns11(c4lpar211-c4lpar214) | ||||
| #mutex=block2a,block2b,block2c | ||||
| #mutex=block3a,block3b,block3c | ||||
|  | ||||
| # translatenames: | ||||
| # If your scheduler will be using names for nodes that are different from | ||||
| # xCAT node names (e.g. the scheduler is using a different administrative | ||||
| # network), you will need to tell xCAT how to translate from xCAT node names | ||||
| # to the node names registered with your scheduler. | ||||
| # | ||||
| # Syntax: | ||||
| #  translatenames=<xCAT_noderange>:/<pattern>/<replacement>/ | ||||
| # where <pattern> and <replacement> are perl regular expressions to | ||||
| # be performed on the node names in <xCAT_noderange>. | ||||
| # See the xcatdb man page for more details on using regular expressions. | ||||
| # Multiple translatenames statements are allowed.  If an xCAT nodename | ||||
| # exists in more than one xCAT_noderange, the last translated value | ||||
| # will be used. | ||||
| #translatenames=service:|bb(\d+)s(\d+)|bb($1)sn($2)| | ||||
| #translatenames=compute:/\z/-hf2/ | ||||
|  | ||||
|  | ||||
|  | ||||
| # maxupdates:  Maximum number of updategroups that can be updated at one time  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user