-Implement a nodegrpch command

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4262 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
jbjohnso 2009-09-29 20:41:13 +00:00
parent 23e342ae7d
commit 6bc4a63848
2 changed files with 229 additions and 78 deletions

View File

@ -1199,9 +1199,16 @@ sub setAttribs
{
$newpairs{$_} = $keypairs{$_};
}
my $needinsert=0;
for my $col (keys %$elems)
{
$newpairs{$col} = $$elems{$col};
$newpairs{$col} = $$elems{$col};
if (defined $newpairs{$col} and not $newpairs{$col} eq "") {
$needinsert=1;
}
}
unless ($needinsert) { #Don't bother inserting truly blank lines
return;
}
foreach (keys %newpairs) {
#$cols .= $_ . ","; # mysql changes

View File

@ -37,6 +37,7 @@ sub handled_commands
tabdump => "tabutils",
tabrestore => "tabutils",
tabch => "tabutils", # not implemented yet
nodegrpch => "tabutils",
nodech => "tabutils",
nodeadd => "tabutils",
noderm => "tabutils",
@ -104,7 +105,11 @@ sub process_request
{
return nodech($nodes, $args, $callback, 1);
}
elsif ($command eq "nodech" or $command eq "nodech")
elsif ($command eq "nodegrpch" or $command eq "chnodegrp")
{
return nodech($nodes, $args, $callback, "groupch");
}
elsif ($command eq "nodech" or $command eq "chnode")
{
return nodech($nodes, $args, $callback, 0);
}
@ -550,12 +555,127 @@ sub getTableColumn {
return split /\./,$string,2;
}
# sub groupch
# {
# my $args = shift;
# my $nodech_usage = sub
# {
# my $exitcode = shift @_;
# my $cmdname = "groupch";
# my %rsp;
# push @{$rsp{data}}, "Usage: $cmdname <group1,group2,...> table.column=value [...]";
# push @{$rsp{data}}, " $cmdname {-v | --version}";
# push @{$rsp{data}}, " $cmdname [-? | -h | --help]";
# if ($exitcode) { $rsp{errorcode} = $exitcode; }
# $callback->(\%rsp);
# };
# my @args = @{$args};
# unless (scalar @args >= 2) {
# $nodech_usage->(1);
# return;
# }
# my @groups = split /,/,shift @args;
# foreach (@args)
# {
# # if ($deletemode)
# # {
# # if (m/[=\.]/) # in delete mode they can only specify tables names
# # {
# # $callback->({error => [". and = not valid in delete mode."],errorcode=>1});
# # next;
# # }
# # $tables{$_} = 1;
# # next;
# # }
# unless (m/=/ or m/!~/)
# {
# $callback->({error => ["Malformed argument $_ ignored."],errorcode=>1});
# next;
# }
# my $stable;
# my $scolumn;
# #Check for selection criteria
# if (m/^[^=]*==/) {
# ($temp,$value)=split /==/,$_,2;
# ($stable,$scolumn)=getTableColumn($temp);
# $criteria{$stable}->{$scolumn}=[$value,'match'];
# next; #Is a selection criteria, not an assignment specification
# } elsif (m/^[^=]*!=/) {
# ($temp,$value)=split /!=/,$_,2;
# ($stable,$scolumn)=getTableColumn($temp);
# $criteria{$stable}->{$scolumn}=[$value,'natch'];
# next; #Is a selection criteria, not an assignment specification
# } elsif (m/^[^=]*=~/) {
# ($temp,$value)=split /=~/,$_,2;
# ($stable,$scolumn)=getTableColumn($temp);
# $value =~ s/^\///;
# $value =~ s/\/$//;
# $criteria{$stable}->{$scolumn}=[$value,'regex'];
# next; #Is a selection criteria, not an assignment specification
# } elsif (m/^[^=]*!~/) {
# ($temp,$value)=split /!~/,$_,2;
# ($stable,$scolumn)=getTableColumn($temp);
# $value =~ s/^\///;
# $value =~ s/\/$//;
# $criteria{$stable}->{$scolumn}=[$value,'negex'];
# next; #Is a selection criteria, not an assignment specification
# }
# #Now definitely an assignment
#
# ($temp, $value) = split('=', $_, 2);
# $value =~ s/^@//; #Allow the =@ operator to exist for an unambiguous assignmenet operator
# #So before, table.column==value meant set to =value, now it would be matching value
# #the new way would be table.column=@=value to be unambiguous
# #now a value like '@hi' would be set with table.column=@@hi
# if ($value eq '') { #If blank, force a null entry to override group settings
# $value = '|^.*$||';
# }
# my $op = '=';
# if ($temp =~ /,$/)
# {
# $op = ',=';
# chop($temp);
# }
# elsif ($temp =~ /\^$/)
# {
# $op = '^=';
# chop($temp);
# }
# my $table;
# if ($shortnames{$temp})
# {
# ($table, $column) = @{$shortnames{$temp}};
# }
# else
# {
# ($table, $column) = split('\.', $temp, 2);
# }
# unless (grep /$column/,@{$xCAT::Schema::tabspec{$table}->{cols}}) {
# $callback->({error=>"$table.$column not a valid table.column description",errorcode=>[1]});
# return;
# }
# # Keep a list of the value/op pairs, in case there is more than 1 per table.column
# #$tables{$table}->{$column} = [$value, $op];
# push @{$tables{$table}->{$column}}, ($value, $op);
# }
# }
sub nodech
{
my $nodes = shift;
my $args = shift;
my $callback = shift;
my $addmode = shift;
my $groupmode;
if ($addmode eq "groupch") {
$addmode = 0;
$groupmode=1;
}
my $VERSION;
my $HELP;
my $deletemode;
@ -566,10 +686,13 @@ sub nodech
{
my $exitcode = shift @_;
my $addmode = shift @_;
my $cmdname = $addmode ? 'nodeadd' : 'nodech';
my $groupmode = shift @_;
my $cmdname = $addmode ? 'nodeadd' : ($groupmode ? 'nodegrpch' : 'nodech');
my %rsp;
if ($addmode) {
push @{$rsp{data}}, "Usage: $cmdname <noderange> groups=<groupnames> [table.column=value] [...]";
} elsif ($groupmode) {
push @{$rsp{data}}, "Usage: $cmdname <group1,group2,...> [table.column=value] [...]";
} else {
push @{$rsp{data}}, "Usage: $cmdname <noderange> table.column=value [...]";
push @{$rsp{data}}, " $cmdname {-d | --delete} <noderange> <table> [...]";
@ -588,13 +711,13 @@ sub nodech
my %options = ('h|?|help' => \$HELP, 'v|version' => \$VERSION);
if (!$addmode) { $options{'d|delete'} = \$deletemode; }
if (!GetOptions(%options)) {
$nodech_usage->(1, $addmode);
$nodech_usage->(1, $addmode,$groupmode);
return;
}
# Help
if ($HELP) {
$nodech_usage->(0, $addmode);
$nodech_usage->(0, $addmode,$groupmode);
return;
}
@ -612,6 +735,7 @@ sub nodech
# do not exist yet. The nodech cmd is linked to xcatclient, so its noderange is
# put in $nodes instead of $args.
if (scalar(@ARGV) < (1+$addmode)) { $nodech_usage->(1, $addmode); return; }
my @groups;
if ($addmode)
{
@ -621,6 +745,8 @@ sub nodech
$callback->({error => "No noderange to add.\n",errorcode=>1});
return;
}
} elsif ($groupmode) {
@groups = split /,/, shift @ARGV;
}
my $column;
my $value;
@ -753,89 +879,107 @@ sub nodech
my $tabhdl = xCAT::Table->new($tab, -create => 1, -autocommit => 0);
if ($tabhdl)
{
foreach (@$nodes)
if ($deletemode)
{
if ($deletemode)
foreach (@$nodes)
{
$tabhdl->delEntries({'node' => $_});
}
else
{
}
else
{
#$tabhdl->setNodeAttribs($_,$tables{$tab});
my %uhsh;
my $node = $_;
foreach (keys %{$tables{$tab}}) # for each column specified for this table
{
#my $op = $tables{$tab}->{$_}->[1];
#my $val = $tables{$tab}->{$_}->[0];
my @valoppairs = @{$tables{$tab}->{$_}}; #Deep copy
while (scalar(@valoppairs)) { # alternating list of value and op for this table.column
my $val = shift @valoppairs;
my $op = shift @valoppairs;
my $key = $_;
# When changing the groups of the node, check whether the new group
# is a dynamic group.
if (($key eq 'groups') && ($op eq '=')) {
if (scalar(@grplist) == 0) { # Do not call $grptab->getAllEntries for each node, performance issue.
$grptab = xCAT::Table->new('nodegroup');
if ($grptab) {
@grplist = @{$grptab->getAllEntries()};
}
#$tabhdl->setNodeAttribs($_,$tables{$tab});
my %uhsh;
my $node = $_;
foreach (keys %{$tables{$tab}}) # for each column specified for this table
{
#my $op = $tables{$tab}->{$_}->[1];
#my $val = $tables{$tab}->{$_}->[0];
my @valoppairs = @{$tables{$tab}->{$_}}; #Deep copy
while (scalar(@valoppairs)) { # alternating list of value and op for this table.column
my $val = shift @valoppairs;
my $op = shift @valoppairs;
my $key = $_;
# When changing the groups of the node, check whether the new group
# is a dynamic group.
if (($key eq 'groups') && ($op eq '=')) {
if (scalar(@grplist) == 0) { # Do not call $grptab->getAllEntries for each node, performance issue.
$grptab = xCAT::Table->new('nodegroup');
if ($grptab) {
@grplist = @{$grptab->getAllEntries()};
}
my @grps = split(/,/, $val);
foreach my $grp (@grps) {
foreach my $grpdef_ref (@grplist) {
my %grpdef = %$grpdef_ref;
if (($grpdef{'groupname'} eq $grp) && ($grpdef{'grouptype'} eq 'dynamic')) {
my %rsp;
$rsp{data}->[0] = "nodegroup $grp is a dynamic node group, should not add a node into a dynamic node group statically.\n";
$callback->(\%rsp);
}
}
my @grps = split(/,/, $val);
foreach my $grp (@grps) {
foreach my $grpdef_ref (@grplist) {
my %grpdef = %$grpdef_ref;
if (($grpdef{'groupname'} eq $grp) && ($grpdef{'grouptype'} eq 'dynamic')) {
my %rsp;
$rsp{data}->[0] = "nodegroup $grp is a dynamic node group, should not add a node into a dynamic node group statically.\n";
$callback->(\%rsp);
}
}
}
if ($op eq '=') {
$uhsh{$key} = $val;
}
elsif ($op eq ',=') { #splice assignment
my $curval = $uhsh{$key}; # in case it was already set
if (!defined($curval)) {
my $cent = $tabhdl->getNodeAttribs($node, [$key]);
if ($cent) { $curval = $cent->{$key}; }
}
if ($curval) {
my @vals = split(/,/, $curval);
unless (grep /^$val$/, @vals) {
@vals = (@vals, $val);
my $newval = join(',', @vals);
$uhsh{$key} = $newval;
}
} else {
$uhsh{$key} = $val;
}
}
elsif ($op eq '^=') {
my $curval = $uhsh{$key}; # in case it was already set
if (!defined($curval)) {
my $cent = $tabhdl->getNodeAttribs($node, [$key]);
if ($cent) { $curval = $cent->{$key}; }
}
if ($curval) {
my @vals = split(/,/, $curval);
if (grep /^$val$/, @vals) { #only bother if there
@vals = grep(!/^$val$/, @vals);
my $newval = join(',', @vals);
$uhsh{$key} = $newval;
}
} #else, what they asked for is the case alredy
}
} # end of while @valoppairs
} # end of foreach column specified for this table
}
if ($op eq '=') {
$uhsh{$key} = $val;
}
elsif ($op eq ',=') { #splice assignment
my $curval = $uhsh{$key}; # in case it was already set
if (!defined($curval)) {
my $cent = $tabhdl->getNodeAttribs($node, [$key]);
if ($cent) { $curval = $cent->{$key}; }
}
if ($curval) {
my @vals = split(/,/, $curval);
unless (grep /^$val$/, @vals) {
@vals = (@vals, $val);
my $newval = join(',', @vals);
$uhsh{$key} = $newval;
}
} else {
$uhsh{$key} = $val;
}
}
elsif ($op eq '^=') {
my $curval = $uhsh{$key}; # in case it was already set
if (!defined($curval)) {
my $cent = $tabhdl->getNodeAttribs($node, [$key]);
if ($cent) { $curval = $cent->{$key}; }
}
if ($curval) {
my @vals = split(/,/, $curval);
if (grep /^$val$/, @vals) { #only bother if there
@vals = grep(!/^$val$/, @vals);
my $newval = join(',', @vals);
$uhsh{$key} = $newval;
}
} #else, what they asked for is the case alredy
}
} # end of while @valoppairs
} # end of foreach column specified for this table
if (keys %uhsh)
{
my @rc = $tabhdl->setNodeAttribs($node, \%uhsh);
if (keys %uhsh)
{
if ($groupmode) {
my $nodekey = "node";
if (defined $xCAT::Schema::tabspec{$tab}->{nodecol}) {
$nodekey = $xCAT::Schema::tabspec{$tab}->{nodecol}
}
my %clrhash; #First, we prepare to clear all nodes of their overrides on these columns
foreach (keys %uhsh) {
if ($_ eq $nodekey) { next; } #skip attempts to manipulate 'node' type columns in a groupch
$clrhash{$_}="";
}
foreach my $group (@groups) {
$tabhdl->setAttribs({node=>$group},\%uhsh);
$nodes = [noderange($group)];
unless (scalar @$nodes) { next; }
$tabhdl->setNodesAttribs($nodes,\%clrhash);
}
} else {
my @rc = $tabhdl->setNodesAttribs($nodes, \%uhsh);
if (not defined($rc[0]))
{
$callback->({error => "DB error " . $rc[1],errorcode=>1});