diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 3b1f4fdb3..5a1a2658c 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -658,145 +658,6 @@ sub _execute_dsh #---------------------------------------------------------------------------- -=head3 - execute_dshservice - - This is the main driver routine for an instance of the dshservice command. - Given the options configured in the $options hash table, the routine - executes the actions specified by the routine - - Arguments: - $options - options hash table describing dshservice configuration options - - Returns: - None - - Globals: - None - - Error: - None - - Example: - - Comments: - -=cut - -sub execute_dshservice -{ - my ($class, $options) = @_; - - if ($$options{'all-valid-contexts'}) - { - scalar(@dsh_valid_contexts) || xCAT::DSHCLI->get_valid_contexts; - - foreach my $context (sort(@dsh_valid_contexts)) - { - print STDOUT "$context\n"; - } - } - - my $rsp = {}; - my $result; - if ($$options{'query'}) - { - xCAT::DSHCLI->config_default_context($options); - - if (!(-e "$::CONTEXT_DIR$$options{'context'}.pm")) - { - $rsp->{data}->[0] = " Context: $$options{'context'} not valid."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - - return ++$result; - } - - if ($$options{'nodes'}) - { - my %resolved_targets = (); - my %unresolved_targets = (); - my %context_targets = (); - my @nodenames; - - xCAT::DSHCLI->resolve_targets($options, \%resolved_targets, - \%unresolved_targets, \%context_targets); - - foreach my $user_node (sort keys(%resolved_targets)) - { - my $properties = $resolved_targets{$user_node}; - my $context = $$properties{context}; - my $node = $$properties{hostname}; - $context->query_node($node); - } - foreach my $user_node (sort keys(%unresolved_targets)) - { - my $properties = $unresolved_targets{$user_node}; - my $context = $$properties{context}; - my $node = $$properties{hostname}; - $context->query_node($node); - } - - } - if ($$options{'defaults'}) - { - scalar(@dsh_valid_contexts) || xCAT::DSHCLI->get_valid_contexts; - - print STDOUT "DefaultContext=$$options{'context'}\n"; - - my $dsh_defaults = xCAT::DSHCLI->get_dsh_defaults; - - foreach my $context (sort keys(%$dsh_defaults)) - { - my $context_defaults = $$dsh_defaults{$context}; - foreach my $key (sort keys(%$context_defaults)) - { - my $key_label = $key; - ($key eq 'RemoteShell') - && ($key_label = 'NodeRemoteShell'); - print STDOUT - "$context:$key_label=$$context_defaults{$key}\n"; - } - } - } - } - - if ($$options{'resolve'}) - { - my %resolved_targets = (); - my %unresolved_targets = (); - my %context_targets = (); - - xCAT::DSHCLI->config_default_context($options); - - if (!(-e "$::CONTEXT_DIR$$options{'context'}.pm")) - { - - $rsp->{data}->[0] = " Context: $$options{'context'} not valid."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return ++$result; - } - - xCAT::DSHCLI->resolve_targets($options, \%resolved_targets, - \%unresolved_targets, \%context_targets); - - my @targets = (sort keys(%resolved_targets)); - push @targets, (sort keys(%unresolved_targets)); - - foreach my $target (@targets) - { - print STDOUT "$target\n"; - } - } - - if ($$options{'show-config'}) - { - xCAT::DSHCLI->show_dsh_config($options); - } - -} - -#---------------------------------------------------------------------------- - =head3 fork_fanout_dcp @@ -4179,20 +4040,44 @@ sub parse_and_run_dcp return; } - if ($options{'rsyncSN'}) - { - $syncSN = 1; - } - # if rsyncing the nodes + # if rsyncing the nodes or service nodes if ($options{'File'}) { - my $rc = - &parse_rsync_input_file(\@nodelist, \%options, - $options{'File'}, $syncSN); + + # if syncing a service node + if ($options{'rsyncSN'}) + { + $syncSN = 1; + } + + # set default sync dir on service node + my $synfiledir = "/var/xcat/syncfiles"; + + # get the directory on the servicenode to put the rsync files in + my @syndir = xCAT::Utils->get_site_attribute("SNsyncfiledir"); + if ($syndir[0]) + { + $synfiledir = $syndir[0]; + } + + my $rc; + my $syncfile = $options{'File'}; + if (xCAT::Utils->isServiceNode()) + { # running on service node + $rc = + &parse_rsync_input_file_on_SN(\@nodelist, \%options, $syncfile, + $synfiledir); + } + else + { # running on MN + $rc = + &parse_rsync_input_file_on_MN(\@nodelist, \%options, $syncfile, + $syncSN, $synfiledir); + } if ($rc == 1) { - $rsp->{data}->[0] = "Error parsing the rsync file"; + $rsp->{data}->[0] = "Error parsing the rsync file:$syncfile."; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); return; } @@ -4377,9 +4262,10 @@ sub rsync_to_image #------------------------------------------------------------------------------- =head3 - parse_rsync_input_file + parse_rsync_input_file_on_MN + - This parses the -F rsync input file. + This parses the -F rsync input file on the Management node. File format: /.../file1 -> /.../dir1/filex @@ -4387,7 +4273,11 @@ sub rsync_to_image /.../file1 /..../filex -> /...../dir1 Arguments: - Input nodelist,options, pointer to the sync file + Input nodelist,options, pointer to the sync file,flag is + syncing the service node and + the directory to syn the files to on the service node + based on defaults or the site.SNsyncfiledir attribute, + if syncing a service node for hierarchical support. Returns: Errors if invalid options or the executed dcp command @@ -4406,10 +4296,10 @@ sub rsync_to_image #------------------------------------------------------------------------------- -sub parse_rsync_input_file +sub parse_rsync_input_file_on_MN { use File::Basename; - my ($nodes, $options, $input_file, $rsyncSN) = @_; + my ($nodes, $options, $input_file, $rsyncSN, $syncdir) = @_; my @dest_host = @$nodes; my $process_line = 0; open(INPUTFILE, "< $input_file") || die "File $input_file does not exist\n"; @@ -4444,10 +4334,12 @@ sub parse_rsync_input_file { # if syncing the Service Node, file goes to the same place - # from which it came + # where it was on the MN but in the syncdir on the service + # node if ($rsyncSN == 1) { # syncing the SN - $dest_dir = dirname($srcfile); + $dest_dir = $syncdir; # the SN sync dir + $dest_dir .= dirname($srcfile); $dest_dir =~ s/\s*//g; #remove blanks } $$options{'destDir_srcFile'}{$target_node}{$dest_dir} ||= @@ -4510,6 +4402,133 @@ sub parse_rsync_input_file #------------------------------------------------------------------------------- +=head3 + parse_rsync_input_file_on_SN + + This parses the -F rsync input file on the Service node. + + File format: + /.../file1 -> /.../dir1/filex + /.../file1 -> /.../dir1 + /.../file1 /..../filex -> /...../dir1 + + Arguments: + Input nodelist,options, pointer to the sync file and + the directory to syn the files from + based on defaults or the site.SNsyncfiledir attribute, + + Returns: + Errors if invalid options or the executed dcp command + + Globals: + + + Error: + None + + Example: + + Comments: + +=cut + +#------------------------------------------------------------------------------- + +sub parse_rsync_input_file_on_SN +{ + use File::Basename; + my ($nodes, $options, $input_file, $syncdir) = @_; + my @dest_host = @$nodes; + my $process_line = 0; + open(INPUTFILE, "< $input_file") || die "File $input_file does not exist\n"; + while (my $line = ) + { + chomp $line; + if ($line =~ /(.+) -> (.+)/) + { + $process_line = 1; + my $src_file = $1; + my $dest_file = $2; + $dest_file =~ s/[\s;]//g; + my $dest_dir; + if (-d $dest_file) + { # if a directory , just use + $dest_dir = $dest_file; + } + else + { # strip off the file + $dest_dir = dirname($dest_file); + } + $dest_dir =~ s/\s*//g; #remove blanks + + my @srcfiles = (split ' ', $src_file); + + foreach my $target_node (@dest_host) + { + $$options{'destDir_srcFile'}{$target_node} ||= {}; + + # for each file on the line + foreach my $srcfile (@srcfiles) + { + my $tmpsrcfile = $syncdir; # add syndir on front + $tmpsrcfile .= $srcfile; + $srcfile = $tmpsrcfile; + $$options{'destDir_srcFile'}{$target_node}{$dest_dir} ||= + {}; + + # can be full file name for destination or just the + # directory name. For source must be full path + my $src_basename = basename($srcfile); # get file name + + my $dest_basename; # destination file name + if (-d $dest_file) + { # if a directory, get filename from src + $dest_basename = $src_basename; + } + else + { # get the file name from the destination + $dest_basename = basename($dest_file); + } + $$options{'destDir_srcFile'}{$target_node}{$dest_dir} ||= + $dest_basename =~ s/[\s;]//g; + + # if the filename will be the same at the destination + if ($src_basename eq $dest_basename) + { + $$options{'destDir_srcFile'}{$target_node}{$dest_dir} + {'same_dest_name'} ||= []; + push @{$$options{'destDir_srcFile'}{$target_node} + {$dest_dir}{'same_dest_name'}}, $srcfile; + } + else # changing file names + { + $$options{'destDir_srcFile'}{$target_node}{$dest_dir} + {'diff_dest_name'} ||= {}; + $$options{'destDir_srcFile'}{$target_node}{$dest_dir} + {'diff_dest_name'}{$srcfile} = $dest_basename; + } + + } + } + } + } + close INPUTFILE; + if ($process_line == 0) + { # no valid lines in the file + my $rsp = {}; + $rsp->{data}->[0] = "Found no lines to process in $input_file."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return 1; + } + else + { + $$options{'nodes'} = join ',', keys %{$$options{'destDir_srcFile'}}; + } + return 0; +} + +#------------------------------------------------------------------------------- + =head3 runlocal_on_rootimg @@ -4837,7 +4856,8 @@ sub show_dsh_config #------------------------------------------------------------------------------- -=head3 get_config +=head3 + get_config Substitute specific keywords in hash e.g. config file: