2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-21 15:18:19 +00:00
Files
xcat-core/xCAT-server/sbin/chtab
T
Vinícius Ferrão 06a3f486c7 fix(chtab): report a table that chtab -d cannot open
chtab -d called delEntries on each table that it named without a check
that the table opened. A table name that xCAT does not know made chtab
die after it had deleted the rows of the tables named before it. The
error was "Can't call method delEntries on an undefined value".

The delete moves to xCAT::TableUtils->delete_rows, which opens every
named table first. When a table does not open, it deletes no row and
returns the table name. chtab -d reports that table with the error of
the update form.
2026-10-14 13:14:42 -03:00

178 lines
4.7 KiB
Perl
Executable File

#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use xCAT::Table;
use xCAT::TableUtils;
use xCAT::NodeRange;
use Getopt::Long;
use strict;
#This or something like this must always be available and not depend on server
#Otherwise, can't set things to let server run in the first place
#
sub usage {
print "Usage:\n";
print " To add or update rows for tables:
chtab keycolname=keyvalue[,keycolname=keyvalue...] tablename.colname=newvalue [tablename.colname=newvalue...]\n";
print " To delete rows from tables:
chtab -d|--delete keycolname=keyvalue[,keycolname=keyvalue...] tablename [tablename...]\n";
print " To display usage and other information:
chtab [-h|--help|-v|--Version]\n\n";
print " -d|--delete Delete the rows from a list of tables.
-v|--version Display the version of this command.
-h|--help Display this usage information.
keycolname=keyvalue a column name-and-value pair that identifies the rows in a table to be changed.
tablename.colname=newvalue the new value for the specified row and column of the table.\n";
}
my %tables;
# options can be bundled up like -vV
Getopt::Long::Configure("bundling");
$Getopt::Long::ignorecase = 0;
# parse the options
if (!GetOptions(
'd|delete' => \$::DELETE,
'h|help' => \$::HELP,
'v|version' => \$::VERSION,))
{
&usage;
exit(1);
}
# display the usage if -h or --help is specified
if ($::HELP) { &usage; exit(0); }
# display the version statement if -v or --verison is specified
if ($::VERSION)
{
my $version = xCAT::Utils->Version();
print "chtab $version\n";
exit(0);
}
my $target = shift @ARGV;
unless ($target) {
usage;
exit(1);
}
my $current_userid = getpwuid($>);
if ($current_userid ne "root")
{
print "WARNING: chtab bypasses xcatd and does not enforce xCAT policy tables. Consider using tabch instead.\n";
}
my %keyhash = ();
my @keypairs = split(/,/, $target);
if ($keypairs[0] !~ /([^\.\=]+)\.([^\.\=]+)\=(.+)/) {
foreach (@keypairs) {
m/(.*)=(.*)/;
my $key = $1;
my $val = $2;
if (!defined($key) || !defined($val)) {
print "Incorrect argument \"$_\".\n";
usage;
exit(1);
}
$keyhash{$key} = $val;
}
} else {
unshift(@ARGV, $target);
}
if ($::DELETE) {
#delete option is specified
my @tables_to_del = @ARGV;
if (@tables_to_del == 0) {
print "Missing table name.\n";
usage;
exit(1);
}
my $missing = xCAT::TableUtils->delete_rows(\%keyhash, @tables_to_del);
if (defined($missing)) {
print "Table $missing does not exist.\n";
exit(1);
}
}
else {
#update or create option
my %tableupdates;
for (@ARGV) {
my $temp;
my $table;
my $column;
my $value;
($table, $temp) = split('\.', $_, 2);
#try to create the entry if it doesn't exist
unless ($tables{$table}) {
my $tab = xCAT::Table->new($table, -create => 1, -autocommit => 0);
if ($tab) {
$tables{$table} = $tab;
} else {
print "Table $table does not exist.\n";
exit(1);
}
}
#splice assignment
if (grep /\+=/, $temp) {
($column, $value) = split('\+=', $temp, 2);
#grab the current values to check against
my ($attrHash) = $tables{$table}->getAttribs(\%keyhash, $column);
my @existing = split(",", $attrHash->{$column});
#if it has values, merge the new and old ones together so no dupes
if (@existing) {
my @values = split(",", $value);
my %seen = ();
my @uniq = ();
my $item;
foreach $item (@existing, @values) {
unless ($seen{$item}) {
# if we get here, we have not seen it before
$seen{$item} = 1;
push(@uniq, $item);
}
}
$value = join(",", @uniq);
}
}
#normal non-splicing assignment
else {
($column, $value) = split("=", $temp, 2);
}
$tableupdates{$table}{$column} = $value;
}
#commit all the changes
foreach (keys %tables) {
if (exists($tableupdates{$_})) {
my $rc = $tables{$_}->setAttribs(\%keyhash, \%{ $tableupdates{$_} });
if ($rc) {
$::exitcode = 1;
}
}
$tables{$_}->commit;
}
}
if ($::exitcode) {
exit $::exitcode;
}