diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm
deleted file mode 100644
index e0934796d..000000000
--- a/perl-xCAT/xCAT/Client.pm
+++ /dev/null
@@ -1,1254 +0,0 @@
-#!/usr/bin/env perl
-# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
-package xCAT::Client;
-BEGIN
-{
- $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
-}
-
-# if AIX - make sure we include perl 5.8.2 in INC path.
-# Needed to find perl dependencies shipped in deps tarball.
-use Storable qw/nstore_fd fd_retrieve/;
-if ($^O =~ /^aix/i) {
- unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2));
-}
-use IO::Handle;
-
-my $inet6support;
-if ($^O =~ /^aix/i) { # disable AIX IPV6 TODO fix
- $inet6support = 0;
-} else {
- $inet6support=eval { require Socket6; 1; };
-}
-if ($inet6support) {
- $inet6support = eval { require IO::Socket::INET6; 1; };
-}
-if ($inet6support) {
- $inet6support = eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet6'); 1;};
-}
-
-if ($^O =~ /^linux/i) {
- # Is IPv6 enabled on the MN or xcat client node at all?
- my $ipv6enabled = `ip addr | grep inet6`;
- if (!$ipv6enabled) {
- $inet6support = 0;
- }
-}
-
-unless ($inet6support) {
- eval { require Socket };
- eval { require IO::Socket::INET };
- eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet4') };
-}
-
-
-use XML::Simple; #smaller than libxml....
-use Fcntl;
-use POSIX qw/:errno_h/;
-use IO::Select;
-$XML::Simple::PREFERRED_PARSER='XML::Parser';
-#require Data::Dumper;
-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;
-
-
-sub rspclean {
- my $response = shift;
- my $callback = shift;
- my $rsps = XMLin($response,SuppressEmpty=>undef,ForceArray=>1);
- foreach my $rsp (@{$rsps->{xcatresponse}}) {
- #add ESC back
- foreach my $key (keys %$rsp) {
- if (ref($rsp->{$key}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{$key}}) {
- next unless defined $text;
- $text =~ s/xxxxESCxxxx/\e/g;
- }
- }
- else {
- $rsp->{$key} =~ s/xxxxESCxxxx/\e/g;
- }
- }
- $callback->($rsp);
- if ($rsp->{serverdone}) {
- return 1;
- }
- }
- return 0;
-}
-sub send_request {
- my $request = shift;
- my $sock = shift;
- my $encode = shift;
- if ($encode eq "xml") {
- my $msg=XMLout($request,RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]);
- if ($ENV{XCATXMLTRACE}) { print $msg; }
- if($ENV{XCATXMLWARNING}) {
- validateXML($msg);
- }
- print $sock $msg;
- $sock->flush();
- } else {
- nstore_fd($request,$sock);
- $sock->flush();
- }
-}
-#################################
-# submit_request will take an xCAT command and pass it to the xCAT
-# server for execution.
-# Note must not put a require or use for Utils.pm in the non-bypass path
-#
-# 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
-# directory /opt/xcat/lib/perl/xCAT_plugin will be used.
-#
-# Input:
-# Request hash - A hash ref containing the input command and args to be
-# passed to the plugin. The the xcatd daemon (or this routine when
-# XCATBYPASS) reads the {noderange} entry and builds a flattened array
-# of nodes that gets added as request->{node}
-# The format for the request hash is:
-# { command => [ 'xcatcmd' ],
-# noderange => [ 'noderange_string' ],
-# arg => [ 'arg1', 'arg2', '...', 'argn' ]
-# }
-# 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.
-# The input request and the response hash created by the plugin should
-# always create hashes with array values.
-#################################
-sub submit_request {
- my $request = shift;
- my $callback = shift;
- my $keyfile = shift;
- my $certfile = shift;
- my $cafile = shift;
- # get home directory
- my @user = getpwuid($>);
- my $homedir=$user[7];
- unless ($keyfile) { $keyfile = $homedir."/.xcat/client-cred.pem"; }
- unless ($certfile) { $certfile = $homedir."/.xcat/client-cred.pem"; }
- unless ($cafile) { $cafile = $homedir."/.xcat/ca.pem"; }
- $xCAT::Client::EXITCODE = 0; # clear out exit code before invoking the plugin
-if (ref($request) eq 'HASH') { # the request is an array, not pure XML
- $request->{clienttype}->[0] = "cli"; # setup clienttype for auditlog
-}
-# If XCATBYPASS is set, invoke the plugin process_request method directly
-# without going through the socket connection to the xcatd daemon
- if ($ENV{XCATBYPASS}) {
- #add current userid to the request
- if (ref($request) eq 'HASH') { # the request is an array, not pure XML
- if (!(defined($request->{username}))) {
- $request->{username}->[0] = getpwuid($>);
- }
-
- # only allow root to run
- unless ($request->{username}->[0] =~ /root/) {
- print ("WARNING: Only allow root to run XCATBYPASS mode, your current user ID is $request->{username}->[0].\n");
- return 0;
- }
- }
- # Load plugins from either specified or default dir
- require xCAT::Table;
- my %cmd_handlers;
- my @plugins_dirs = split('\:',$ENV{XCATBYPASS});
- if (-d $plugins_dirs[0]) {
- foreach (@plugins_dirs) {
- $plugins_dir = $_;
- scan_plugins();
- }
- } else {
- # figure out default plugins dir
- #my $sitetab=xCAT::Table->new('site');
- #unless ($sitetab) {
- # print ("ERROR: Unable to open basic site table for configuration\n");
- #}
- $plugins_dir=$::XCATROOT.'/lib/perl/xCAT_plugin';
- scan_plugins();
- }
-
- populate_site_hash();
-
- # don't do XML transformation -- assume request is well-formed
- # my $xmlreq=XMLout($request,RootName=>xcatrequest,NoAttr=>1,KeyAttr=>[]);
- # $request = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ;
-
-
- # Call the plugin directly
- # ${"xCAT_plugin::".$modname."::"}{process_request}->($request,$callback);
- plugin_command($request,undef,$callback);
- return 0;
- }
-
-# No XCATBYPASS, so establish a socket connection with the xcatd daemon
-# and submit the request
- if ($ENV{XCATHOST}) {
- $xcathost=$ENV{XCATHOST};
- }
- my %connargs=();
- if ($xcathost =~ s/%([^\]|:]*)//) {
- $connargs{PeerScope} = $1;
- }
- $connargs{PeerAddr} = $xcathost;
- $connargs{Timeout} = 15;
- if ($connargs{PeerScope} and $connargs{PeerScope} =~ /[a-zA-Z]/) { #non-numeric, need to translate...
- my @ipdata = `ip link`;
- @ipdata = grep(/[^@]$connargs{PeerScope}(:|@)/,@ipdata);
- if (scalar(@ipdata) != 1) {
- print STDERR "Unable to identify scope ".$connargs{PeerScope}."\n";
- exit(1);
- }
- $connargs{PeerScope} = $ipdata[0];
- $connargs{PeerScope} =~ s/:.*//;
- }
-
-
- my $pclient;
- if ($inet6support) {
- $pclient = IO::Socket::INET6->new(
- %connargs,
- );
- } else {
- $pclient = IO::Socket::INET->new(
- PeerAddr => $xcathost,
- Timeout => 15,
- );
- }
- unless ($pclient) {
- print "Unable to open socket connection to xcatd daemon on $xcathost.\n";
- print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n";
- if ($@ =~ /SSL Timeout/) {
- die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat";
- } else {
- die "Connection failure: $@"
- }
- }
- my $client;
- if (-r $keyfile and -r $certfile and -r $cafile) {
- $client = IO::Socket::SSL->start_SSL($pclient,
- SSL_key_file => $keyfile,
- SSL_cert_file => $certfile,
- SSL_ca_file => $cafile,
- SSL_use_cert => 1,
- Timeout => 0,
- );
- } else {
- $client = IO::Socket::SSL->start_SSL($pclient,
- Timeout => 0,
- );
- }
- unless ($client) {
- print "Unable to open socket connection to xcatd daemon on $xcathost.\n";
- print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n";
- if ($@ =~ /SSL Timeout/) {
- die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat";
- } else {
- die "Connection failure: $@"
- }
- }
-
- my $msg;
- my $encode = "xml";
- #storable encoding is unsafe, carry on with the unsafe xml scheme
- #perhaps one day will support faster schemes
- #my $encode = "storable";
- #my $straightprint=0;
- #if ($ENV{XCATXMLTRACE} or $ENV{XCATXMLWARNING}) { $encode="xml"; }
- if (ref($request) eq 'HASH') { # the request is an array, not pure XML
- #print $client "xcatencoding: $encode\n";
- #my $encok=<$client>;
- send_request($request,$client,$encode);
- } else { #XML
- $straightprint=1;
- $msg=$request;
- print $client $msg;
- }
- $SIG{TERM} = $SIG{INT} = sub { send_request({abortcommand=>[1]},$client,$encode); exit 0; };
- my $response;
- my $rsp;
- my $cleanexit=0;
- if ($encode eq 'xml') {
- my $massresponse="";
- my $nextcoalescetime=time()+1;
- my $coalescenow=0;
- my $flags=fcntl($client,F_GETFL,0);
- $flags |= O_NONBLOCK; #select can be a bit.. fickle, make sysread work more easily...
- fcntl($client,F_SETFL,$flags);
- my $clientsel = new IO::Select;
- $clientsel->add($client);
- my $line;
- my $newdata=0;
- while (1) {
- my $shouldexit;
- if ($newdata and ($coalescenow or time() > $nextcoalescetime)) {
- $coalescenow=0;
- $newdata=0;
- $nextcoalescetime=time()+1;
- $massresponse .= "";
- $shouldexit = rspclean($massresponse,$callback);
- $massresponse="";
- }
-
- if ($shouldexit) {
- $cleanexit=1;
- last;
- }
- $line = "";
- $clientsel->can_read(0.5);
- my $readbytes;
- do { $readbytes=sysread($client,$line,65535,length($line)); } while ($readbytes);
- unless (length($line)) {
- if (not defined $readbytes and $! == EAGAIN) { next; }
- last;
- }
- $newdata=1;
- $response .= $line;
- if ($line =~ m/<\/xcatresponse>\s*\z/) {
- if ($line =~ /serverdone/) { $coalescenow=1; } #if serverdone was detected, hint at coalesce code to flush things out now
- #this means that coalesce can be triggered by stray words in the output prematurely, but that's harmless
- #replace ESC with xxxxESCxxx because XMLin cannot handle it
- $response =~ s/\e/xxxxESCxxxx/g;
-
- if ($ENV{XCATXMLTRACE}) { print $response; }
- $massresponse.=$response;
- $response='';
- if($ENV{XCATXMLWARNING}) {
- validateXML($response);
- }
- }
- }
- if (not $cleanexit and $massresponse ne "") {
- $massresponse .= "";
- $cleanexit = rspclean($massresponse,$callback);
- }
- } else { #storable encode
- my $rsp;
- eval { $rsp = fd_retrieve($client); };
- SERVERINPUT: while ($rsp) {
- my @rsps;
- if (ref $rsp eq 'ARRAY') {
- @rsps = @$rsp;
- } else {
- @rsps = ($rsp);
- }
- foreach (@rsps) {
- $callback->($_);
- if ($_->{serverdone}) {
- $cleanexit=1;
- last SERVERINPUT;
- }
- }
- $rsp = undef;
- eval { $rsp = fd_retrieve($client); };
- }
- }
- $massresponse="";
- unless ($cleanexit) {
- print STDERR "ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely\n";
- $xCAT::Client::EXITCODE = 1;
- }
-
-sub validateXML {
- my $xml = shift;
- my @lines = split /\n/, $xml;
- my $invalidNewline = 0;
- my $contentsColon = 0;
- my $contentsLine;
-
- foreach (@lines) {
- if(!$invalidNewline) {
- if( ($_ =~ // && $_ !~ /<\/contents>/) ||
- ($_ =~ // && $_ !~ /<\/desc>/)) {
- $invalidNewline = 1;
- print "Possible invalid XML using newlines found: \n$xml\n";
- }
- }
- if($_ =~ /.+:.+<\/contents>/) {
- $contentsColon = 1;
- $contentsLine = $_;
- }
- if($_ =~ /.+<\/desc>/) {
- $contentsColon = 0;
- }
- if($contentsColon && $_ =~ /<\/desc>/) {
- print "Possible invalid XML found(data contents using colon and blank description): \n$contentsLine\n$_\n";
- $contentsColon = 0;
- }
- }
-}
-
-###################################
-# scan_plugins
-# will load all plugin perl modules and build a list of supported
-# commands
-#
-# NOTE: This is copied from xcatd (last merge 11/23/09).
-# TODO: Will eventually move to using common source....
-###################################
-sub scan_plugins {
- my @plugins=glob($plugins_dir."/*.pm");
- foreach (@plugins) {
- /.*\/([^\/]*).pm$/;
- my $modname = $1;
- unless ( eval { require "$_" }) {
-# xCAT::MsgUtils->message("S","Error loading module ".$_." ...skipping");
- print "Error loading module $_ ...skipping\n";
- next;
- }
- no strict 'refs';
- my $cmd_adds=${"xCAT_plugin::".$modname."::"}{handled_commands}->();
- foreach (keys %$cmd_adds) {
- my $value = $_;
- if (defined($cmd_handlers{$_})) {
- push @{$cmd_handlers{$_}},[$modname,$cmd_adds->{$_}];
- } else {
- $cmd_handlers{$_} = [ [$modname,$cmd_adds->{$_}] ];
- }
- }
- }
- foreach (@plugins) {
- no strict 'refs';
- /.*\/([^\/]*).pm$/;
- my $modname = $1;
- unless (defined(${"xCAT_plugin::".$modname."::"}{init_plugin})) {
- next;
- }
- ${"xCAT_plugin::".$modname."::"}{init_plugin}->(\&do_request);
- }
-}
-
-
-
-
-###################################
-# plugin_command
-# will invoke the correct plugin
-#
-# NOTE: This is copied from xcatd (last merge 11/23/09).
-# TODO: Will eventually move to using common source....
-###################################
-sub plugin_command {
- my $req = shift;
- my $sock = shift;
- my $callback = shift;
- my %handler_hash;
- my $usesiteglobal = 0;
- # We require these only in bypass mode to reduce start up time for the normal case
- #use lib "$::XCATROOT/lib/perl";
- #use xCAT::NodeRange;
- require lib;
- lib->import("$::XCATROOT/lib/perl");
- require xCAT::NodeRange;
- require xCAT::Table;
-
- $Main::resps={};
- my $xmlreq;
- if (ref($req) ne 'HASH') { # the request XML, get an array
- $xmlreq=$req; # save the original XML
- $req = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ;
-
- }
- my @nodes;
- if ($req->{node}) {
- @nodes = @{$req->{node}};
- } elsif ($req->{noderange} and $req->{noderange}->[0]) {
- @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]);
- if (xCAT::NodeRange::nodesmissed()) {
-# my $rsp = {errorcode=>1,error=>"Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed)};
-# my $rsp->{serverdone} = {};
- print "Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed())."\n";
-# if ($sock) {
-# print $sock XMLout($rsp,RootName=>'xcatresponse' ,NoAttr=>1);
-# }
-# return ($rsp);
- return 1;
- }
- unless (@nodes) {
- $req->{emptynoderange} = [1];
- }
- }
- if (@nodes) { $req->{node} = \@nodes; }
- my %unhandled_nodes;
- foreach (@nodes) {
- $unhandled_nodes{$_}=1;
- }
- my $useunhandled=0;
- if (defined($cmd_handlers{$req->{command}->[0]})) {
- my $hdlspec;
- my @globalhandlers=();
- my $useglobals=1; #If it stays 1, then use globals normally, if 0, use only for 'unhandled_nodes, if -1, don't do at all
- foreach (@{$cmd_handlers{$req->{command}->[0]}}) {
- $hdlspec =$_->[1];
- my $ownmod = $_->[0];
- if ($hdlspec =~ /^site:/) { #A site entry specifies a plugin
- my $sitekey = $hdlspec;
- $sitekey =~ s/^site://;
- #$sitetab = xCAT::Table->new('site');
- #my $sent = $sitetab->getAttribs({key=>$sitekey},['value']);
- #if ($sent and $sent->{value}) { #A site style plugin specification is just like
- if ($::XCATSITEVALS{$sitekey}) { #A site style plugin specification is just like
- #a static global, it grabs all nodes rather than some
- $useglobals = -1; #If they tried to specify anything, don't use the default global handlers at all
- unless (@nodes) {
- $handler_hash{$::XCATSITEVALS{$sitekey}} = 1;
- $usesiteglobal = 1;
- }
- foreach (@nodes) { #Specified a specific plugin, not a table lookup
- $handler_hash{$::XCATSITEVALS{$sitekey}}->{$_} = 1;
- }
- }
- } elsif ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name
- if (@nodes) { # only use table lookup plugin if nodelist exists
- # Usage will be handled in common AAAhelp plugin
-
- $useglobals = 0; #Only contemplate nodes that aren't caught through searching below in the global handler
- $useunhandled=1;
- my $table;
- my $cols;
- ($table,$cols) = split(/:/,$hdlspec);
- my @colmns=split(/,/,$cols);
- my @columns;
- my $hdlrtable=xCAT::Table->new($table);
- unless ($hdlrtable) {
- #TODO: proper error handling
- }
- my $node;
- my $colvals = {};
- foreach my $colu (@colmns) {
- if ($colu =~ /=/) { #a value redirect to a pattern/specific name
- my $coln; my $colv;
- ($coln,$colv) = split(/=/,$colu,2);
- $colvals->{$coln} = $colv;
- push (@columns,$coln);
- } else {
- push (@columns,$colu);
- }
- }
-
-
- unless (@nodes) { #register the plugin in the event of usage
- $handler_hash{$ownmod} = 1;
- $useglobals = 1;
- }
- my $hdlrcache;
- if ($hdlrtable) {
- $hdlrcache = $hdlrtable->getNodesAttribs(\@nodes,\@columns);
- }
- foreach $node (@nodes) {
- unless ($hdlrcache) { next; }
- my $attribs = $hdlrcache->{$node}->[0]; #$hdlrtable->getNodeAttribs($node,\@columns);
- unless (defined($attribs)) { next; }
- foreach (@columns) {
- my $col=$_;
- if (defined($attribs->{$col})) {
- if ($colvals->{$col}) { #A pattern match style request.
- if ($attribs->{$col} =~ /$colvals->{$col}/) {
- $handler_hash{$ownmod}->{$node} = 1;
- delete $unhandled_nodes{$node};
- last;
- }
- } else {
- # call the plugin that matches the table value for that node
- if ($attribs->{$col} =~ /$ownmod/) {
- $handler_hash{$attribs->{$col}}->{$node} = 1;
- delete $unhandled_nodes{$node};
- last;
- }
- }
- }
- }
- }
- $hdlrtable->close;
- } # end if (@nodes)
-
- } else {
- push @globalhandlers,$hdlspec;
- }
- }
- if ($useglobals == 1) { #Behavior when globals have not been overriden
- my $hdlspec;
- foreach $hdlspec (@globalhandlers) {
- unless (@nodes) {
- $handler_hash{$hdlspec} = 1;
- }
- foreach (@nodes) { #Specified a specific plugin, not a table lookup
- $handler_hash{$hdlspec}->{$_} = 1;
- }
- }
- } elsif ($useglobals == 0) {
- unless (@nodes or $usesiteglobal) { #if something like 'makedhcp -n',
- foreach (keys %handler_hash) {
- if ($handler_hash{$_} == 1) {
- delete ($handler_hash{$_})
- }
- }
- }
- foreach $hdlspec (@globalhandlers) {
- unless (@nodes or $usesiteglobal) {
- $handler_hash{$hdlspec} = 1;
- }
- foreach (keys %unhandled_nodes) { #Specified a specific plugin, not a table lookup
- $handler_hash{$hdlspec}->{$_} = 1;
- }
- }
- } #Otherwise, global handler is implicitly disabled
- } else {
- print "Error request: $req->{command}->[0] has no known plugin for it.\n";
- return 1;
- }
- if ($useunhandled) {
- my $queuelist;
- foreach (@{$cmd_handlers{$req->{command}->[0]}}) {
- my $queueitem = $_->[1];
- if (($queueitem =~ /:/) and !($queuelist =~ /($queueitem)/)) {
- $queuelist .= "$_->[1];";
- }
- }
- $queuelist =~ s/;$//;
- $queuelist =~ s/:/./g;
- foreach (keys %unhandled_nodes) {
-# if ($sock) {
-# print $sock XMLout({node=>[{name=>[$_],data=>["Unable to identify plugin for this command, check relevant tables: $queuelist"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse');
-# } else {
- my $tabdesc = $queuelist;
- $tabdesc =~ s/=.*$//;
- $callback->({node=>[{name=>[$_],error=>['Unable to identify plugin for this command, check relevant tables: '.$tabdesc],errorcode=>[1]}]});
-# }
- }
- }
-
-## FOR NOW, DON'T FORK CHILD PROCESS TO MAKE BYPASS SIMPLER AND EASIER TO DEBUG
-# $plugin_numchildren=0;
-# %plugin_children=();
-# $SIG{CHLD} = \&plugin_reaper; #sub {my $plugpid; while (($plugpid = waitpid(-1, WNOHANG)) > 0) { if ($plugin_children{$plugpid}) { delete $plugin_children{$plugpid}; $plugin_numchildren--; } } };
-# my $check_fds;
-# if ($sock) {
-# $check_fds = new IO::Select;
-# }
- foreach (keys %handler_hash) {
- my $modname = $_;
-# my $shouldbealivepid=$$;
- if (-r $plugins_dir."/".$modname.".pm") {
- require $plugins_dir."/".$modname.".pm";
-# $plugin_numchildren++;
-# my $pfd; #will be referenced for inter-process messaging.
-# my $parfd; #not causing a problem that I discern yet, but theoretically
-# my $child;
-# if ($sock) { #If $sock not passed in, don't fork..
-# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!";
-# #pipe($pfd,$cfd);
-# $parfd->autoflush(1);
-# $pfd->autoflush(1);
-# $child = xCAT::Utils->xfork;
-# } else {
-# $child = 0;
-# }
-# unless (defined $child) { die "Fork failed"; }
-# if ($child == 0) {
-# if ($parfd) { #If xCAT is doing multiple requests in same communication PID, things would get unfortunate otherwise
-# $parent_fd = $parfd;
-# }
- my $oldprogname=$$progname;
- $$progname=$oldprogname.": $modname instance";
-# if ($sock) { close $pfd; }
- unless ($handler_hash{$_} == 1) {
- my @nodes = sort {($a =~ /(\d+)/)[0] <=> ($b =~ /(\d+)/)[0] || $a cmp $b } (keys %{$handler_hash{$_}});
- $req->{node}=\@nodes;
- }
- no strict "refs";
-# eval { #REMOVEEVALFORDEBUG
-# if ($dispatch_requests) {
- # backup the original req and recover it after the a run
- my $org_req = {%$req};
- dispatch_request($req,$callback,$modname);
- $req = {%$org_req};
-# } else {
-# $SIG{CHLD}='DEFAULT';
-# ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request);
-# }
- $$progname=$oldprogname;
-# if ($sock) {
-# close($parent_fd);
-# xexit(0);
-# }
-# }; #REMOVEEVALFORDEBUG
-# if ($sock or $shouldbealivepid != $$) { #We shouldn't still be alive, try to send as much detail to parent as possible as to why
-# my $error= "$modname plugin bug, pid $$, process description: '$$progname'";
-# if ($@) {
-# $error .= " with error '$@'";
-# } else { #Sys::Virt and perhaps Net::SNMP sometimes crashes in a way $@ won't catch..
-# $error .= " with missing eval error, probably due to special manipulation of $@ or strange circumstances in an XS library, remove evals in xcatd marked 'REMOVEEVALFORDEBUG and run xcatd -f for more info";
-# }
-# if (scalar (@nodes)) { #Don't know which of the nodes, so one error message warning about the possibliity..
-# $error .= " while trying to fulfill request for the following nodes: ".join(",",@nodes);
-# }
-# xCAT::MsgUtils->message("S","xcatd: $error");
-# $callback->({error=>[$error],errorcode=>[1]});
-# xexit(0); #Die like we should have done
-# } elsif ($@) { #We are still alive, should be alive, but yet we have an error. This means we are in the case of 'do_request' or something similar. Forward up the death since our communication channel is intact..
-# die $@;
-# }
-# } else {
-# $plugin_children{$child}=1;
-# close $parfd;
-# $check_fds->add($pfd);
-# }
- } else {
- my $pm_name = $plugins_dir."/".$modname.".pm";
- foreach my $node (keys %{$handler_hash{$_}}) {
- if ($sock) {
- print $sock XMLout({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse');
- } else {
- $callback->({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]});
- }
- }
- }
- }
- unless ($sock) { return $Main::resps };
-# while (($plugin_numchildren > 0) and ($check_fds->count > 0)) { #this tracks end of useful data from children much more closely
-# relay_fds($check_fds,$sock);
-# }
-# #while (relay_fds($check_fds,$sock)) {}
-# my %done;
-# $done{serverdone} = {};
-# if ($req->{transid}) {
-# $done{transid}=$req->{transid}->[0];
-# }
-# if ($sock) {
-# my $clientpresence = new IO::Select; #The client may have gone away without confirmation, don't PIPE over this trivial thing
-# $clientpresence->add($sock);
-# if ($clientpresence->can_write(5)) {
-# print $sock XMLout(\%done,RootName => 'xcatresponse',NoAttr=>1);
-# }
-# }
-}
-
-
-
-
-###################################
-# dispatch_request
-# dispatch the requested command
-#
-# NOTE: This is copied from xcatd (last merge 11/23/09).
-# All we really need from this subroutine is to call preprocess_request
-# and to only run the command for nodes handled by the local server
-# Will eventually move to using common source....
-###################################
-sub dispatch_request {
-# %dispatched_children=();
- require xCAT::Utils;
- my $req = shift;
- $dispatch_cb = shift;
-
- my $modname = shift;
- my $reqs = [];
-# my $child_fdset = new IO::Select;
- no strict "refs";
-
- #Hierarchy support. Originally, the default scope for noderange commands was
- #going to be the servicenode associated unless overriden.
- #However, assume for example that you have blades and a blade is the service node
- #rpower being executed by the servicenode for one of its subnodes would have to
- #reach it's own management module. This has the potential to be non-trivial for some quite possible network configurations.
- #Since plugins may commonly experience this, a preprocess_request implementation
- #will for now be required for a command to be scaled through service nodes
- #If the plugin offers a preprocess method, use it to set the request array
- if (defined(${"xCAT_plugin::".$modname."::"}{preprocess_request})) {
- $SIG{CHLD}='DEFAULT';
- $reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req,$dispatch_cb,\&do_request);
- } else { #otherwise, pass it in without hierarchy support
- $reqs = [$req];
- }
-
-# $dispatch_children=0;
-# $SIG{CHLD} = \&dispatch_reaper; #sub {my $cpid; while (($cpid =waitpid(-1, WNOHANG)) > 0) { if ($dispatched_children{$cpid}) { delete $dispatched_children{$cpid}; $dispatch_children--; } } };
- my $onlyone=0;
- if (defined $reqs and (scalar(@{$reqs}) == 1)) {
- $onlyone=1;
- }
-
- foreach (@{$reqs}) {
-# my $pfd;
-# my $parfd; #use a private variable so it won't trounce itself recursively
-# my $child;
- delete $_->{noderange};
-#----- added to Client.pm -----#
- if ($_->{node}) {
- $_->{noderange}->[0]=join(',',@{$_->{node}});
- }
-#----- end added to Client.pm -----#
-
- if (ref $_->{'_xcatdest'} and (ref $_->{'_xcatdest'}) eq 'ARRAY') {
- _->{'_xcatdest'} = $_->{'_xcatdest'}->[0];
- }
- if ($onlyone and not ($_->{'_xcatdest'} and xCAT::NetworkUtils->thishostisnot($_->{'_xcatdest'}))) {
- $SIG{CHLD}='DEFAULT';
- ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request);
- return;
- }
-
-# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!";
-# $parfd->autoflush(1);
-# $pfd->autoflush(1);
-# $child = xCAT::Utils->xfork;
-# if ($child) {
-# $dispatch_children++;
-# $dispatched_children{$child}=1;
-# $child_fdset->add($pfd);
-# next;
-# }
-# unless (defined $child) {
-# $dispatch_cb->({error=>['Fork failure dispatching request'],errorcode=>[1]});
-# }
-# undef $SIG{CHLD};
-# $dispatch_parentfd = $parfd;
- my @prexcatdests=();
- my @xcatdests=();
- if (ref($_->{'_xcatdest'}) eq 'ARRAY') { #If array, consider it an 'anycast' operation, broadcast done through dupe
- #requests, or an alternative join '&' maybe?
- @prexcatdests=@{$_->{'_xcatdest'}};
- } else {
- @prexcatdests=($_->{'_xcatdest'});
- }
- foreach (@prexcatdests) {
- if ($_ and /,/) {
- push @xcatdests,split /,/,$_;
- } else {
- push @xcatdests,$_;
- }
- }
- my $xcatdest;
- my $numdests=scalar(@xcatdests);
- my $request_satisfied=0;
- foreach $xcatdest (@xcatdests) {
- my $dlock;
- if ($xcatdest and xCAT::NetworkUtils->thishostisnot($xcatdest)) {
-#----- added to Client.pm -----#
- $dispatch_cb->({warning=>['XCATBYPASS is set, skipping hierarchy call to '.$_->{'_xcatdest'}.'']});
-#----- end added to Client.pm -----#
-
-# #mkpath("/var/lock/xcat/"); #For now, limit intra-xCAT requests to one at a time, to mitigate DB handle usage
-# #open($dlock,">","/var/lock/xcat/dispatchto_$xcatdest");
-# #flock($dlock,LOCK_EX);
-# $ENV{XCATHOST} = ($xcatdest =~ /:/ ? $xcatdest : $xcatdest.":3001" );
-# $$progname.=": connection to ".$ENV{XCATHOST};
-# my $errstr;
-# eval {
-# undef $_->{'_xcatdest'};
-# xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/ca.pem");
-# };
-# if ($@) {
-# $errstr=$@;
-# }
-# #unlink("/var/lock/xcat/dispatchto_$xcatdest");
-# #flock($dlock,LOCK_UN);
-# if ($errstr) {
-# if ($numdests == 1) {
-# dispatch_callback({error=>["Unable to dispatch command to ".$ENV{XCATHOST}.", command will not make changes to that server ($errstr)"],errorcode=>[1]});
-# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.": ".$errstr);
-# } else {
-# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.", trying other service nodes: ".$errstr);
-# }
-# next;
-# } else {
-# $request_satisfied=1;
-# last;
-# }
- } else {
- $$progname.=": locally executing";
- $SIG{CHLD}='DEFAULT';
-# ${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_callback,\&do_request);
-#----- changed in Client.pm -----#
- ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request);
-#----- end changed in Client.pm -----#
- last;
- }
- }
-# if ($numdests > 1 and not $request_satisfied) {
-# xCAT::MsgUtils->message("S","Error dispatching a request to all possible service nodes for request");
-# dispatch_callback({error=>["Failed to dispatch command to any of the following service nodes: ".join(",",@xcatdests)],errorcode=>[1]});
-# }
-
-# xexit;
- }
-#while (($dispatch_children > 0) and ($child_fdset->count > 0)) { relay_dispatch($child_fdset) }
-#while (relay_dispatch($child_fdset)) { } #Potentially useless drain.
-}
-
-
-
-###################################
-# do_request
-# called from a plugin to execute another xCAT plugin command internally
-#
-# NOTE: This is copied from xcatd (last merge 11/23/09).
-# Will eventually move to using common source....
-###################################
-sub do_request {
- my $req = shift;
- my $second = shift;
- my $rsphandler = \&build_response;
- my $sock = undef;
- if ($second) {
- if (ref($second) eq "CODE") {
- $rsphandler = $second;
- } elsif (ref($second) eq "GLOB") {
- $sock = $second;
- }
- }
-
- #my $sock = shift; #If no sock, will return a response hash
- if ($cmd_handlers{$req->{command}->[0]}) {
- return plugin_command($req,$sock,$rsphandler);
- } elsif ($req->{command}->[0] eq "noderange" and $req->{noderange}) {
- my @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]);
- my %resp;
- if (xCAT::NodeRange::nodesmissed()) {
- $resp{warning}="Invalid nodes in noderange:".join ',',xCAT::NodeRange::nodesmissed() ."\n";
- }
- $resp{serverdone} = {};
- @{$resp{node}}=@nodes;
- if ($req->{transid}) {
- $resp{transid}=$req->{transid}->[0];
- }
- if ($sock) {
- print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1);
- } else {
- return (\%resp);
- }
- } else {
- my %resp=(error=>"Unsupported request");
- $resp{serverdone} = {};
- if ($req->{transid}) {
- $resp{transid}=$req->{transid}->[0];
- }
- if ($sock) {
- print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1);
- } else {
- return (\%resp);
- }
- }
-}
-
-
-###################################
-# build_response
-# This callback handles responses from nested level plugin calls.
-# It builds a merged hash of all responses that gets passed back
-# to the calling plugin.
-# Note: Need to create a "deep clone" of this response to add to the
-# return, otherwise next time through the referenced data is overwritten
-#
-###################################
-sub build_response {
- my $rsp = shift;
- require Storable;
- foreach (keys %$rsp) {
- my $subresp = Storable::dclone($rsp->{$_});
- push (@{$Main::resps->{$_}}, @{$subresp});
- }
-}
-
-
-
-} # end of submit_request()
-
-####################################
-# populates all the site attributes into %::XCATSITEVALS
-# This is used with XCATBYPASS=1
-###################################
-sub populate_site_hash {
- %::XCATSITEVALS=();
- my $sitetab = xCAT::Table->new('site',-create=>0);
- unless ($sitetab) {
- print ("ERROR: Unable to open basic site table for configuration\n");
- return;
- }
- my @records = $sitetab->getAllAttribs(qw/key value/);
- foreach (@records) {
- $::XCATSITEVALS{$_->{key}}=$_->{value};
- }
-}
-
-
-
-##########################################
-# handle_response is a default callback that can be passed into submit_request()
-# It is invoked repeatedly by submit_request() 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:
-#
-#
-# node1
-#
-# node1 desc
-# node1 contents
-#
-#
-#
-# node2
-#
-# node2 desc
-# node2 contents
-#
-#
-#
-#
-# Results are printed as:
-# node_name: desc: contents
-##########################################
-sub handle_response {
- my $rsp = shift;
- if ($ENV{'XCATSHOWXML'}) {
- my $xmlrec=XMLout($rsp,RootName=>'xcatresponse',NoAttr=>1,KeyAttr=>[]);
- print "$xmlrec\n";
- return;
- }
-#print "in handle_response\n";
- # Handle errors
- if (defined($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->{error}) {
-#print "printing error\n";
- if (ref($rsp->{error}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{error}}) {
- if ($rsp->{NoErrorPrefix}) {
- print STDERR "$text\n";
- } else {
- print STDERR "Error: $text\n";
- }
- }
- }
- else {
- if ($rsp->{NoErrorPrefix}) {
- print STDERR ($rsp->{error}."\n");
- } else {
- print STDERR ("Error: ".$rsp->{error}."\n");
- }
- }
- }
- if ($rsp->{warning}) {
-#print "printing warning\n";
- if (ref($rsp->{warning}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{warning}}) {
- if ($rsp->{NoWarnPrefix}) {
- print STDERR "$text\n";
- } else {
- print STDERR "Warning: $text\n";
- }
- }
- }
- else {
- if ($rsp->{NoWarnPrefix}) {
- print STDERR ($rsp->{warning}."\n");
- } else {
- print STDERR ("Warning: ".$rsp->{warning}."\n");
- }
- }
- }
- if ($rsp->{info}) {
-#print "printing info\n";
- if (ref($rsp->{info}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{info}}) {
- print "$text\n";
- }
- }
- else {
- print ($rsp->{info}."\n");
- }
- }
-
- if ($rsp->{sinfo}) {
- if (ref($rsp->{sinfo}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{sinfo}}) {
- print "$text\r"; $|++;
- }
- }
- else {
- print ($rsp->{sinfo}."\r"); $|++;
- }
- }
-
-
-
- # Handle {node} structure
- my $errflg=0;
- my $nodes=($rsp->{node});
- unless (ref $nodes eq 'ARRAY') {
- $nodes = [$nodes];
- }
- if (scalar @{$nodes}) {
-#print "printing node\n";
- my $node;
- foreach $node (@$nodes) {
- my $desc;
- if (ref($node->{name}) eq 'ARRAY') {
- $desc=$node->{name}->[0];
- } else {
- $desc=$node->{name};
- }
- 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->{error}) {
- $desc.=": Error: ".$node->{error}->[0];
- $errflg=1;
- }
- if ($node->{warning}) {
- $desc.=": Warning: ".$node->{warning}->[0];
- $errflg=1;
- }
- if ($node->{data}) {
- if (ref(\($node->{data})) eq 'SCALAR') {
- $desc=$desc.": ".$node->{data};
- } elsif (ref($node->{data}) eq 'HASH') {
- if ($node->{data}->{desc}) {
- if (ref($node->{data}->{desc}) eq 'ARRAY') {
- $desc=$desc.": ".$node->{data}->{desc}->[0];
- } else {
- $desc=$desc.": ".$node->{data}->{desc};
- }
- }
- if ($node->{data}->{contents}) {
- if (ref($node->{data}->{contents}) eq 'ARRAY') {
- $desc="$desc: ".$node->{data}->{contents}->[0];
- } else {
- $desc="$desc: ".$node->{data}->{contents};
- }
- }
- } elsif (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) {
- if ($errflg == 1) {
- print STDERR ("$desc\n");
- } else {
- print "$desc\n";
- }
- }
- }
- }
-
- # Handle {data} structure with no nodes
- if ($rsp->{data}) {
-#print "printing data\n";
- 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
-
-
-
-
-
-
diff --git a/xCAT-server/lib/xcat/plugins/imgcapture.pm b/xCAT-server/lib/xcat/plugins/imgcapture.pm
index bd4f881de..f0aa71fc9 100644
--- a/xCAT-server/lib/xcat/plugins/imgcapture.pm
+++ b/xCAT-server/lib/xcat/plugins/imgcapture.pm
@@ -123,7 +123,7 @@ sub process_request {
# Handle image capture separately for s390x
if ($arch eq 's390x') {
eval { require xCAT_plugin::zvm; }; # Load z/VM plugin dynamically
- xCAT_plugin::zvm->imageCapture($callback, $node, $os, $arch, $profile, $osimg, $device);
+ xCAT_plugin::zvm->imageCapture($callback, $node, $os, $arch, $type, $profile, $osimg, $device);
return;
}
diff --git a/xCAT-server/lib/xcat/plugins/imgport.pm b/xCAT-server/lib/xcat/plugins/imgport.pm
index 9e3e2af9a..e09706659 100644
--- a/xCAT-server/lib/xcat/plugins/imgport.pm
+++ b/xCAT-server/lib/xcat/plugins/imgport.pm
@@ -174,8 +174,15 @@ sub xexport {
my $dest = shift @ARGV;
my $cwd = $request->{cwd}; #getcwd;
$cwd = $cwd->[0];
+
+ if (!defined $remoteHost) {
+ $callback->( {data => ["Exporting $img_name to $cwd..."]});
+ }
+ else {
+ $callback->( {data => ["Exporting $img_name to $remoteHost..."]});
+ }
- $callback->( {data => ["Exporting $img_name to $cwd..."]});
+
# check if all files are in place
my $attrs = get_image_info($img_name, $callback, $node, @extra);
#print Dumper($attrs);
@@ -237,11 +244,16 @@ sub get_image_info {
$errors++;
}
- unless($attrs0->{provmethod} =~ /install|netboot|statelite|raw/){
+ unless($attrs0->{provmethod} =~ /install|netboot|statelite|raw|sysclone/){
$callback->({error=>["Exporting images with 'provemethod' " . $attrs0->{provmethod} . " is not supported. Hint: install, netboot, statelite, or raw"], errorcode=>[1]});
$errors++;
}
-
+
+ if (($attrs0->{provmethod} =~ /sysclone/) && ($attrs0->{osarch} !~ /s390x/)) {
+ $callback->({error=>["Exporting images with 'provemethod' " . $attrs0->{provmethod} . " is not supported for osarch '" . $attrs0->{osarch} ."'"], errorcode=>[1]});
+ $errors++;
+ }
+
#$attrs->{imagename} = $imagename;
if($errors){
@@ -438,7 +450,7 @@ sub get_files{
my @files;
my $dir = "$installroot/netboot/$osvers/s390x/$profile";
opendir(DIR, $dir) or $callback->({error=>["Could not open image files in directory $dir"], errorcode=>[1]});
-
+
while (my $file = readdir(DIR)) {
# We only want files in the directory that end with .img
next unless (-f "$dir/$file");
@@ -449,7 +461,7 @@ sub get_files{
if (@files) {
$attrs->{rawimagefiles}->{files} = [@files];
}
-
+
closedir(DIR);
}
else {
@@ -465,7 +477,7 @@ sub get_files{
$attrs->{linuximage}->{pkglist} = $temp;
}
}
-
+
@arr = ("$installroot/netboot");
my $rootimgdir=$attrs->{linuximage}->{rootimgdir};
my $ramdisk;
@@ -489,27 +501,27 @@ sub get_files{
$rootimg = look_for_file('rootimg.gz', $callback, $attrs, @arr);
}
unless($ramdisk){
- $callback->({error=>["Couldn't find ramdisk (initrd-stateless.gz) for $imagename"],errorcode=>[1]});
- $errors++;
- }else{
- $attrs->{ramdisk} = $ramdisk;
- }
+ $callback->({error=>["Couldn't find ramdisk (initrd-stateless.gz) for $imagename"],errorcode=>[1]});
+ $errors++;
+ }else{
+ $attrs->{ramdisk} = $ramdisk;
+ }
unless($kernel){
- $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]});
- $errors++;
- }else{
- $attrs->{kernel} = $kernel;
- }
+ $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]});
+ $errors++;
+ }else{
+ $attrs->{kernel} = $kernel;
+ }
unless($rootimg){
- $callback->({error=>["Couldn't find rootimg (rootimg.gz) for $imagename"],errorcode=>[1]});
- $errors++;
- }else{
- $attrs->{rootimg} = $rootimg;
- }
- }
- } elsif ($provmethod =~ /statelite/) {
+ $callback->({error=>["Couldn't find rootimg (rootimg.gz) for $imagename"],errorcode=>[1]});
+ $errors++;
+ }else{
+ $attrs->{rootimg} = $rootimg;
+ }
+ }
+ } elsif ($provmethod =~ /statelite/) {
@arr = ("$installroot/custom/netboot", "$xcatroot/share/xcat/netboot");
#get .pkglist file
if (! $attrs->{linuximage}->{pkglist}) {
@@ -541,24 +553,24 @@ sub get_files{
}
unless($kernel){
- $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]});
- $errors++;
- }else{
- $attrs->{kernel} = $kernel;
- }
+ $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]});
+ $errors++;
+ }else{
+ $attrs->{kernel} = $kernel;
+ }
unless($ramdisk){
- $callback->({error=>["Couldn't find ramdisk (initrd-statelite.gz) for $imagename"],errorcode=>[1]});
- $errors++;
- }else{
- $attrs->{ramdisk} = $ramdisk;
- }
- }
+ $callback->({error=>["Couldn't find ramdisk (initrd-statelite.gz) for $imagename"],errorcode=>[1]});
+ $errors++;
+ }else{
+ $attrs->{ramdisk} = $ramdisk;
+ }
+ }
}
- if (( $provmethod =~ /raw/ ) and ( $arch =~ /s390x/ )) {
+ if (( $provmethod =~ /raw|sysclone/ ) and ( $arch =~ /s390x/ )) {
my @files;
- my $dir = "$installroot/raw/$osvers/s390x/$profile";
+ my $dir = "$installroot/$provmethod/$osvers/s390x/$profile";
opendir(DIR, $dir) or $callback->({error=>["Could not open image files in directory $dir"], errorcode=>[1]});
while (my $file = readdir(DIR)) {
@@ -634,32 +646,52 @@ sub look_for_file {
}
-# here's where we make the tarball
+#-------------------------------------------------------
+
+=head3 make_bundle
+
+ Description : Makes the image bundle tar ball.
+ Arguments : Image name from the command line
+ Destination command line parameter, i.e. name of the tar ball. For a
+ remote host this can include the target directory.
+ Remote host parameter from the command line, if specified
+ Image attributes from the osimage table
+ callback
+ Current working directory
+ Returns : None
+ Example : make_bundle( $img_name, $dest, $remoteHost, $attrs, $callback, $cwd );
+
+=cut
+
+#-------------------------------------------------------
sub make_bundle {
my $imagename = shift;
my $dest = shift;
my $remoteHost = shift;
my $attribs = shift;
my $callback = shift;
-
- # tar ball is made in local working directory. Sometimes doing this in /tmp
- # is bad. In the case of my development machine, the / filesystem was nearly full.
- # so doing it in cwd is easy and predictable.
my $dir = shift;
- #my $dir = getcwd;
+ my $rc;
+
+ # Determine the local working directory. It could be specified in the site table
+ # or we will default to the current working directory which was passed to this routine.
+ my @siteEntries = xCAT::TableUtils->get_site_attribute("tmpdir");
+ my $workDir = $siteEntries[0];
+ if (!$workDir) {
+ $workDir = $dir;
+ }
# get rid of spaces and put in underlines.
$imagename =~ s/\s+/_/g;
- # we may find that cwd doesn't work, so we use the request cwd.
- my $ttpath = mkdtemp("$dir/imgexport.$$.XXXXXX");
+ # Create the directory in which we collect the files prior to tarring them.
+ my $ttpath = mkdtemp("$workDir/imgexport.$$.XXXXXX");
$callback->({data=>["Creating $ttpath..."]}) if $::VERBOSE;
my $tpath = "$ttpath/$imagename";
mkdir("$tpath");
chmod 0755,$tpath;
-
#for statelite
if ($attribs->{osimage}->{provmethod} eq 'statelite') {
#copy the rootimgdir over
@@ -670,6 +702,10 @@ sub make_bundle {
$attribs->{'rootimgtree'} = "$rootimgdir/rootimgtree.gz";
} else {
$callback->({error=>["Couldn't locate the root image directory. "],errorcode=>[1]});
+ $rc = system("rm -rf $ttpath");
+ if ($rc) {
+ $callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]});
+ }
return 0;
}
@@ -677,6 +713,10 @@ sub make_bundle {
my $lftab= xCAT::Table->new("litefile" ,-create=>1);
if (!$lftab) {
$callback->({error=>["Could not open the litefile table."],errorcode=>[1]});
+ $rc = system("rm -rf $ttpath");
+ if ($rc) {
+ $callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]});
+ }
return 0;
}
@@ -777,7 +817,7 @@ sub make_bundle {
# Copy any raw image files. Multiple files can exist (used by s390x)
if ($attribs->{rawimagefiles}->{files}) {
foreach my $fromf (@{$attribs->{rawimagefiles}->{files}}) {
- my $rc = system("cp $fromf $tpath");
+ $rc = system("cp $fromf $tpath");
if ($rc != 0) {
$callback->({error=>["Unable to copy the raw image file $fromf."], errorcode=>[1]});
$rc = system("rm -rf $ttpath");
@@ -806,30 +846,39 @@ sub make_bundle {
}
}
- # If this is an export to a remote host then split the destination into the
- # remote directory portion and the name of the export bundle.
- my $remoteDest;
- if (defined $remoteHost) {
- $remoteDest = $dest;
- if (defined $dest) {
- $dest = (split( '/', $dest))[-1];
- }
- }
-
# now get right below all this stuff and tar it up.
chdir($ttpath);
$callback->( {data => ["Inside $ttpath."]});
- unless($dest){
- $dest = "$dir/$imagename.tgz";
- }
- # if no absolute path specified put it in the cwd
- unless($dest =~ /^\//){
- $dest = "$dir/$dest";
+ # Determine the name of the bundle that we will create.
+ my ($bundleName, $destDir);
+ if (defined $dest) {
+ ($bundleName, $destDir) = fileparse($dest);
+ if ($bundleName eq '') {
+ $bundleName="$imagename.tgz";
+ }
+ } else {
+ $bundleName="$imagename.tgz";
+ }
+
+
+ # Determine the full file specification of the image bundle.
+ my $remoteDest;
+ my $tempBundle;
+ if (defined $remoteHost) {
+ # For a remote host, we need both a local build bundle
+ # and the final remote bundle file specification.
+ $tempBundle = mktemp("$workDir/imgexport.$$.XXXXXX");
+ chomp($tempBundle);
+ $dest = $tempBundle;
+ $remoteDest = "$destDir$bundleName";
+ }
+ else {
+ # Local imgexports go to the current working directory
+ $dest = "$dir/$bundleName";
}
$callback->( {data => ["Compressing $imagename bundle. Please be patient."]});
- my $rc;
if($::VERBOSE){
$callback->({data => ["tar czvf $dest . "]});
$rc = system("tar czvf $dest . ");
@@ -854,28 +903,48 @@ sub make_bundle {
if (defined $remoteHost) {
my $remoteFile = $remoteHost . ':' . $remoteDest;
- $callback->({data=>["Moving the image bundle to the remote system"]});
+ $callback->({data=>["Moving the image bundle to the remote system location $remoteDest"]});
$rc = system("/usr/bin/scp -B $dest $remoteFile");
if ($rc) {
- $callback->({error=>["Unable to copy the image bundle to the remote host"], errorcode=>[1]});
- }
-
- # Remove the image bundle that was sent to the remote system.
- $rc = system("rm $dest");
- if ($rc) {
- $callback->({error=>["Failed to clean up image bundle $dest"], errorcode=>[1]});
+ $callback->({error=>["Unable to copy the image bundle $bundleName to the remote host"], errorcode=>[1]});
}
}
}
- chdir($dir);
+ # Remove the temporary image bundle if it is still around (for remote exports).
+ if (-e $tempBundle) {
+ $rc = system("rm -f $tempBundle");
+ if ($rc) {
+ $callback->({error=>["Failed to clean up the temporary image bundle $tempBundle"], errorcode=>[1]});
+ }
+ }
+
+ # Remove the directory that we used to collect the files prior to creating the tar ball.
+ chdir($dir);
$rc = system("rm -rf $ttpath");
if ($rc) {
$callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]});
- return;
- }
+ }
+
+ return;
}
+#-------------------------------------------------------
+
+=head3 extract_bundle
+
+ Description : Extract the files from the image tar ball.
+ Arguments : Request
+ callback
+ nodes
+ New profile name to use for the image, if specified.
+ Remote host parameter from the command line
+ Returns : None
+ Example : extract_bundle( $request, $callback, $nodes, $new_profile, $remoteHost );
+
+=cut
+
+#-------------------------------------------------------
sub extract_bundle {
my $request = shift;
#print Dumper($request);
@@ -889,31 +958,43 @@ sub extract_bundle {
my $data;
my $datas;
my $error = 0;
+ my $bundleCopy;
my $bundle = shift @ARGV;
- # extract the image in temp path in cwd
+ # Determine the current working directory.
my $dir = $request->{cwd}; #getcwd;
$dir = $dir->[0];
#print Dumper($dir);
- # If we have a remote file then move it to the xCAT MN
+ # A working directory will hold the temporary image directory.
+ # It will also hold the local copy of a remote image bundle.
+ # The directory can be defined in the site table and if not
+ # defined there then we will default to using the current working
+ # directory.
+ my @siteEntries = xCAT::TableUtils->get_site_attribute("tmpdir");
+ my $workDir = $siteEntries[0];
+ if (!$workDir) {
+ $workDir = $dir;
+ }
+
+ # If we have a remote file then transfer it to the xCAT MN first.
if (defined $remoteHost) {
- # Create unique directory for the bundle and copy the bundle to it
+ # Create unique copy the remote bundle in the working directory
my $remoteFile = "$remoteHost:$bundle";
- $dir = `/bin/mktemp -d /var/tmp/XXXXXX`;
- chomp($dir);
- $bundle = $dir . '/' . (split( '/', $bundle))[-1];
+ $bundleCopy = `/bin/mktemp $workDir/imgimport.$$.XXXXXX`;
+ chomp($bundleCopy);
$callback->({data=>["Obtaining the image bundle from the remote system"]});
- my $rc = system("/usr/bin/scp -v -B $remoteFile $dir");
+ my $rc = system("/usr/bin/scp -v -B $remoteFile $bundleCopy");
if ($rc != 0) {
- $callback->({error=>["Unable to copy the image bundle from the remote host"], errorcode=>[1]});
- $rc = rmtree $dir;
- if (! $rc) {
- $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]});
+ $callback->({error=>["Unable to copy the image bundle $bundle from the remote host"], errorcode=>[1]});
+ $rc = system("rm -rf $bundleCopy");
+ if ($rc) {
+ $callback->({error=>["Failed to remove the local copy of the remote image bundle $bundleCopy"], errorcode=>[1]});
}
return;
}
+ $bundle = $bundleCopy;
} else {
# When we are not doing a remote copy, we need to verify the bundle exists and find its exact location
unless(-r $bundle){
@@ -936,7 +1017,7 @@ sub extract_bundle {
}
}
- my $tpath = mkdtemp("$dir/imgimport.$$.XXXXXX");
+ my $tpath = mkdtemp("$workDir/imgimport.$$.XXXXXX");
$callback->({data=>["Unbundling image..."]});
my $rc;
@@ -949,6 +1030,9 @@ sub extract_bundle {
if ($rc) {
$callback->({error => ["Failed to extract bundle $bundle"],errorcode=>[1]});
+ # Remove the files in the untar directory so that we don't attempt to process
+ # a partially untarred image bundle.
+ system("rm -rf $tpath");
}
# get all the files in the tpath. These should be all the image names.
@@ -956,97 +1040,85 @@ sub extract_bundle {
# go through each image directory. Find the XML and put it into the array. If there are any
# errors then the whole thing is over and we error and leave.
foreach my $imgdir (@files){
- unless(-r "$imgdir/manifest.xml"){
- $callback->({error=>["Failed to find manifest.xml file in image bundle"],errorcode=>[1]});
- if (defined $remoteHost) {
- $rc = rmtree $dir;
- if ( ! $rc ) {
- $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]});
- }
- }
- return;
- }
- $xml = new XML::Simple;
- # get the data!
- # put it in an eval string so that it
- $data = eval { $xml->XMLin("$imgdir/manifest.xml") };
- if($@){
- $callback->({error=>["invalid manifest.xml file inside the bundle. Please verify the XML"],errorcode=>[1]});
- #my $foo = $@;
- #$foo =~ s/\n//;
- #$callback->({error=>[$foo],errorcode=>[1]});
- #foreach($@){
- # last;
- #}
- # If this was an import from a remote host then remove the directory created for the remote files.
- # We do not want to leave files hanging around that were brought from another system.
- if (defined $remoteHost) {
- $rc = rmtree $dir;
- if ( ! $rc ) {
- $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]});
- }
- }
- return;
- }
- #print Dumper($data);
- #push @{$datas}, $data;
-
- # now we need to import the files...
- unless(verify_manifest($data, $callback)){
- $error++;
- next;
+ unless(-r "$imgdir/manifest.xml"){
+ $callback->({error=>["Failed to find manifest.xml file in image bundle"],errorcode=>[1]});
+ last;
+ }
+
+ $xml = new XML::Simple;
+ # get the data!
+ # put it in an eval string so that it
+ $data = eval { $xml->XMLin("$imgdir/manifest.xml") };
+ if($@){
+ $callback->({error=>["invalid manifest.xml file inside the bundle. Please verify the XML"],errorcode=>[1]});
+ #my $foo = $@;
+ #$foo =~ s/\n//;
+ #$callback->({error=>[$foo],errorcode=>[1]});
+ #foreach($@){
+ # last;
+ #}
+ last;
+ }
+ #print Dumper($data);
+ #push @{$datas}, $data;
+
+ # now we need to import the files...
+ unless(verify_manifest($data, $callback)){
+ $error++;
+ next;
+ }
+
+ # check media first
+ unless(check_media($data, $callback)){
+ $error++;
+ next;
+ }
+
+ #change profile name if needed
+ if ($new_profile) {
+ $data=change_profile($data, $callback, $new_profile, $imgdir);
+ }
+
+ #import manifest.xml into xCAT database
+ unless(set_config($data, $callback)){
+ $error++;
+ next;
+ }
+
+ # now place files in appropriate directories.
+ unless(make_files($data, $imgdir, $callback)){
+ $error++;
+ next;
+ }
+
+ # put postscripts in the postsctipts table
+ if ($nodes) {
+ unless(set_postscripts($data, $callback, $nodes)){
+ $error++;
+ next;
+ }
+ }
+
+ my $osimage = $data->{osimage}->{imagename};
+ $callback->({data=>["Successfully imported the image $osimage."]});
}
- # check media first
- unless(check_media($data, $callback)){
- $error++;
- next;
- }
-
- #change profile name if needed
- if ($new_profile) {
- $data=change_profile($data, $callback, $new_profile, $imgdir);
- }
-
- #import manifest.xml into xCAT database
- unless(set_config($data, $callback)){
- $error++;
- next;
- }
-
- # now place files in appropriate directories.
- unless(make_files($data, $imgdir, $callback)){
- $error++;
- next;
- }
-
- # put postscripts in the postsctipts table
- if ($nodes) {
- unless(set_postscripts($data, $callback, $nodes)){
- $error++;
- next;
- }
- }
-
- my $osimage = $data->{osimage}->{imagename};
- $callback->({data=>["Successfully imported the image $osimage."]});
- }
-
- # remove temp file only if there were no problems.
- unless($error){
+ # Clean up for this routine.
+ # Remove the temp directory used for the exploded bundle
+ if ( -e $tpath ) {
$rc = system("rm -rf $tpath");
if ($rc) {
$callback->({error=>["Failed to clean up temp space $tpath"],errorcode=>[1]});
- return;
- }
+ # Don't return just yet. We want the rest of the cleanup to occur.
+ }
}
-
+
# If this was an import from a remote host then remove the directory created for the remote files.
# We do not want to leave files hanging around that were brought from another system.
- if ( defined $remoteHost ) {
- $rc = rmtree $dir;
- if ( ! $rc ) {
- $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"],errorcode=>[1]});
+ if ( -e $bundleCopy ) {
+ $rc = system("rm -rf $bundleCopy");
+ if ($rc) {
+ $callback->({error=>["Failed to remove the local copy of the remote image bundle $bundleCopy"], errorcode=>[1]});
}
}
}
@@ -1068,7 +1140,11 @@ sub change_profile {
$installdir = '/install';
}
if ($data->{linuximage}->{rootimgdir}) {
- $data->{linuximage}->{rootimgdir}="$installdir/netboot/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile";
+ if (($data->{osimage}->{osarch} eq "s390x") && ($data->{osimage}->{provmethod} =~ /raw|sysclone/)) {
+ $data->{linuximage}->{rootimgdir}="$installdir/$data->{osimage}->{provmethod}/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile";
+ } else {
+ $data->{linuximage}->{rootimgdir}="$installdir/netboot/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile";
+ }
for my $a ("kernel", "ramdisk", "rootimg", "rootimgtree", "litefile") {
if ($data->{$a}) {
@@ -1325,8 +1401,12 @@ sub verify_manifest {
}
$data->{osimage}->{osarch} =~ s/^\s*(\S*)\s*$/$1/;
- unless($data->{osimage}->{provmethod} =~ /install|netboot|statelite|raw/){
- $callback->({error=>["Importing images with 'provemethod' " . $data->{osimage}->{provmethod} . " is not supported. Hint: install, netboot, statelite, or raw"],errorcode=>[1]});
+ unless($data->{osimage}->{provmethod} =~ /install|netboot|statelite|sysclone|raw/){
+ $callback->({error=>["Importing images with 'provmethod' " . $data->{osimage}->{provmethod} . " is not supported. Hint: install, netboot, statelite, sysclone or raw"],errorcode=>[1]});
+ $errors++;
+ }
+ if (($data->{osimage}->{provmethod} =~ /sysclone/) && ($data->{osimage}->{osarch} !~ /s390x/)) {
+ $callback->({error=>["Importing images with 'provemethod' " . $data->{osimage}->{provmethod} . " is not supported for osarch '" . $data->{osimage}->{osarch} ."'"], errorcode=>[1]});
$errors++;
}
$data->{osimage}->{provmethod} =~ s/^\s*(\S*)\s*$/$1/;
@@ -1344,18 +1424,28 @@ sub verify_manifest {
$callback->({info => ['this is an esx image']});
# do nothing for ESX
1;
- } elsif (($data->{osimage}->{provmethod} =~ /netboot/) and ($data->{osimage}->{osarch} !~ /s390x/)) {
- unless($data->{ramdisk}){
- $callback->({error=>["The 'ramdisk' field is not defined in manifest.xml."],errorcode=>[1]});
- $errors++;
- }
- unless($data->{kernel}){
- $callback->({error=>["The 'kernel' field is not defined in manifest.xml."],errorcode=>[1]});
- $errors++;
- }
- unless($data->{rootimg}){
- $callback->({error=>["The 'rootimg' field is not defined in manifest.xml."],errorcode=>[1]});
- $errors++;
+ } elsif ($data->{osimage}->{provmethod} =~ /netboot/) {
+ if ($data->{osimage}->{osarch} =~ /s390x/) {
+ if (!$data->{rawimagefiles}) {
+ $callback->({error=>["The 'rawimagefiles' section is not defined in manifest.xml."],errorcode=>[1]});
+ $errors++;
+ } elsif (!$data->{rawimagefiles}->{files}) {
+ $callback->({error=>["'files' were not specified in the 'rawimagefiles' section of manifest.xml."],errorcode=>[1]});
+ $errors++;
+ }
+ } else {
+ unless($data->{ramdisk}){
+ $callback->({error=>["The 'ramdisk' field is not defined in manifest.xml."],errorcode=>[1]});
+ $errors++;
+ }
+ unless($data->{kernel}){
+ $callback->({error=>["The 'kernel' field is not defined in manifest.xml."],errorcode=>[1]});
+ $errors++;
+ }
+ unless($data->{rootimg}){
+ $callback->({error=>["The 'rootimg' field is not defined in manifest.xml."],errorcode=>[1]});
+ $errors++;
+ }
}
}elsif($data->{osimage}->{provmethod} =~ /statelite/){
@@ -1372,6 +1462,16 @@ sub verify_manifest {
$errors++;
}
+ } elsif ($data->{osimage}->{provmethod} =~ /sysclone/) {
+ if ($data->{osimage}->{osarch} =~ /s390x/) {
+ if (!$data->{rawimagefiles}) {
+ $callback->({error=>["The 'rawimagefiles' section is not defined in manifest.xml."],errorcode=>[1]});
+ $errors++;
+ } elsif (!$data->{rawimagefiles}->{files}) {
+ $callback->({error=>["'files' were not specified in the 'rawimagefiles' section of manifest.xml."],errorcode=>[1]});
+ $errors++;
+ }
+ }
}
if($errors){
@@ -1565,7 +1665,7 @@ sub make_files {
$callback->( {data => ["Updating the litefile table."]});
my $fn=$data->{litefile};
if (!$fn) {
- $callback->({error=>["Could not find liefile.csv."],errorcode=>[1]});
+ $callback->({error=>["Could not find litefile.csv."],errorcode=>[1]});
return 1;
} elsif (! -r $fn) {
$callback->({error=>["Could not find $fn."],errorcode=>[1]});
@@ -1592,11 +1692,11 @@ sub make_files {
close(FILE);
$lftab->commit;
- $callback->( {data => ["The litetree and statelite talbes are untouched. You can update them if needed."]});
+ $callback->( {data => ["The litetree and statelite tables are untouched. You can update them if needed."]});
}
# For s390x copy all image files from the root bundle directory to the repository location
- if (($data->{osimage}->{osarch} =~ /s390x/) && (($data->{osimage}->{provmethod} =~ /raw/) || ($data->{osimage}->{provmethod} =~ /netboot/))) {
+ if (($data->{osimage}->{osarch} =~ /s390x/) && ($data->{osimage}->{provmethod} =~ /raw|netboot|sysclone/)) {
my $reposImgDir = "$installroot/$data->{osimage}->{provmethod}/$data->{osimage}->{osvers}/$data->{osimage}->{osarch}/$data->{osimage}->{profile}";
mkpath($reposImgDir);
diff --git a/xCAT-server/lib/xcat/plugins/rmimage.pm b/xCAT-server/lib/xcat/plugins/rmimage.pm
index a22c50e06..3125cbc4c 100644
--- a/xCAT-server/lib/xcat/plugins/rmimage.pm
+++ b/xCAT-server/lib/xcat/plugins/rmimage.pm
@@ -105,8 +105,8 @@ sub process_request {
if($verbose) {
$callback->({info=>["For osimage $imagename: osver = $osver, arch = $arch, profile = $profile, method = $method in osimage table"]});
}
- if (($method) && ($method ne "netboot") && ($method ne "statelite") && ($method ne "raw")) {
- $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, or raw image files"], errorcode=>[1]});
+ if (($method) && ($method ne "netboot") && ($method ne "statelite") && ($method ne "raw") && ($method ne "sysclone")) {
+ $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, sysclone or raw image files"], errorcode=>[1]});
return;
}
@@ -136,23 +136,31 @@ sub process_request {
$callback->({error=>["Invalid image name $imagename"],errorcode=>[1]});
return;
}
- if (($method ne "netboot") && ($method ne "statelite") && ($method ne "raw")) {
- $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, or raw image files"], errorcode=>[1]});
+ if (($method ne "netboot") && ($method ne "statelite") && ($method ne "raw") && ($method ne "sysclone")) {
+ $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, sysclone or raw image files"], errorcode=>[1]});
return;
}
}
-
- if ($method eq "raw") {
- $imagedir = "$installroot/$method/$osver/$arch/$profile";
+
+ if ($arch eq "s390x") {
+ if (($method eq "raw") || ($method eq "sysclone")) {
+ $imagedir = "$installroot/$method/$osver/$arch/$profile";
+ } else {
+ $imagedir = "$installroot/netboot/$osver/$arch/$profile";
+ }
} else {
$imagedir = "$installroot/netboot/$osver/$arch/$profile";
}
}
} else { # imagename is not specified
- if ($method eq "raw") {
- $imagedir = "$installroot/$method/$osver/$arch/$profile";
+ if ($arch eq "s390x") {
+ if (($method eq "raw") || ($method eq "sysclone")) {
+ $imagedir = "$installroot/$method/$osver/$arch/$profile";
+ } else {
+ $imagedir = "$installroot/netboot/$osver/$arch/$profile";
+ }
} else {
- $imagedir = "$installroot/netboot/$osver/$arch/$profile";
+ $imagedir = "$installroot/netboot/$osver/$arch/$profile";
}
}
@@ -164,7 +172,14 @@ sub process_request {
$callback->({error=>["Image directory $imagedir does not exist"],errorcode=>[1]});
return;
}
-
+
+ # Doing this extra check now because we now have a method and arch from either the node or the image name.
+ if (($method eq "sysclone") && ($arch ne "s390x")) {
+ # Only supporting removing sysclone images for s390x at this time.
+ $callback->({error=>["rmimage cannot be used to remove sysclone images for \"$arch\" architecture"], errorcode=>[1]});
+ return;
+ }
+
my @filestoremove = ("$imagedir/rootimg.gz", "$imagedir/kernel", "$imagedir/initrd-stateless.gz", "$imagedir/initrd-statelite.gz");
#some rpms like atftp mount the rootimg/proc to /proc, we need to make sure rootimg/proc is free of junk
@@ -196,7 +211,7 @@ sub process_request {
}
# For s390x, remove the image directory.
- if (($arch eq "s390x") && (-d "$imagedir") && (($method eq "raw") || ($method eq "netboot"))) {
+ if (($arch eq "s390x") && (-d "$imagedir") && (($method eq "raw") || ($method eq "netboot") || ($method eq "sysclone"))) {
$callback->({info=>["Removing directory $imagedir"]});
rmtree "$imagedir";
}
diff --git a/xCAT-server/share/xcat/scripts/xcatconf4z b/xCAT-server/share/xcat/scripts/xcatconf4z
index 605433dfa..83eb026de 100644
--- a/xCAT-server/share/xcat/scripts/xcatconf4z
+++ b/xCAT-server/share/xcat/scripts/xcatconf4z
@@ -1,5 +1,4 @@
#!/bin/sh
-# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
### BEGIN INIT INFO
# Provides: xcatconf4z
@@ -181,16 +180,20 @@ function setupIso {
# @Output:
# None
# @Code:
- # Create ISO based on transport directory
iso="/var/opt/xcat/transport.iso"
- /usr/bin/mkisofs -l -o $iso $transportdir
- # Create loop back device pointing to ISO9660 image
- nextLoopDev=`/sbin/losetup -f`
- if [[ -n $nextLoopDev ]]; then
- /sbin/losetup $nextLoopDev $iso
- else
- return
+ # If there are files in the transport directory then create an ISO system.
+ if [ "$(ls -A .)" ]; then
+ /usr/bin/mkisofs -l -o $iso $transportdir
+ fi
+
+ # If the ISO filesystem exists then create loop back device pointing
+ # to the ISO9660 image
+ if [[ -e $iso ]]; then
+ nextLoopDev=`/sbin/losetup -f`
+ if [[ -n $nextLoopDev ]]; then
+ /sbin/losetup $nextLoopDev $iso
+ fi
fi
# Execute init script (if one exists)
@@ -263,18 +266,20 @@ function setupDisk {
return
fi
- out=`stat -L --printf=%t:%T $xcat_srcFile`
+ out=`/usr/bin/stat --printf=%n ${xcat_srcFile}`
if (( $? != 0 )); then
echo "xcatconf4z $funcName (Error) Unable to stat the source file: $xcat_srcFile"
return
fi
- major=${out%:*}
- major=$(echo ${major} | sed -e 's/^ *//g')
- minor=${out#*:}
- minor=$(echo ${minor} | sed -e 's/^ *//g')
+ configFile='/etc/udev/rules.d/56-zfcp.rules'
+ tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///')
+ wwpn_lun=$(echo ${xcat_srcFile} | sed -e 's/^\/dev.*-zfcp-//')
+ wwpn=$(echo ${wwpn_lun} | sed -e 's/:0x.*//')
+ lun=$(echo ${wwpn_lun} | sed -e 's/^0x.*://')
- mknod $xcat_tgtFile b 0x$major 0x$minor
+ echo "KERNEL==\"sd*\", SYSFS{wwpn}==\"${wwpn}\", SYSFS{fcp_lun}==\"${lun}\", SYMLINK+=\"${tgtNode}%n\"" >> ${configFile}
+ udevadm trigger --sysname-match=sd*
##########################################################################
# Handle removing a file system node
@@ -289,8 +294,11 @@ function setupDisk {
return
fi
- umount "$xcat_tgtFile"
- rm -f "$xcat_tgtFile"
+ configFile='/etc/udev/rules.d/56-zfcp.rules'
+ tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///')
+
+ sed -i -e /SYMLINK+=\"${tgtNode}%n\"/d ${configFile}
+ udevadm trigger --sysname-match=sd*
##########################################################################
# Handle adding a SCSI volume
@@ -463,22 +471,23 @@ function setupDisk {
# Main Code Section
############################################################################
case "$1" in
- start)
- if [[ -z "$authorizedSenders" ]]; then
- echo "xcatconf4z is disabled. There are no authorized senders of configuration files."
- else
- echo "xcatconf4z is starting"
- transportdir="/var/opt/xcat/transport"
- rm -Rf $transportdir
- /bin/mkdir -p $transportdir
- cd $transportdir
-
- # Get Linux version
- getOsVersion
-
+ start)
+ echo "xcatconf4z is starting"
+ transportdir="/var/opt/xcat/transport"
+ rm -Rf $transportdir
+ /bin/mkdir -p $transportdir
+ cd $transportdir
+
+ # Get Linux version
+ getOsVersion
+
+ if [[ -n "$authorizedSenders" ]]; then
pullReader
- setupIso
- fi
+ else
+ echo "xcatconf4z is disabled from accepting configuration reader files."
+ fi
+
+ setupIso
;;
stop|status|restart|reload|force-reload)
# Do nothing