Cleaned up the client code and added man pages for tabdump and tabrestore
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@477 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
bc7fc0742d
commit
8c057025b8
@ -27,19 +27,20 @@ use Storable qw(dclone);
|
||||
my $xcathost='localhost:3001';
|
||||
my $plugins_dir;
|
||||
my %resps;
|
||||
my $EXITCODE; # save the bitmask of all exit codes returned by calls to handle_response()
|
||||
1;
|
||||
|
||||
|
||||
#################################
|
||||
# submit_request will take an xCAT command and pass it to the xCAT
|
||||
# server for execution.
|
||||
#
|
||||
#
|
||||
# If the XCATBYPASS env var is set, the connection to the server/daemon
|
||||
# will be bypassed and the plugin will be called directly. If it is
|
||||
# set to one or more directories (separated by ":"), all perl modules
|
||||
# in those directories will be loaded in as plugins (for duplicate
|
||||
# commands, last one in wins). If it is set to any other value
|
||||
# (e.g. "yes", "default", whatever string you want) the default plugin
|
||||
# set to one or more directories (separated by ":"), all perl modules
|
||||
# in those directories will be loaded in as plugins (for duplicate
|
||||
# commands, last one in wins). If it is set to any other value
|
||||
# (e.g. "yes", "default", whatever string you want) the default plugin
|
||||
# directory /opt/xcat/lib/perl/xCAT_plugin will be used.
|
||||
#
|
||||
# Input:
|
||||
@ -54,12 +55,12 @@ my %resps;
|
||||
# }
|
||||
# Callback - A subroutine ref that will be called to process the output
|
||||
# from the plugin.
|
||||
#
|
||||
#
|
||||
# NOTE: The request hash will get converted to XML when passed to the
|
||||
# xcatd daemon, and will get converted back to a hash before being
|
||||
# passed to the plugin. The XMLin ForceArray option is used to
|
||||
# force all XML constructs to be arrays so that the plugin code
|
||||
# and callback routines can access the data consistently.
|
||||
# and callback routines can access the data consistently.
|
||||
# The input request and the response hash created by the plugin should
|
||||
# always create hashes with array values.
|
||||
#################################
|
||||
@ -72,6 +73,7 @@ sub submit_request {
|
||||
unless ($keyfile) { $keyfile = $ENV{HOME}."/.xcat/client-key.pem"; }
|
||||
unless ($certfile) { $certfile = $ENV{HOME}."/.xcat/client-cert.pem"; }
|
||||
unless ($cafile) { $cafile = $ENV{HOME}."/.xcat/ca.pem"; }
|
||||
$xCAT::Client::EXITCODE = 0; # clear out exit code before invoking the plugin
|
||||
|
||||
|
||||
# If XCATBYPASS is set, invoke the plugin process_request method directly
|
||||
@ -128,12 +130,6 @@ sub submit_request {
|
||||
if ($response =~ m/<\/xcatresponse>/) {
|
||||
$rsp = XMLin($response,SuppressEmpty=>undef,ForceArray=>1);
|
||||
$response='';
|
||||
if ($rsp->{warning}) {
|
||||
printf ("Warning: ".$rsp->{warning}->[0]."\n");
|
||||
}
|
||||
if ($rsp->{error}) {
|
||||
printf "Error: ". $rsp->{error}->[0]."\n";
|
||||
}
|
||||
$callback->($rsp);
|
||||
if ($rsp->{serverdone}) {
|
||||
last;
|
||||
@ -143,10 +139,10 @@ sub submit_request {
|
||||
|
||||
###################################
|
||||
# scan_plugins
|
||||
# will load all plugin perl modules and build a list of supported
|
||||
# will load all plugin perl modules and build a list of supported
|
||||
# commands
|
||||
#
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# Will eventually move to using common source....
|
||||
###################################
|
||||
sub scan_plugins {
|
||||
@ -184,9 +180,9 @@ sub scan_plugins {
|
||||
|
||||
###################################
|
||||
# plugin_command
|
||||
# will invoke the correct plugin
|
||||
# will invoke the correct plugin
|
||||
#
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# Will eventually move to using common source....
|
||||
###################################
|
||||
sub plugin_command {
|
||||
@ -333,7 +329,7 @@ sub plugin_command {
|
||||
# do_request
|
||||
# called from a plugin to execute another xCAT plugin command internally
|
||||
#
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# NOTE: This is copied from xcatd (last merge 10/3/07).
|
||||
# Will eventually move to using common source....
|
||||
###################################
|
||||
sub do_request {
|
||||
@ -402,7 +398,160 @@ sub build_response {
|
||||
|
||||
|
||||
|
||||
}
|
||||
} # end of submit_request()
|
||||
|
||||
|
||||
|
||||
##########################################
|
||||
# handle_response is a default callback that can be passed into submit_response()
|
||||
# It is invoked repeatedly by submit_response() to print out the data returned by
|
||||
# the plugin.
|
||||
#
|
||||
# The normal flow is:
|
||||
# -> client cmd (e.g. nodels, which is just a link to xcatclient)
|
||||
# -> xcatclient
|
||||
# -> submit_request()
|
||||
# -> send xml request to xcatd
|
||||
# -> xcatd
|
||||
# -> process_request() of the plugin
|
||||
# <- plugin callback
|
||||
# <- xcatd
|
||||
# <- xcatd sends xml response to client
|
||||
# <- submit_request() read response
|
||||
# <- handle_response() prints responses and saves exit codes
|
||||
# <- xcatclient gets exit code and exits
|
||||
#
|
||||
# But in XCATBYPASS mode, the flow is:
|
||||
# -> client cmd (e.g. nodels, which is just a link to xcatclient)
|
||||
# -> xcatclient
|
||||
# -> submit_request()
|
||||
# -> process_request() of the plugin
|
||||
# <- handle_response() prints responses and saves exit codes
|
||||
# <- xcatclient gets exit code and exits
|
||||
#
|
||||
# Format of the response hash:
|
||||
# {data => [ 'data str1', 'data str2', '...' ] }
|
||||
#
|
||||
# Results are printed as:
|
||||
# data str1
|
||||
# data str2
|
||||
#
|
||||
# or:
|
||||
# {data => [ {desc => [ 'desc1' ],
|
||||
# contents => [ 'contents1' ] },
|
||||
# {desc => [ 'desc2 ],
|
||||
# contents => [ 'contents2' ] }
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: In this format, only the data array can have more than one
|
||||
# element. All other arrays are assumed to be a single element.
|
||||
# Results are printed as:
|
||||
# desc1: contents1
|
||||
# desc2: contents2
|
||||
#
|
||||
# or:
|
||||
# {node => [ {name => ['node1'],
|
||||
# data => [ {desc => [ 'node1 desc' ],
|
||||
# contents => [ 'node1 contents' ] } ] },
|
||||
# {name => ['node2'],
|
||||
# data => [ {desc => [ 'node2 desc' ],
|
||||
# contents => [ 'node2 contents' ] } ] },
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: Only the node array can have more than one element.
|
||||
# All other arrays are assumed to be a single element.
|
||||
#
|
||||
# This was generated from the corresponding XML:
|
||||
# <xcatrequest>
|
||||
# <node>
|
||||
# <name>node1</name>
|
||||
# <data>
|
||||
# <desc>node1 desc</desc>
|
||||
# <contents>node1 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# <node>
|
||||
# <name>node2</name>
|
||||
# <data>
|
||||
# <desc>node2 desc</desc>
|
||||
# <contents>node2 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# </xcatrequest>
|
||||
#
|
||||
# Results are printed as:
|
||||
# node_name: desc: contents
|
||||
##########################################
|
||||
sub handle_response {
|
||||
my $rsp = shift;
|
||||
# Handle errors
|
||||
if ($rsp->{errorcode}) {
|
||||
if (ref($rsp->{errorcode}) eq 'ARRAY') { foreach my $ecode (@{$rsp->{errorcode}}) { $xCAT::Client::EXITCODE |= $ecode; } }
|
||||
else { $xCAT::Client::EXITCODE |= $rsp->{errorcode}; } # assume it is a non-reference scalar
|
||||
}
|
||||
if ($rsp->{warning}) {
|
||||
if (ref($rsp->{warning}) eq 'ARRAY') { print ("Warning: " . $rsp->{warning}->[0] . "\n"); }
|
||||
else { print ("Warning: ".$rsp->{warning}."\n"); }
|
||||
}
|
||||
if ($rsp->{error}) {
|
||||
if (ref($rsp->{error}) eq 'ARRAY') { print ("Error: " . $rsp->{error}->[0] . "\n"); }
|
||||
else { print ("Error: ".$rsp->{error}."\n"); }
|
||||
}
|
||||
|
||||
# Handle {node} structure
|
||||
if ($rsp->{node}) {
|
||||
my $nodes=($rsp->{node});
|
||||
my $node;
|
||||
foreach $node (@$nodes) {
|
||||
my $desc=$node->{name}->[0];
|
||||
if ($node->{errorcode}) {
|
||||
if (ref($node->{errorcode}) eq 'ARRAY') { foreach my $ecode (@{$node->{errorcode}}) { $xCAT::Client::EXITCODE |= $ecode; } }
|
||||
else { $xCAT::Client::EXITCODE |= $node->{errorcode}; } # assume it is a non-reference scalar
|
||||
}
|
||||
if ($node->{data}) {
|
||||
if (ref(\($node->{data}->[0])) eq 'SCALAR') {
|
||||
$desc=$desc.": ".$node->{data}->[0];
|
||||
} else {
|
||||
if ($node->{data}->[0]->{desc}) {
|
||||
$desc=$desc.": ".$node->{data}->[0]->{desc}->[0];
|
||||
}
|
||||
if ($node->{data}->[0]->{contents}) {
|
||||
$desc="$desc: ".$node->{data}->[0]->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Handle {data} structure with no nodes
|
||||
if ($rsp->{data}) {
|
||||
my $data=($rsp->{data});
|
||||
my $data_entry;
|
||||
foreach $data_entry (@$data) {
|
||||
my $desc;
|
||||
if (ref(\($data_entry)) eq 'SCALAR') {
|
||||
$desc=$data_entry;
|
||||
} else {
|
||||
if ($data_entry->{desc}) {
|
||||
$desc=$data_entry->{desc}->[0];
|
||||
}
|
||||
if ($data_entry->{contents}) {
|
||||
if ($desc) {
|
||||
$desc="$desc: ".$data_entry->{contents}->[0];
|
||||
} else {
|
||||
$desc=$data_entry->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} # end of handle_response
|
||||
|
||||
|
||||
|
||||
|
@ -1,175 +1,44 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
|
||||
}
|
||||
|
||||
# Used as a standard client cmd that can be used for many of the xcat cmds.
|
||||
# It grabs the arguments, noderange, and stdin and then submits the request to
|
||||
# xcatd and waits for responses. Most of the client/server communication is
|
||||
# contained in Client.pm.
|
||||
|
||||
# To use this, sym link your cmd name to this script.
|
||||
|
||||
BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; }
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use Cwd;
|
||||
use IO::Socket::SSL;
|
||||
use IO::Socket::INET;
|
||||
#use IO::Socket::SSL;
|
||||
#use IO::Socket::INET;
|
||||
use File::Basename;
|
||||
use Data::Dumper;
|
||||
use xCAT::Client submit_request;
|
||||
#use Data::Dumper;
|
||||
use xCAT::Client;
|
||||
|
||||
my $bname = basename($0);
|
||||
|
||||
#########################################
|
||||
# Main
|
||||
# Build hash and submit request
|
||||
#########################################
|
||||
|
||||
my $exitcode = 0; #var to store exit code that results from responses
|
||||
my $cmdref;
|
||||
if($bname =~ /xcatclient/) {
|
||||
$cmdref->{command}->[0]=shift @ARGV;
|
||||
} elsif ($bname =~/^(.*$)/) {
|
||||
$cmdref->{command}->[0] = $1;
|
||||
} else {
|
||||
printf("Bad usage\n");
|
||||
exit(1);
|
||||
}
|
||||
if ($bname =~ /xcatclient/) { $cmdref->{command}->[0]=shift @ARGV; } # xcatclient was invoked directly and the 1st arg is cmd name that is used to locate the plugin
|
||||
else { $cmdref->{command}->[0] = $bname; } # the cmd was sym linked to xcatclient
|
||||
$cmdref->{cwd}->[0] = cwd();
|
||||
|
||||
if (-p STDIN) {
|
||||
my $data;
|
||||
while ( <STDIN> ) {
|
||||
$data.=$_;
|
||||
}
|
||||
while ( <STDIN> ) { $data.=$_; }
|
||||
$cmdref->{stdin}->[0]=$data;
|
||||
}
|
||||
|
||||
# Consider the 1st non-hyphen arg to be the noderange. All others (before and after) go on the arg list.
|
||||
my $arg=shift(@ARGV);
|
||||
while ($arg =~ /^-/) {
|
||||
push (@{$cmdref->{arg}}, $arg);
|
||||
$arg=shift(@ARGV);
|
||||
}
|
||||
if ($arg ne "NO_NODE_RANGE") {
|
||||
if ($arg ne "NO_NODE_RANGE") {
|
||||
$cmdref->{noderange}->[0]=$arg;
|
||||
}
|
||||
foreach (@ARGV) { push (@{$cmdref->{arg}}, $_ ); }
|
||||
#$cmdref->{arg}=\@ARGV;
|
||||
xCAT::Client::submit_request($cmdref,\&handle_response);
|
||||
exit $exitcode;
|
||||
|
||||
|
||||
##########################################
|
||||
# handle_response is the callback that is
|
||||
# invoked to print out the data returned by
|
||||
# the plugin.
|
||||
#
|
||||
# Format of the response hash:
|
||||
# {data => [ 'data str1', 'data str2', '...' ] }
|
||||
#
|
||||
# Results are printed as:
|
||||
# data str1
|
||||
# data str2
|
||||
#
|
||||
# or:
|
||||
# {data => [ {desc => [ 'desc1' ],
|
||||
# contents => [ 'contents1' ] },
|
||||
# {desc => [ 'desc2 ],
|
||||
# contents => [ 'contents2' ] }
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: In this format, only the data array can have more than one
|
||||
# element. All other arrays are assumed to be a single element.
|
||||
# Results are printed as:
|
||||
# desc1: contents1
|
||||
# desc2: contents2
|
||||
#
|
||||
# or:
|
||||
# {node => [ {name => ['node1'],
|
||||
# data => [ {desc => [ 'node1 desc' ],
|
||||
# contents => [ 'node1 contents' ] } ] },
|
||||
# {name => ['node2'],
|
||||
# data => [ {desc => [ 'node2 desc' ],
|
||||
# contents => [ 'node2 contents' ] } ] },
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: Only the node array can have more than one element.
|
||||
# All other arrays are assumed to be a single element.
|
||||
#
|
||||
# This was generated from the corresponding HTML:
|
||||
# <xcatrequest>
|
||||
# <node>
|
||||
# <name>node1</name>
|
||||
# <data>
|
||||
# <desc>node1 desc</desc>
|
||||
# <contents>node1 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# <node>
|
||||
# <name>node2</name>
|
||||
# <data>
|
||||
# <desc>node2 desc</desc>
|
||||
# <contents>node2 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# </xcatrequest>
|
||||
#
|
||||
# Results are printed as:
|
||||
# node_name: desc: contents
|
||||
##########################################
|
||||
sub handle_response {
|
||||
my $rsp = shift;
|
||||
# Handle {node} structure
|
||||
if ($rsp->{errorcode}) {
|
||||
foreach my $ecode (@{$rsp->{errorcode}}) {
|
||||
$exitcode |= $ecode;
|
||||
}
|
||||
}
|
||||
if ($rsp->{node}) {
|
||||
my $nodes=($rsp->{node});
|
||||
my $node;
|
||||
foreach $node (@$nodes) {
|
||||
my $desc=$node->{name}->[0];
|
||||
if ($node->{errorcode}) {
|
||||
foreach my $ecode (@{$node->{errorcode}}) {
|
||||
$exitcode |= $ecode;
|
||||
}
|
||||
}
|
||||
if ($node->{data}) {
|
||||
if (ref(\($node->{data}->[0])) eq 'SCALAR') {
|
||||
$desc=$desc.": ".$node->{data}->[0];
|
||||
} else {
|
||||
if ($node->{data}->[0]->{desc}) {
|
||||
$desc=$desc.": ".$node->{data}->[0]->{desc}->[0];
|
||||
}
|
||||
if ($node->{data}->[0]->{contents}) {
|
||||
$desc="$desc: ".$node->{data}->[0]->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Handle {data} structure with no nodes
|
||||
if ($rsp->{data}) {
|
||||
my $data=($rsp->{data});
|
||||
my $data_entry;
|
||||
foreach $data_entry (@$data) {
|
||||
my $desc;
|
||||
if (ref(\($data_entry)) eq 'SCALAR') {
|
||||
$desc=$data_entry;
|
||||
} else {
|
||||
if ($data_entry->{desc}) {
|
||||
$desc=$data_entry->{desc}->[0];
|
||||
}
|
||||
if ($data_entry->{contents}) {
|
||||
if ($desc) {
|
||||
$desc="$desc: ".$data_entry->{contents}->[0];
|
||||
} else {
|
||||
$desc=$data_entry->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
push (@{$cmdref->{arg}}, @ARGV);
|
||||
|
||||
xCAT::Client::submit_request($cmdref,\&xCAT::Client::handle_response);
|
||||
exit $xCAT::Client::EXITCODE;
|
||||
|
@ -1,25 +1,32 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
# Used as a standard client cmd that can be used for xcat cmds that do not have
|
||||
# noderange as an argument. See xcatclient for additional documentation.
|
||||
|
||||
# To use this, sym link your cmd name to this script.
|
||||
|
||||
BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; }
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
use xCAT::Client;
|
||||
|
||||
#######################################
|
||||
# It handles the commands without noderanges.
|
||||
#######################################
|
||||
my $bname = basename($0);
|
||||
my $cmd;
|
||||
if($bname =~ /xcatclientnnr/) {
|
||||
$cmd = shift @ARGV;
|
||||
} elsif ($bname =~/^(.*$)/) {
|
||||
$cmd = $1;
|
||||
} else {
|
||||
printf("Bad usage\n");
|
||||
exit(1);
|
||||
my $cmdref;
|
||||
if ($bname =~ /xcatclientnnr/) { $cmdref->{command}->[0]=shift @ARGV; } # xcatclientnnr was invoked directly and the 1st arg is cmd name that is used to locate the plugin
|
||||
else { $cmdref->{command}->[0] = $bname; } # the cmd was sym linked to xcatclientnnr
|
||||
$cmdref->{cwd}->[0] = cwd();
|
||||
|
||||
if (-p STDIN) {
|
||||
my $data;
|
||||
while ( <STDIN> ) { $data.=$_; }
|
||||
$cmdref->{stdin}->[0]=$data;
|
||||
}
|
||||
exec("xcatclient $cmd NO_NODE_RANGE @ARGV 2>&1");
|
||||
#if (system("/usr/bin/xcatclient $cmd NO_NODE_RANGE @ARGV 2>&1") != 0) {
|
||||
# print "$cmd failed: $?\n";
|
||||
#}
|
||||
|
||||
#exit;
|
||||
push (@{$cmdref->{arg}}, @ARGV);
|
||||
|
||||
xCAT::Client::submit_request($cmdref,\&xCAT::Client::handle_response);
|
||||
exit $xCAT::Client::EXITCODE;
|
||||
|
||||
|
||||
|
45
xCAT-client-2.0/pods/man1/tabdump.1.pod
Normal file
45
xCAT-client-2.0/pods/man1/tabdump.1.pod
Normal file
@ -0,0 +1,45 @@
|
||||
=head1 NAME
|
||||
|
||||
B<tabdump> - display a database table in csv format.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
I<tabdump [table]>
|
||||
|
||||
I<tabdump [? | -h | --help]>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The tabdump command displays the header and all the rows of the specified table in csv format.
|
||||
Only one table can be specified. If no table is specified, the list of existing
|
||||
tables will be displayed.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
B<-?|-h|--help> Display usage message.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
0 The command completed successfully.
|
||||
|
||||
1 An error has occurred.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
1. To display the contents of the site table:
|
||||
|
||||
I<tabdump site>
|
||||
|
||||
2. To see what tables exist in the xCAT database:
|
||||
|
||||
I<tabdump>
|
||||
|
||||
=head1 FILES
|
||||
|
||||
/opt/xcat/sbin/tabdump
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
This command is part of the xCAT software product.
|
||||
|
||||
|
50
xCAT-client-2.0/pods/man1/tabrestore.1.pod
Normal file
50
xCAT-client-2.0/pods/man1/tabrestore.1.pod
Normal file
@ -0,0 +1,50 @@
|
||||
=head1 NAME
|
||||
|
||||
B<tabrestore> - replaces the contents of an xCAT database table with the contents in a csv file.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
I<tabrestore table.csv>
|
||||
|
||||
I<tabrestore [? | -h | --help]>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The tabrestore command reads the contents of the specified file and puts its data
|
||||
in the corresponding table in the xCAT database. Any existing rows in that table
|
||||
are replaced. The file must be in csv format. It could be created by tabdump.
|
||||
Only one table can be specified.
|
||||
|
||||
This command can be used to copy the example table entries in /opt/xcat/share/xcat/templates/e1350
|
||||
into the xCAT database.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
B<-?|-h|--help> Display usage message.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
0 The command completed successfully.
|
||||
|
||||
1 An error has occurred.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
1. To put rows into the mp table:
|
||||
|
||||
I<tabrestore mp.csv>
|
||||
|
||||
The file mp.csv could contain something like:
|
||||
|
||||
#node,mpa,id,comments,disable
|
||||
"blade","|\D+(\d+)|amm(($1-1)/14+1)|","|\D+(\d+)|(($1-1)%14+1)|",,
|
||||
|
||||
=head1 FILES
|
||||
|
||||
/opt/xcat/sbin/tabrestore
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
This command is part of the xCAT software product.
|
||||
|
||||
|
@ -1,166 +1,46 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
#Just like xcatclient, but needs to read a file in and pass it as $request->data
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
|
||||
}
|
||||
|
||||
# Just like xcatclient, but needs to read a file in and pass it as $request->data
|
||||
|
||||
BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; }
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use IO::Socket::SSL;
|
||||
use IO::Socket::INET;
|
||||
use File::Basename;
|
||||
use Data::Dumper;
|
||||
use xCAT::Client submit_request;
|
||||
my $bname = basename($0);
|
||||
use xCAT::Client;
|
||||
use Getopt::Long;
|
||||
|
||||
#########################################
|
||||
# Main
|
||||
# Build hash and submit request
|
||||
#########################################
|
||||
sub usage {
|
||||
print "Usage: tabrestore <tablename>.csv\n";
|
||||
print " tabrestore [-?|-h|--help]\n";
|
||||
exit $_[0];
|
||||
}
|
||||
|
||||
#my $bname = basename($0);
|
||||
my $cmdref;
|
||||
my $exitcode=0;
|
||||
$cmdref->{command}->[0] = "tabrestore";
|
||||
|
||||
# Get the options
|
||||
my $HELP;
|
||||
if (!GetOptions('h|?|help' => \$HELP)) { usage(1); }
|
||||
my $arg=shift(@ARGV);
|
||||
while ($arg =~ /^-/) {
|
||||
push (@{$cmdref->{arg}}, $arg);
|
||||
$arg=shift(@ARGV);
|
||||
}
|
||||
unless ($arg) {
|
||||
printf("Usage: tabrestore [tablename].csv\n");
|
||||
exit(1);
|
||||
}
|
||||
unless ($arg) { usage(2); } # no filename specified
|
||||
|
||||
# Open the specified table file and put its contents in the data key
|
||||
my $filename = $arg;
|
||||
unless (-r $filename) {
|
||||
printf("Unable to open $arg for reading.\n");
|
||||
exit(1);
|
||||
}
|
||||
my $tabname = basename($filename);
|
||||
$tabname =~ s/\..*//;
|
||||
$cmdref->{table}->[0] = $tabname;
|
||||
my $fh;
|
||||
open($fh,$filename);
|
||||
unless (open($fh,$filename)) { print "Error: Unable to open $arg for reading.\n"; exit 3; }
|
||||
while (<$fh>) {
|
||||
push @{$cmdref->{data}},$_;
|
||||
}
|
||||
|
||||
foreach (@ARGV) { push (@{$cmdref->{arg}}, $_ ); }
|
||||
#$cmdref->{arg}=\@ARGV;
|
||||
xCAT::Client::submit_request($cmdref,\&handle_response);
|
||||
exit $exitcode;
|
||||
push (@{$cmdref->{arg}}, @ARGV); # get the rest of the arguments
|
||||
|
||||
|
||||
##########################################
|
||||
# handle_response is the callback that is
|
||||
# invoked to print out the data returned by
|
||||
# the plugin.
|
||||
#
|
||||
# Format of the response hash:
|
||||
# {data => [ 'data str1', 'data str2', '...' ] }
|
||||
#
|
||||
# Results are printed as:
|
||||
# data str1
|
||||
# data str2
|
||||
#
|
||||
# or:
|
||||
# {data => [ {desc => [ 'desc1' ],
|
||||
# contents => [ 'contents1' ] },
|
||||
# {desc => [ 'desc2 ],
|
||||
# contents => [ 'contents2' ] }
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: In this format, only the data array can have more than one
|
||||
# element. All other arrays are assumed to be a single element.
|
||||
# Results are printed as:
|
||||
# desc1: contents1
|
||||
# desc2: contents2
|
||||
#
|
||||
# or:
|
||||
# {node => [ {name => ['node1'],
|
||||
# data => [ {desc => [ 'node1 desc' ],
|
||||
# contents => [ 'node1 contents' ] } ] },
|
||||
# {name => ['node2'],
|
||||
# data => [ {desc => [ 'node2 desc' ],
|
||||
# contents => [ 'node2 contents' ] } ] },
|
||||
# :
|
||||
# ] }
|
||||
# NOTE: Only the node array can have more than one element.
|
||||
# All other arrays are assumed to be a single element.
|
||||
#
|
||||
# This was generated from the corresponding HTML:
|
||||
# <xcatrequest>
|
||||
# <node>
|
||||
# <name>node1</name>
|
||||
# <data>
|
||||
# <desc>node1 desc</desc>
|
||||
# <contents>node1 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# <node>
|
||||
# <name>node2</name>
|
||||
# <data>
|
||||
# <desc>node2 desc</desc>
|
||||
# <contents>node2 contents</contents>
|
||||
# </data>
|
||||
# </node>
|
||||
# </xcatrequest>
|
||||
#
|
||||
# Results are printed as:
|
||||
# node_name: desc: contents
|
||||
##########################################
|
||||
sub handle_response {
|
||||
my $rsp = shift;
|
||||
# Handle {node} structure
|
||||
if ($rsp->{node}) {
|
||||
my $nodes=($rsp->{node});
|
||||
my $node;
|
||||
foreach $node (@$nodes) {
|
||||
my $desc=$node->{name}->[0];
|
||||
if ($node->{data}) {
|
||||
if (ref(\($node->{data}->[0])) eq 'SCALAR') {
|
||||
$desc=$desc.": ".$node->{data}->[0];
|
||||
} else {
|
||||
if ($node->{data}->[0]->{desc}) {
|
||||
$desc=$desc.": ".$node->{data}->[0]->{desc}->[0];
|
||||
}
|
||||
if ($node->{data}->[0]->{contents}) {
|
||||
$desc="$desc: ".$node->{data}->[0]->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Handle {data} structure with no nodes
|
||||
if ($rsp->{error}) {
|
||||
$exitcode=1;
|
||||
}
|
||||
if ($rsp->{data}) {
|
||||
my $data=($rsp->{data});
|
||||
my $data_entry;
|
||||
foreach $data_entry (@$data) {
|
||||
my $desc;
|
||||
if (ref(\($data_entry)) eq 'SCALAR') {
|
||||
$desc=$data_entry;
|
||||
} else {
|
||||
if ($data_entry->{desc}) {
|
||||
$desc=$data_entry->{desc}->[0];
|
||||
}
|
||||
if ($data_entry->{contents}) {
|
||||
if ($desc) {
|
||||
$desc="$desc: ".$data_entry->{contents}->[0];
|
||||
} else {
|
||||
$desc=$data_entry->{contents}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($desc) {
|
||||
print "$desc\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xCAT::Client::submit_request($cmdref,\&xCAT::Client::handle_response);
|
||||
exit $xCAT::Client::EXITCODE;
|
167
xCAT-client-2.0/share/man/man1/tabdump.1
Normal file
167
xCAT-client-2.0/share/man/man1/tabdump.1
Normal file
@ -0,0 +1,167 @@
|
||||
.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sh \" Subsection heading
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
.de Vb \" Begin verbatim text
|
||||
.ft CW
|
||||
.nf
|
||||
.ne \\$1
|
||||
..
|
||||
.de Ve \" End verbatim text
|
||||
.ft R
|
||||
.fi
|
||||
..
|
||||
.\" Set up some character translations and predefined strings. \*(-- will
|
||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
||||
.\" double quote, and \*(R" will give a right double quote. | will give a
|
||||
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
|
||||
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
|
||||
.\" expand to `' in nroff, nothing in troff, for use with C<>.
|
||||
.tr \(*W-|\(bv\*(Tr
|
||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
||||
.ie n \{\
|
||||
. ds -- \(*W-
|
||||
. ds PI pi
|
||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
||||
. ds L" ""
|
||||
. ds R" ""
|
||||
. ds C` ""
|
||||
. ds C' ""
|
||||
'br\}
|
||||
.el\{\
|
||||
. ds -- \|\(em\|
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
'br\}
|
||||
.\"
|
||||
.\" If the F register is turned on, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.if \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. nr % 0
|
||||
. rr F
|
||||
.\}
|
||||
.\"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.hy 0
|
||||
.if n .na
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
. \" fudge factors for nroff and troff
|
||||
.if n \{\
|
||||
. ds #H 0
|
||||
. ds #V .8m
|
||||
. ds #F .3m
|
||||
. ds #[ \f1
|
||||
. ds #] \fP
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
|
||||
. ds #V .6m
|
||||
. ds #F 0
|
||||
. ds #[ \&
|
||||
. ds #] \&
|
||||
.\}
|
||||
. \" simple accents for nroff and troff
|
||||
.if n \{\
|
||||
. ds ' \&
|
||||
. ds ` \&
|
||||
. ds ^ \&
|
||||
. ds , \&
|
||||
. ds ~ ~
|
||||
. ds /
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
|
||||
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
|
||||
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
|
||||
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
|
||||
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
|
||||
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
|
||||
.\}
|
||||
. \" troff and (daisy-wheel) nroff accents
|
||||
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
|
||||
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
|
||||
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
|
||||
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
|
||||
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
|
||||
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
|
||||
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
|
||||
.ds ae a\h'-(\w'a'u*4/10)'e
|
||||
.ds Ae A\h'-(\w'A'u*4/10)'E
|
||||
. \" corrections for vroff
|
||||
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
|
||||
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
|
||||
. \" for low resolution devices (crt and lpr)
|
||||
.if \n(.H>23 .if \n(.V>19 \
|
||||
\{\
|
||||
. ds : e
|
||||
. ds 8 ss
|
||||
. ds o a
|
||||
. ds d- d\h'-1'\(ga
|
||||
. ds D- D\h'-1'\(hy
|
||||
. ds th \o'bp'
|
||||
. ds Th \o'LP'
|
||||
. ds ae ae
|
||||
. ds Ae AE
|
||||
.\}
|
||||
.rm #[ #] #H #V #F C
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "TABDUMP.1 1"
|
||||
.TH TABDUMP.1 1 "2008-02-13" "perl v5.8.8" "User Contributed Perl Documentation"
|
||||
.SH "NAME"
|
||||
\&\fBtabdump\fR \- display a database table in csv format.
|
||||
.SH "SYNOPSIS"
|
||||
.IX Header "SYNOPSIS"
|
||||
\&\fItabdump [table]\fR
|
||||
.PP
|
||||
\&\fItabdump [? | \-h | \-\-help]\fR
|
||||
.SH "DESCRIPTION"
|
||||
.IX Header "DESCRIPTION"
|
||||
The tabdump command displays the header and all the rows of the specified table in csv format.
|
||||
Only one table can be specified. If no table is specified, the list of existing
|
||||
tables will be displayed.
|
||||
.SH "OPTIONS"
|
||||
.IX Header "OPTIONS"
|
||||
\&\fB\-?|\-h|\-\-help\fR Display usage message.
|
||||
.SH "RETURN VALUE"
|
||||
.IX Header "RETURN VALUE"
|
||||
0 The command completed successfully.
|
||||
.PP
|
||||
1 An error has occurred.
|
||||
.SH "EXAMPLES"
|
||||
.IX Header "EXAMPLES"
|
||||
1. To display the contents of the site table:
|
||||
.PP
|
||||
\&\fItabdump site\fR
|
||||
.PP
|
||||
2. To see what tables exist in the xCAT database:
|
||||
.PP
|
||||
\&\fItabdump\fR
|
||||
.SH "FILES"
|
||||
.IX Header "FILES"
|
||||
/opt/xcat/sbin/tabdump
|
||||
.SH "NOTES"
|
||||
.IX Header "NOTES"
|
||||
This command is part of the xCAT software product.
|
172
xCAT-client-2.0/share/man/man1/tabrestore.1
Normal file
172
xCAT-client-2.0/share/man/man1/tabrestore.1
Normal file
@ -0,0 +1,172 @@
|
||||
.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sh \" Subsection heading
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
.de Vb \" Begin verbatim text
|
||||
.ft CW
|
||||
.nf
|
||||
.ne \\$1
|
||||
..
|
||||
.de Ve \" End verbatim text
|
||||
.ft R
|
||||
.fi
|
||||
..
|
||||
.\" Set up some character translations and predefined strings. \*(-- will
|
||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
||||
.\" double quote, and \*(R" will give a right double quote. | will give a
|
||||
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
|
||||
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
|
||||
.\" expand to `' in nroff, nothing in troff, for use with C<>.
|
||||
.tr \(*W-|\(bv\*(Tr
|
||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
||||
.ie n \{\
|
||||
. ds -- \(*W-
|
||||
. ds PI pi
|
||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
||||
. ds L" ""
|
||||
. ds R" ""
|
||||
. ds C` ""
|
||||
. ds C' ""
|
||||
'br\}
|
||||
.el\{\
|
||||
. ds -- \|\(em\|
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
'br\}
|
||||
.\"
|
||||
.\" If the F register is turned on, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.if \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. nr % 0
|
||||
. rr F
|
||||
.\}
|
||||
.\"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.hy 0
|
||||
.if n .na
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
. \" fudge factors for nroff and troff
|
||||
.if n \{\
|
||||
. ds #H 0
|
||||
. ds #V .8m
|
||||
. ds #F .3m
|
||||
. ds #[ \f1
|
||||
. ds #] \fP
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
|
||||
. ds #V .6m
|
||||
. ds #F 0
|
||||
. ds #[ \&
|
||||
. ds #] \&
|
||||
.\}
|
||||
. \" simple accents for nroff and troff
|
||||
.if n \{\
|
||||
. ds ' \&
|
||||
. ds ` \&
|
||||
. ds ^ \&
|
||||
. ds , \&
|
||||
. ds ~ ~
|
||||
. ds /
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
|
||||
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
|
||||
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
|
||||
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
|
||||
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
|
||||
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
|
||||
.\}
|
||||
. \" troff and (daisy-wheel) nroff accents
|
||||
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
|
||||
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
|
||||
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
|
||||
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
|
||||
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
|
||||
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
|
||||
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
|
||||
.ds ae a\h'-(\w'a'u*4/10)'e
|
||||
.ds Ae A\h'-(\w'A'u*4/10)'E
|
||||
. \" corrections for vroff
|
||||
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
|
||||
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
|
||||
. \" for low resolution devices (crt and lpr)
|
||||
.if \n(.H>23 .if \n(.V>19 \
|
||||
\{\
|
||||
. ds : e
|
||||
. ds 8 ss
|
||||
. ds o a
|
||||
. ds d- d\h'-1'\(ga
|
||||
. ds D- D\h'-1'\(hy
|
||||
. ds th \o'bp'
|
||||
. ds Th \o'LP'
|
||||
. ds ae ae
|
||||
. ds Ae AE
|
||||
.\}
|
||||
.rm #[ #] #H #V #F C
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "TABRESTORE.1 1"
|
||||
.TH TABRESTORE.1 1 "2008-02-14" "perl v5.8.8" "User Contributed Perl Documentation"
|
||||
.SH "NAME"
|
||||
\&\fBtabrestore\fR \- replaces the contents of an xCAT database table with the contents in a csv file.
|
||||
.SH "SYNOPSIS"
|
||||
.IX Header "SYNOPSIS"
|
||||
\&\fItabrestore table.csv\fR
|
||||
.PP
|
||||
\&\fItabrestore [? | \-h | \-\-help]\fR
|
||||
.SH "DESCRIPTION"
|
||||
.IX Header "DESCRIPTION"
|
||||
The tabrestore command reads the contents of the specified file and puts its data
|
||||
in the corresponding table in the xCAT database. Any existing rows in that table
|
||||
are replaced. The file must be in csv format. It could be created by tabdump.
|
||||
Only one table can be specified.
|
||||
.PP
|
||||
This command can be used to copy the example table entries in /opt/xcat/share/xcat/templates/e1350
|
||||
into the xCAT database.
|
||||
.SH "OPTIONS"
|
||||
.IX Header "OPTIONS"
|
||||
\&\fB\-?|\-h|\-\-help\fR Display usage message.
|
||||
.SH "RETURN VALUE"
|
||||
.IX Header "RETURN VALUE"
|
||||
0 The command completed successfully.
|
||||
.PP
|
||||
1 An error has occurred.
|
||||
.SH "EXAMPLES"
|
||||
.IX Header "EXAMPLES"
|
||||
1. To put rows into the mp table:
|
||||
.PP
|
||||
\&\fItabrestore mp.csv\fR
|
||||
.PP
|
||||
The file mp.csv could contain something like:
|
||||
.PP
|
||||
#node,mpa,id,comments,disable
|
||||
\&\*(L"blade\*(R",\*(L"|\eD+(\ed+)|amm(($1\-1)/14+1)|\*(R",\*(L"|\eD+(\ed+)|(($1\-1)%14+1)|\*(R",,
|
||||
.SH "FILES"
|
||||
.IX Header "FILES"
|
||||
/opt/xcat/sbin/tabrestore
|
||||
.SH "NOTES"
|
||||
.IX Header "NOTES"
|
||||
This command is part of the xCAT software product.
|
@ -4,31 +4,13 @@
|
||||
# xCAT plugin package to handle various commands that work with the
|
||||
# xCAT tables
|
||||
#
|
||||
# Supported commands:
|
||||
# nodeadd
|
||||
# nodels
|
||||
# nodech
|
||||
# tabdump
|
||||
# tabrestore
|
||||
# noderm
|
||||
# To be implemented:
|
||||
# gettab
|
||||
# chtab
|
||||
# tabls
|
||||
# getnodecfg (?? this doesn't seem much different from gettab)
|
||||
# nr
|
||||
# These were xCAT 1.2 commands. Are they still useful in xCAT 1.3?
|
||||
# addattr
|
||||
# delattr
|
||||
# chtype
|
||||
#
|
||||
#####################################################
|
||||
package xCAT_plugin::tabutils;
|
||||
use xCAT::Table;
|
||||
use xCAT::Schema;
|
||||
use Data::Dumper;
|
||||
use xCAT::NodeRange;
|
||||
use xCAT::Schema; #noderm will need to build list of tables..
|
||||
use xCAT::Schema;
|
||||
|
||||
#use Getopt::Long qw(GetOptionsFromArray);
|
||||
|
||||
@ -51,17 +33,17 @@ sub handled_commands
|
||||
gettab => "tabutils",
|
||||
tabdump => "tabutils",
|
||||
tabrestore => "tabutils",
|
||||
tabch => "tabutils",
|
||||
tabch => "tabutils", # not implemented yet
|
||||
nodech => "tabutils",
|
||||
nodeadd => "tabutils",
|
||||
noderm => "tabutils",
|
||||
tabls => "tabutils",
|
||||
tabls => "tabutils", # not implemented yet
|
||||
nodels => "tabutils",
|
||||
getnodecfg => "tabutils",
|
||||
addattr => "tabutils",
|
||||
delattr => "tabutils",
|
||||
chtype => "tabutils",
|
||||
nr => "tabutils",
|
||||
getnodecfg => "tabutils", # not implemented yet (?? this doesn't seem much different from gettab)
|
||||
addattr => "tabutils", # not implemented yet
|
||||
delattr => "tabutils", # not implemented yet
|
||||
chtype => "tabutils", # not implemented yet
|
||||
nr => "tabutils", # not implemented yet
|
||||
tabgrep => "tabutils"
|
||||
};
|
||||
}
|
||||
@ -72,45 +54,15 @@ my %usage = (
|
||||
nodeadd =>
|
||||
"Usage: nodeadd <noderange> [table.column=value] [table.column=value] ...",
|
||||
noderm => "Usage: noderm <noderange>",
|
||||
tabdump =>
|
||||
"Usage: tabdump <tablename>\n where <tablename> is one of the following:\n "
|
||||
. join("\n ", keys %xCAT::Schema::tabspec),
|
||||
tabrestore => "Usage: tabrestore <tablename>.csv",
|
||||
# the usage for tabdump is in the tabdump function
|
||||
#tabdump => "Usage: tabdump <tablename>\n where <tablename> is one of the following:\n " . join("\n ", keys %xCAT::Schema::tabspec),
|
||||
# the usage for tabrestore is in the tabrestore client cmd
|
||||
#tabrestore => "Usage: tabrestore <tablename>.csv",
|
||||
);
|
||||
|
||||
#####################################################
|
||||
# Process the command
|
||||
#####################################################
|
||||
sub gettab
|
||||
{
|
||||
my $req = shift;
|
||||
my $callback = shift;
|
||||
my $keyspec = shift @{$req->{arg}};
|
||||
my @keypairs = split /,/, $keyspec;
|
||||
my %keyhash;
|
||||
foreach (@keypairs)
|
||||
{
|
||||
(my $key, my $value) = split /=/, $_;
|
||||
$keyhash{$key} = $value;
|
||||
}
|
||||
my %tabhash;
|
||||
foreach my $tabvalue (@{$req->{arg}})
|
||||
{
|
||||
(my $table, my $column) = split /\./, $tabvalue;
|
||||
$tabhash{$table}->{$column} = 1;
|
||||
}
|
||||
foreach my $tabn (keys %tabhash)
|
||||
{
|
||||
my $tab = xCAT::Table->new($tabn);
|
||||
(my $ent) = $tab->getAttribs(\%keyhash, keys %{$tabhash{$tabn}});
|
||||
foreach my $coln (keys %{$tabhash{$tabn}})
|
||||
{
|
||||
$callback->({data => ["$tabn.$coln:" . $ent->{$coln}]});
|
||||
}
|
||||
$tab->close;
|
||||
}
|
||||
}
|
||||
|
||||
sub process_request
|
||||
{
|
||||
use Getopt::Long;
|
||||
@ -141,11 +93,11 @@ sub process_request
|
||||
}
|
||||
elsif ($command eq "nodeadd" or $command eq "addnode")
|
||||
{
|
||||
return chnode($nodes, $args, $callback, 1);
|
||||
return nodech($nodes, $args, $callback, 1);
|
||||
}
|
||||
elsif ($command eq "nodech" or $command eq "chnode")
|
||||
elsif ($command eq "nodech" or $command eq "nodech")
|
||||
{
|
||||
return chnode($nodes, $args, $callback, 0);
|
||||
return nodech($nodes, $args, $callback, 0);
|
||||
}
|
||||
elsif ($command eq "tabrestore")
|
||||
{
|
||||
@ -171,6 +123,36 @@ sub process_request
|
||||
|
||||
}
|
||||
|
||||
sub gettab
|
||||
{
|
||||
my $req = shift;
|
||||
my $callback = shift;
|
||||
my $keyspec = shift @{$req->{arg}};
|
||||
my @keypairs = split /,/, $keyspec;
|
||||
my %keyhash;
|
||||
foreach (@keypairs)
|
||||
{
|
||||
(my $key, my $value) = split /=/, $_;
|
||||
$keyhash{$key} = $value;
|
||||
}
|
||||
my %tabhash;
|
||||
foreach my $tabvalue (@{$req->{arg}})
|
||||
{
|
||||
(my $table, my $column) = split /\./, $tabvalue;
|
||||
$tabhash{$table}->{$column} = 1;
|
||||
}
|
||||
foreach my $tabn (keys %tabhash)
|
||||
{
|
||||
my $tab = xCAT::Table->new($tabn);
|
||||
(my $ent) = $tab->getAttribs(\%keyhash, keys %{$tabhash{$tabn}});
|
||||
foreach my $coln (keys %{$tabhash{$tabn}})
|
||||
{
|
||||
$callback->({data => ["$tabn.$coln:" . $ent->{$coln}]});
|
||||
}
|
||||
$tab->close;
|
||||
}
|
||||
}
|
||||
|
||||
sub noderm
|
||||
{
|
||||
my $nodes = shift;
|
||||
@ -219,11 +201,12 @@ sub noderm
|
||||
push @tablist, $_;
|
||||
}
|
||||
}
|
||||
chnode($nodes, \@tablist, $cb, 0);
|
||||
nodech($nodes, \@tablist, $cb, 0);
|
||||
}
|
||||
|
||||
sub tabrestore
|
||||
{
|
||||
# the usage for tabrestore is in the tabrestore client cmd
|
||||
|
||||
#request->{data} is an array of CSV formatted lines
|
||||
my $request = shift;
|
||||
@ -231,9 +214,8 @@ sub tabrestore
|
||||
my $table = $request->{table}->[0];
|
||||
my $linenumber = 1;
|
||||
my $tab = xCAT::Table->new($table, -create => 1, -autocommit => 0);
|
||||
unless ($tab)
|
||||
{
|
||||
$cb->({error => "Unable to open $table"});
|
||||
unless ($tab) {
|
||||
$cb->({error => "Unable to open $table",errorcode=>4});
|
||||
return;
|
||||
}
|
||||
$tab->delEntries(); #Yes, delete *all* entries
|
||||
@ -269,8 +251,7 @@ sub tabrestore
|
||||
{
|
||||
error =>
|
||||
"CSV missing opening \" for record with \" characters on line $linenumber, character "
|
||||
. index($origline, $line)
|
||||
. ": $origline"
|
||||
. index($origline, $line) . ": $origline", errorcode=>4
|
||||
}
|
||||
);
|
||||
next LINE;
|
||||
@ -291,8 +272,7 @@ sub tabrestore
|
||||
{
|
||||
error =>
|
||||
"CSV unmatched \" in record on line $linenumber, character "
|
||||
. index($origline, $line)
|
||||
. ": $origline"
|
||||
. index($origline, $line) . ": $origline", errorcode=>4
|
||||
}
|
||||
);
|
||||
next LINE;
|
||||
@ -317,8 +297,7 @@ sub tabrestore
|
||||
{
|
||||
error =>
|
||||
"CSV unescaped \" in record on line $linenumber, character "
|
||||
. index($origline, $line)
|
||||
. ": $origline"
|
||||
. index($origline, $line) . ": $origline", errorcode=>4
|
||||
}
|
||||
);
|
||||
$rollback = 1;
|
||||
@ -335,12 +314,7 @@ sub tabrestore
|
||||
if ($line)
|
||||
{
|
||||
$rollback = 1;
|
||||
$cb->(
|
||||
{
|
||||
error =>
|
||||
"Too many fields on line $linenumber: $origline | $line"
|
||||
}
|
||||
);
|
||||
$cb->({error => "Too many fields on line $linenumber: $origline | $line", errorcode=>4});
|
||||
next LINE;
|
||||
}
|
||||
|
||||
@ -349,14 +323,7 @@ sub tabrestore
|
||||
if (not defined($rc[0]))
|
||||
{
|
||||
$rollback = 1;
|
||||
$cb->(
|
||||
{
|
||||
error => "DB error "
|
||||
. $rc[1]
|
||||
. " with line $linenumber: "
|
||||
. $origline
|
||||
}
|
||||
);
|
||||
$cb->({error => "DB error " . $rc[1] . " with line $linenumber: " . $origline, errorcode=>4});
|
||||
}
|
||||
}
|
||||
if ($rollback)
|
||||
@ -374,69 +341,79 @@ sub tabrestore
|
||||
|
||||
sub tabdump
|
||||
{
|
||||
|
||||
#TODO: need to return header for not-yet existing, but schemad tabs
|
||||
#TODO: schema defined column order.
|
||||
my $args = shift;
|
||||
my $cb = shift;
|
||||
my $table = "";
|
||||
foreach (@$args)
|
||||
{
|
||||
unless (/^-/)
|
||||
{
|
||||
if ($table)
|
||||
{
|
||||
return 1; #TODO: Error, usage
|
||||
}
|
||||
$table = $_;
|
||||
}
|
||||
my $HELP;
|
||||
|
||||
sub tabdump_usage {
|
||||
my $exitcode = shift @_;
|
||||
my %rsp;
|
||||
push @{$rsp{data}}, "Usage: tabdump [table]";
|
||||
push @{$rsp{data}}, " tabdump [-?|-h|--help]";
|
||||
if ($exitcode) { $rsp{errorcode} = $exitcode; }
|
||||
$cb->(\%rsp);
|
||||
}
|
||||
my $tabh = xCAT::Table->new($table);
|
||||
|
||||
# Process arguments
|
||||
@ARGV = @{$args};
|
||||
if (!GetOptions('h|?|help' => \$HELP)) { tabdump_usage(1); return; }
|
||||
|
||||
if ($HELP) { tabdump_usage(0); return; }
|
||||
if (scalar(@ARGV)>1) { tabdump_usage(1); return; }
|
||||
|
||||
my %rsp;
|
||||
# If no arguments given, we display a list of the tables
|
||||
if (!scalar(@ARGV)) {
|
||||
push @{$rsp{data}}, keys %xCAT::Schema::tabspec;
|
||||
$cb->(\%rsp);
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $ARGV[0];
|
||||
my $tabh = xCAT::Table->new($table);
|
||||
|
||||
sub tabdump_header {
|
||||
my $header = "#" . join(",", @_);
|
||||
push @{$rsp{data}}, $header;
|
||||
}
|
||||
|
||||
# If the table does not exist yet (because its never been written to),
|
||||
# at least show the header (the column names)
|
||||
unless ($tabh)
|
||||
{
|
||||
if (defined($xCAT::Schema::tabspec{$table}))
|
||||
{
|
||||
my $header = join ",", @{$xCAT::Schema::tabspec{$table}->{cols}};
|
||||
$header = "#" . $header;
|
||||
push @{$rsp{data}}, $header;
|
||||
$cb->(\%rsp);
|
||||
tabdump_header(@{$xCAT::Schema::tabspec{$table}->{cols}});
|
||||
$cb->(\%rsp);
|
||||
return;
|
||||
}
|
||||
$cb->({error => "No such table: $table"});
|
||||
$cb->({error => "No such table: $table",errorcode=>1});
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $recs = $tabh->getAllEntries();
|
||||
my $rec;
|
||||
my $firstline = 1;
|
||||
unless (@$recs)
|
||||
unless (@$recs) # table exists, but is empty. Show header.
|
||||
{
|
||||
if (defined($xCAT::Schema::tabspec{$table}))
|
||||
{
|
||||
my $header = join ",", @{$xCAT::Schema::tabspec{$table}->{cols}};
|
||||
$header = "#" . $header;
|
||||
push @{$rsp{data}}, $header;
|
||||
$cb->(\%rsp);
|
||||
tabdump_header(@{$xCAT::Schema::tabspec{$table}->{cols}});
|
||||
$cb->(\%rsp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Display all the rows of the table in the order of the columns in the schema
|
||||
tabdump_header(@{$tabh->{colnames}});
|
||||
foreach $rec (@$recs)
|
||||
{
|
||||
my $line = '';
|
||||
if ($firstline)
|
||||
{
|
||||
$firstline = 0;
|
||||
$line = join ",", @{$tabh->{colnames}};
|
||||
$line = "#" . $line;
|
||||
push @{$rsp{data}}, $line;
|
||||
$line = '';
|
||||
}
|
||||
foreach (@{$tabh->{colnames}})
|
||||
{
|
||||
$rec->{$_} =~ s/"/""/g;
|
||||
if (defined $rec->{$_})
|
||||
{
|
||||
$rec->{$_} =~ s/"/""/g;
|
||||
$line = $line . '"' . $rec->{$_} . '",';
|
||||
}
|
||||
else
|
||||
@ -444,14 +421,14 @@ sub tabdump
|
||||
$line .= ',';
|
||||
}
|
||||
}
|
||||
$line =~ s/,$//;
|
||||
$line =~ s/,$//; # remove the extra comma at the end
|
||||
$line = $line . $lineappend;
|
||||
push @{$rsp{data}}, $line;
|
||||
}
|
||||
$cb->(\%rsp);
|
||||
}
|
||||
|
||||
sub chnode
|
||||
sub nodech
|
||||
{
|
||||
my $nodes = shift;
|
||||
my $args = shift;
|
||||
|
Loading…
Reference in New Issue
Block a user