diff --git a/docs/documentation/plugins/node-control/index.asciidoc b/docs/documentation/plugins/node-control/index.asciidoc index bdbd8f8eb..c43c1d8ba 100644 --- a/docs/documentation/plugins/node-control/index.asciidoc +++ b/docs/documentation/plugins/node-control/index.asciidoc @@ -110,9 +110,9 @@ The pre hooks can abort the update process by exiting != 0. All hooks can make use of the following environment variables: -- `PEER_NAME`: name of the backend as set in the thruk.conf. -- `PEER_KEY`: internal id of the backend. -- `HOST_NAME`: remote host name of this backend. -- `SITE_NAME`: site name which will be updated. -- `OMD_VERSION`: current omd version that site is running. -- `OMD_UPDATE`: omd version that'll be used for the update. +- `PEER_NAME`: name of the backend as set in the thruk.conf. +- `PEER_KEY`: internal id of the backend. +- `OMD_HOST_NAME`: remote host name of this backend. +- `SITE_NAME`: site name which will be updated. +- `FROM_OMD_VERSION`: current omd version that site is running. +- `OMD_UPDATE`: omd version that'll be used for the update. diff --git a/lib/Thruk/Backend/Peer.pm b/lib/Thruk/Backend/Peer.pm index d60472d7d..a43959f92 100644 --- a/lib/Thruk/Backend/Peer.pm +++ b/lib/Thruk/Backend/Peer.pm @@ -333,7 +333,7 @@ sub cmd { if($background_options) { $background_options->{"background"} = 1; $background_options->{"cmd"} = $cmd; - $background_options->{"env"} = $env; + $background_options->{"env"} = $env if $env; } if($self->{'type'} eq 'http') { # forward by http federation diff --git a/lib/Thruk/Utils/External.pm b/lib/Thruk/Utils/External.pm index e99eb6d10..b7a3ee210 100644 --- a/lib/Thruk/Utils/External.pm +++ b/lib/Thruk/Utils/External.pm @@ -94,6 +94,7 @@ sub cmd { clean => "remove job after displaying it if true" render => "set to a true value to render page immediatly" show_output => show console with output + log_archive => store stdout/stderr with this filename } ) @@ -200,6 +201,7 @@ sub perl { $err = $@ unless $err; $c->stats->profile(end => 'External::perl'); save_profile($c, $dir); + _save_log_archive($c, $dir, $conf->{'log_archive'}) if $conf->{'log_archive'}; if($err) { eval { Thruk::Utils::IO::write($dir."/stderr", "ERROR: perl eval failed:\n".$err, undef, 1); @@ -338,7 +340,7 @@ sub read_job { my $start = -e $job_dir.'/start' ? (stat(_))[9] : 0; my $end = -e $job_dir.'/rc' ? (stat(_))[9] : 0; - my $rc = Thruk::Utils::IO::saferead($job_dir.'/rc') // ''; + my $rc = Thruk::Utils::IO::saferead($job_dir.'/rc') // ''; # 0 is OK, everything else is an error (exit code) my $res = Thruk::Utils::IO::saferead($job_dir.'/perl_res') // ''; my $out = Thruk::Utils::IO::saferead($job_dir.'/stdout') // ''; my $err = Thruk::Utils::IO::saferead($job_dir.'/stderr') // ''; @@ -350,6 +352,7 @@ sub read_job { $cmd =~ s%^\$VAR1\s*=\s*%%gmx; $cmd =~ s%\n$%%gmx; } + chomp($rc); if($rc !~ m/^\d*$/mx) { $rc = -1; } my($hostid, $hostname) = split(/\n/mx, $host); @@ -358,20 +361,20 @@ sub read_job { 'id' => $id, 'pid' => $pid, 'user' => $user, - 'host_id' => $hostid // "", + 'host_id' => $hostid // "", 'host_name' => $hostname // "", 'cmd' => $cmd, - 'rc' => $rc // '', + 'rc' => $rc // '', 'perl_res' => $res // '', 'stdout' => $out // '', 'stderr' => $err // '', 'is_running' => 0+$is_running, 'time' => 0+$time, 'start' => 0+($start || 0), - 'end' => 0+($end || 0), + 'end' => 0+($end || 0), 'percent' => 0+$percent, - 'message' => $message // '', - 'forward' => $forward // '', + 'message' => $message // '', + 'forward' => $forward // '', 'show_output'=> $show_output // 0, 'remaining' => 0+$remaining, }; @@ -772,6 +775,18 @@ sub save_profile { return; } +############################################## +# save stdout and stderr into new logfile +sub _save_log_archive { + my($c, $job_dir, $logfile) = @_; + + my $out = Thruk::Utils::IO::saferead($job_dir.'/stdout') // ''; + my $err = Thruk::Utils::IO::saferead($job_dir.'/stderr') // ''; + Thruk::Utils::IO::write($logfile, $out.$err); + + return; +} + ############################################## =head2 do_child_stuff diff --git a/lib/Thruk/Utils/IO.pm b/lib/Thruk/Utils/IO.pm index 98c2a6518..8baca5509 100644 --- a/lib/Thruk/Utils/IO.pm +++ b/lib/Thruk/Utils/IO.pm @@ -871,6 +871,10 @@ sub cmd { require Thruk::Utils::Encode unless $options->{'no_decode'}; + if(ref $cmd ne 'ARRAY' && $cmd !~ m/&\s*$/mx) { + $cmd = ["/bin/sh", "-c", $cmd]; + } + my($rc, $output); if(ref $cmd eq 'ARRAY') { my $prog = shift @{$cmd}; @@ -895,15 +899,21 @@ sub cmd { $sel->remove($fh); next; } else { + my $prefix = ""; if($options->{'output_prefix'}) { - my $prefix = $options->{'output_prefix'}; + $prefix = $options->{'output_prefix'}; if(ref $prefix eq 'CODE') { - $prefix = &{$prefix}; + $prefix = &{$prefix}(); + } + } + if($options->{'print_prefix'} || $options->{'output_prefix'}) { + for my $l (split/\n/mx, $line) { + push @lines, $prefix.$l."\n"; + print $options->{'print_prefix'}, $l, "\n" if defined $options->{'print_prefix'}; } - $line = $prefix.$line; + } else { + push @lines, $line; } - push @lines, $line; - print $options->{'print_prefix'}, $line if defined $options->{'print_prefix'}; } } } @@ -920,21 +930,15 @@ sub cmd { &timing_breakpoint('IO::cmd: '.$cmd); _debug( "running cmd: ". $cmd ) if $c; - # background process? - if($cmd =~ m/&\s*$/mx) { - local $SIG{CHLD} = 'IGNORE'; # let the system reap the childs, we don't care - if($cmd !~ m|2>&1|mx) { - _warn(longmess("cmd does not redirect output but wants to run in the background, add >/dev/null 2>&1 to: ".$cmd)) if $c; - } - $output = `$cmd`; - $rc = $?; - # rc will be -1 otherwise when ignoring SIGCHLD - $rc = 0 if $rc == -1; - } else { - $output = `$cmd`; - $rc = $?; - $output = Thruk::Utils::Encode::decode_any($output) unless $options->{'no_decode'}; + # background command + local $SIG{CHLD} = 'IGNORE'; # let the system reap the childs, we don't care + if($cmd !~ m|2>&1|mx) { + _warn(longmess("cmd does not redirect output but wants to run in the background, add >/dev/null 2>&1 to: ".$cmd)) if $c; } + $output = `$cmd`; + $rc = $?; + # rc will be -1 otherwise when ignoring SIGCHLD + $rc = 0 if $rc == -1; } if($rc == -1) { diff --git a/lib/Thruk/Utils/Log.pm b/lib/Thruk/Utils/Log.pm index cadf978e3..7c69c0a4f 100644 --- a/lib/Thruk/Utils/Log.pm +++ b/lib/Thruk/Utils/Log.pm @@ -301,7 +301,7 @@ sub _audit_log { =cut sub time_prefix { my($seconds, $microseconds) = Time::HiRes::gettimeofday; - return(sprintf("[%s,%s]", + return(sprintf("[%s,%s] ", POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime($seconds)), substr(sprintf("%06s", $microseconds), 0, 3), )); @@ -340,6 +340,39 @@ sub wrap_stdout2log_stop { return; } +############################################## + +=head2 wrap_stderr2log + + wrap stderr to warn logger. everything printed to stderr will be logged + with info level to stdout. + +=cut +sub wrap_stderr2log { + my($capture, $tmp); + ## no critic + open($capture, '>', \$tmp) or die("cannot open stdout capture: $!"); + tie *$capture, 'Thruk::Utils::Log', (*STDERR); + select $capture; + STDERR->autoflush(1); + ## use critic + return($capture); +} + +############################################## + +=head2 wrap_stderr2log_stop + + stop wrapping stderr + +=cut +sub wrap_stderr2log_stop { + ## no critic + select *STERR; + ## use critic + return; +} + ############################################## sub TIEHANDLE { my($class, $fh) = @_; diff --git a/plugins/plugins-available/node-control/lib/Thruk/NodeControl/Utils.pm b/plugins/plugins-available/node-control/lib/Thruk/NodeControl/Utils.pm index 4a48b6ba7..22e3ada03 100644 --- a/plugins/plugins-available/node-control/lib/Thruk/NodeControl/Utils.pm +++ b/plugins/plugins-available/node-control/lib/Thruk/NodeControl/Utils.pm @@ -61,7 +61,7 @@ sub get_peers { =head2 get_server - get_server($c) + get_server($c, $peer, [$config]) return server details @@ -96,7 +96,7 @@ sub get_server { $facts->{'job_checking'} = time(); $save_required = 1; } - return; + next; } my $data; eval { @@ -144,13 +144,13 @@ sub get_server { peer_key => $peer->{'key'}, peer_name => $peer->{'name'}, section => $peer->{'section'}, - gathering => $facts->{'gathering'} || 0, - cleaning => $facts->{'cleaning'} || 0, - run_all => $facts->{'run_all'} || 0, - installing => $facts->{'installing'} || 0, - updating => $facts->{'updating'} || 0, - os_updating => $facts->{'os_updating'} || 0, - os_sec_updating => $facts->{'os_sec_updating'} || 0, + gathering => $facts->{'gathering'} || 0, # job id of current gathering job or 0 + cleaning => $facts->{'cleaning'} || 0, # cleaning job id + run_all => $facts->{'run_all'} || 0, # job id when install/update/clean runs in one job + installing => $facts->{'installing'} || 0, # install job id + updating => $facts->{'updating'} || 0, # update job id + os_updating => $facts->{'os_updating'} || 0, # os update id + os_sec_updating => $facts->{'os_sec_updating'} || 0, # sec update job id host_name => $facts->{'ansible_facts'}->{'ansible_fqdn'}, omd_version => $facts->{'omd_version'} // '', omd_versions => $facts->{'omd_versions'} // [], @@ -445,27 +445,54 @@ sub omd_install { return if $facts->{'installing'}; return if($facts->{'run_all'} && !$force); + my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; + my $f = Thruk::Utils::IO::json_lock_patch($file, { 'installing' => 1, 'last_error' => '' }, { pretty => 1, allow_empty => 1 }); + + # continue in background job + my $job = Thruk::Utils::External::perl($c, { + expr => 'Thruk::NodeControl::Utils::_omd_install_step2($c, "'.$peer->{'key'}.'", "'.$version.'")', + message => 'Installing OMD '.$version, + background => 1, + log_archive => $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'_install.log', + }); + return($job); +} + +########################################################## +sub _omd_install_step2 { + my($c, $peerkey, $version) = @_; + + my $peer = $c->db->get_peer_by_key($peerkey); + my $facts = _ansible_get_facts($c, $peer, 0); my $config = config($c); + my $job = $ENV{'THRUK_JOB_ID'}; + my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; + my $f = Thruk::Utils::IO::json_lock_patch($file, { 'installing' => $job, 'last_error' => '' }, { pretty => 1, allow_empty => 1 }); + if(!$config->{'cmd_'.$facts->{'ansible_facts'}->{'ansible_pkg_mgr'}.'_pkg_install'}) { - die("package manager ".$facts->{'ansible_facts'}->{'ansible_pkg_mgr'}." not supported"); + Thruk::Utils::IO::json_lock_patch($file, { 'installing' => 0, 'last_error' => "package manager ".$facts->{'ansible_facts'}->{'ansible_pkg_mgr'}." not supported" }, { pretty => 1, allow_empty => 1 }); + return; } - my $cmd = _cmd_line($config->{'cmd_'.$facts->{'ansible_facts'}->{'ansible_pkg_mgr'}.'_pkg_install'}, { '%PKG' => $version }); - - my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; - my $f = Thruk::Utils::IO::json_lock_patch($file, { 'installing' => 1, 'last_error' => '' }, { pretty => 1, allow_empty => 1 }); + my $cmd = _cmd_line($config->{'cmd_'.$facts->{'ansible_facts'}->{'ansible_pkg_mgr'}.'_pkg_install'}, { '%PKG' => $version }); my($rc, $job); eval { - ($rc, $job) = _remote_cmd($c, $peer, $cmd, { message => 'Installing OMD '.$version }); - die("starting job failed") unless $job; + ($rc, $job) = _remote_cmd($c, $peer, $cmd, {}, undef, undef, 1); }; if($@) { $f = Thruk::Utils::IO::json_lock_patch($file, { 'installing' => 0, 'last_error' => $@ }, { pretty => 1, allow_empty => 1 }); return; } - Thruk::Utils::IO::json_lock_patch($file, { 'installing' => $job, 'last_job' => $job, 'last_error' => "" }, { pretty => 1, allow_empty => 1 }); - return($job); + # wait for 1800 sec + my $jobdata = _wait_for_job($c, $peer, $job, 2, 1800, 1); + if($jobdata && $jobdata->{'rc'} ne "0") { + update_runtime_data($c, $peer, 1); + return; + } + + update_runtime_data($c, $peer, 1); + return(1); } ########################################################## @@ -474,7 +501,7 @@ sub omd_install { omd_update($c, $peer, $version) -update site to given version on peer +update site to given version on peer in background, returns job id =cut sub omd_update { @@ -486,71 +513,94 @@ sub omd_update { my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; my $f = Thruk::Utils::IO::json_lock_patch($file, { 'updating' => 1, 'last_error' => '' }, { pretty => 1, allow_empty => 1 }); + + # continue in background job + my $job = Thruk::Utils::External::perl($c, { + expr => 'Thruk::NodeControl::Utils::_omd_update_step2($c, "'.$peer->{'key'}.'", "'.$version.'")', + message => sprintf('updating %s on %s to omd %s', $facts->{'omd_site'}, $peer->{'name'}, $version), + background => 1, + log_archive => $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'_update.log', + }); + return($job); +} + +########################################################## +sub _omd_update_step2 { + my($c, $peerkey, $version) = @_; + my $peer = $c->db->get_peer_by_key($peerkey); + my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; my $config = config($c); my $env = _get_hook_env($c, $peer, $version); + my $facts = _ansible_get_facts($c, $peer, 0); + + printf("*** updating %s on %s\n", $facts->{'omd_site'}//'', $peer->{'name'}//''); + printf("*** from: %s\n", $env->{'FROM_OMD_VERSION'} // 'unknown'); + printf("*** to: %s\n", $version); + + my $job = $ENV{'THRUK_JOB_ID'}; + Thruk::Utils::IO::json_lock_patch($file, { 'updating' => $job, 'last_job' => $job, 'last_error' => "" }, { pretty => 1, allow_empty => 1 }); if($config->{'hook_update_pre_local'}) { - my($rc, $out) = Thruk::Utils::IO::cmd($config->{'hook_update_pre_local'}, { env => $env }); + print "*** hook_update_pre_local:\n"; + my($rc, $out) = Thruk::Utils::IO::cmd($config->{'hook_update_pre_local'}, { env => $env, print_prefix => "" }); + print "*** hook_update_pre_local rc: $rc\n"; if($rc != 0) { + print "*** -> update canceled\n"; Thruk::Utils::IO::json_lock_patch($file, { 'updating' => 0, 'last_error' => sprintf("update canceled by local pre hook (rc: %d): %s", $rc, $out) }, { pretty => 1, allow_empty => 1 }); return; } } if($config->{'hook_update_pre'}) { - my($rc, $out) = _remote_cmd($c, $peer, $config->{'hook_update_pre'}, undef, $env); + print "*** hook_update_pre:\n"; + my($rc, $out) = _remote_cmd($c, $peer, $config->{'hook_update_pre'}, undef, $env, 1); + print "*** rc:$rc\n"; + print "*** output:\n".$out."\n"; if($rc != 0) { + print "*** -> update canceled\n"; Thruk::Utils::IO::json_lock_patch($file, { 'updating' => 0, 'last_error' => sprintf("update canceled by pre hook (rc: %d): %s", $rc, $out) }, { pretty => 1, allow_empty => 1 }); return; } } - # continue in background job - my $job = Thruk::Utils::External::perl($c, { - expr => 'Thruk::NodeControl::Utils::_omd_update_step2($c, "'.$peer->{'key'}.'", "'.$version.'")', - background => 1, - }); - return($job); -} - -########################################################## -sub _omd_update_step2 { - my($c, $peerkey, $version) = @_; - my $peer = $c->db->get_peer_by_key($peerkey); - my $file = $c->config->{'var_path'}.'/node_control/'.$peer->{'key'}.'.json'; - my $config = config($c); - my $env = _get_hook_env($c, $peer, $version); - - my($rc, $job); + my($rc); eval { my $root = Thruk::Base::dirname(__FILE__); - my $script = Thruk::Utils::IO::read($root."/../../../scripts/omd_update.sh"); + my $script = Thruk::Utils::IO::read($config->{'omd_update_script'} || $root."/../../../scripts/omd_update.sh"); $peer->rpc($c, 'Thruk::Utils::IO::write', 'var/tmp/omd_update.sh', $script); - $peer->rpc($c, 'Thruk::Utils::IO::write', 'var/tmp/omd_update_post.sh', ($config->{'hook_update_post'} || "")); - ($rc, $job) = _remote_cmd($c, $peer, 'OMD_UPDATE="'.$version.'" bash var/tmp/omd_update.sh', { message => 'Updating Site To '.$version, env => $env }); + ($rc, $job) = _remote_cmd($c, $peer, 'OMD_UPDATE="'.$version.'" bash var/tmp/omd_update.sh', { env => $env }, undef, $env, 1); }; if($@) { Thruk::Utils::IO::json_lock_patch($file, { 'updating' => 0, 'last_error' => $@ }, { pretty => 1, allow_empty => 1 }); return; } - Thruk::Utils::IO::json_lock_patch($file, { 'updating' => $job, 'last_job' => $job, 'last_error' => "" }, { pretty => 1, allow_empty => 1 }); - # wait for 180 sec - my $jobdata = _wait_for_job($c, $peer, $job, 3, 180, 1); + my $jobdata = _wait_for_job($c, $peer, $job, 1, 180, 1); if($jobdata && $jobdata->{'rc'} ne "0") { update_runtime_data($c, $peer, 1); return; } + if($config->{'hook_update_post'}) { + print "*** hook_update_post:\n"; + my($rc, $out) = _remote_cmd($c, $peer, $config->{'hook_update_post'}, undef, $env, 1); + print "*** rc: $rc\n"; + print "*** output:\n".$out."\n"; + } + if($config->{'hook_update_post_local'}) { - Thruk::Utils::IO::cmd($config->{'hook_update_post_local'}, { env => $env, print_prefix => "" }); + print "*** hook_update_post_local:\n"; + my($rc, $out) = Thruk::Utils::IO::cmd($config->{'hook_update_post_local'}, { env => $env, print_prefix => "" }); + print "*** hook_update_post_local rc: $rc\n"; } update_runtime_data($c, $peer, 1); - return($job); + printf("*** updating %s on %s to omd %s finished\n", $facts->{'omd_site'}, $peer->{'name'}, $version); + + return(1); } ########################################################## @@ -576,8 +626,8 @@ sub omd_install_update_cleanup { # continue in background job my $job = Thruk::Utils::External::perl($c, { - expr => 'Thruk::NodeControl::Utils::_omd_install_update_cleanup_step2($c, "'.$peer->{'key'}.'", "'.$version.'")', - background => 1, + expr => 'Thruk::NodeControl::Utils::_omd_install_update_cleanup_step2($c, "'.$peer->{'key'}.'", "'.$version.'")', + background => 1, }); Thruk::Utils::IO::json_lock_patch($file, { 'run_all' => $job, 'last_job' => $job }, { pretty => 1, allow_empty => 1 }); return($job); @@ -597,10 +647,9 @@ sub _omd_install_update_cleanup_step2 { if($config->{'pkg_install'} && !grep(/$version/mx, @{$facts->{'omd_versions'} // []})) { $job = omd_install($c, $peer, $version, 1); die("failed to start install") unless $job; - $jobdata = _wait_for_job($c, $peer, $job, 3, 1800); + $jobdata = _wait_for_job($c, $peer, $job, 3, 1800, 1); return unless $jobdata; - print $jobdata->{'stdout'},"\n"; - print $jobdata->{'stderr'},"\n"; + return unless $jobdata->{'rc'} eq '0'; } else { print "*** not required, already installed\n"; } @@ -616,10 +665,8 @@ sub _omd_install_update_cleanup_step2 { return; } die("failed to start update") unless $job; - $jobdata = _wait_for_job($c, $peer, $job, 3, 180); + $jobdata = _wait_for_job($c, $peer, $job, 1, 180, 1); return unless $jobdata; - print $jobdata->{'stdout'},"\n"; - print $jobdata->{'stderr'},"\n"; } else { print "*** not required, already current version\n"; } @@ -629,9 +676,7 @@ sub _omd_install_update_cleanup_step2 { print "*** running cleanup\n"; $job = omd_cleanup($c, $peer, 1); die("failed to start cleanup") unless $job; - $jobdata = _wait_for_job($c, $peer, $job, 3, 1800); - print $jobdata->{'stdout'},"\n"; - print $jobdata->{'stderr'},"\n"; + $jobdata = _wait_for_job($c, $peer, $job, 3, 1800, 1); } Thruk::Utils::IO::json_lock_patch($file, { 'run_all' => 0, 'last_error' => '' }, { pretty => 1, allow_empty => 1 }); @@ -975,6 +1020,23 @@ sub _wait_for_job { $poll_interval = 3 unless $poll_interval; my $end = time() + $max_wait; my $jobdata; + + my($already_out, $already_err) = (0, 0); + my $print_remaining = sub { + return unless $jobdata; + return unless $print; + if($jobdata->{'stdout'}) { + my $out = substr($jobdata->{'stdout'}, $already_out); + print $out; + $already_out += length($out); + } + if($jobdata->{'stderr'}) { + my $out = substr($jobdata->{'stderr'}, $already_err); + print $out; + $already_err += length($out); + } + }; + while(time() < $end) { eval { $jobdata = $peer->job_data($c, $job); @@ -982,27 +1044,24 @@ sub _wait_for_job { if($jobdata && !$jobdata->{'is_running'}) { last; } + &{$print_remaining}(); sleep($poll_interval); } - if($jobdata && $print) { - print $jobdata->{'stdout'},"\n" if $jobdata->{'stdout'}; - print $jobdata->{'stderr'},"\n" if $jobdata->{'stderr'}; - } + &{$print_remaining}(); return($jobdata); } ########################################################## sub _get_hook_env { my($c, $peer, $version) = @_; - my $config = config($c); - my $server = get_server($c, $peer, $config); + my $server = get_server($c, $peer); my $env = { - 'PEER_NAME' => $peer->{'name'} // '', - 'PEER_KEY' => $peer->{'key'} // '', - 'HOST_NAME' => $server->{'host_name'} // '', - 'SITE_NAME' => $server->{'omd_site'} // '', - 'OMD_VERSION' => $server->{'omd_version'} // '', - 'OMD_UPDATE' => $version // '', + 'PEER_NAME' => $peer->{'name'} // '', + 'PEER_KEY' => $peer->{'key'} // '', + 'OMD_HOST_NAME' => $server->{'host_name'} // '', + 'SITE_NAME' => $server->{'omd_site'} // '', + 'FROM_OMD_VERSION' => $server->{'omd_version'} // '', + 'OMD_UPDATE' => $version // '', }; return($env); } diff --git a/plugins/plugins-available/node-control/scripts/omd_update.sh b/plugins/plugins-available/node-control/scripts/omd_update.sh index 434d060ba..38fda6b2b 100755 --- a/plugins/plugins-available/node-control/scripts/omd_update.sh +++ b/plugins/plugins-available/node-control/scripts/omd_update.sh @@ -12,7 +12,7 @@ if [ -n "$DRYRUN" -a "$DRYRUN" != "0" ]; then exit 1 fi -echo "[$(date)] updating site $(id -un) from $(omd version -b) to version $OMD_UPDATE..." +echo "*** updating site $(id -un) from $(omd version -b) to version $OMD_UPDATE..." omd stop # make sure it is stopped @@ -59,17 +59,7 @@ fi if [ "$(omd version -b)" = "$OMD_UPDATE" ]; then omd start - echo "[$(date)] update finished: $(omd version -b)" - - # run post hook if available - RC=0 - if [ -e "${OMD_ROOT}/var/tmp/omd_update_post.sh" ]; then - echo "[$(date)] starting post update hook" - bash -x ${OMD_ROOT}/var/tmp/omd_update_post.sh - RC=$? - rm -f ${OMD_ROOT}/var/tmp/omd_update_post.sh - echo "[$(date)] post update hook exited: $RC" - fi + echo "*** update finished: $(omd version -b)" # exit tmux again if command -v tmux >/dev/null 2>&1; then diff --git a/root/thruk/javascript/thruk-3.18.js b/root/thruk/javascript/thruk-3.18.js index 8b79e4aee..3a0592213 100644 --- a/root/thruk/javascript/thruk-3.18.js +++ b/root/thruk/javascript/thruk-3.18.js @@ -3929,7 +3929,27 @@ function showJobOutputPopupUpdate(jobid, peerid, divid, data) { head.find("I.fa-check").remove(); head.find("I.fa-exclamation").remove(); jQuery('#'+divid).text(data.stdout+data.stderr); - jQuery("#"+divid).scrollTop(jQuery("#"+divid).prop("scrollHeight")); + + // check if text area should scroll + var scroll = jQuery("#"+divid).data("scroll"); + if(scroll === "0") {} + else if(scroll === "1") { + jQuery("#"+divid).scrollTop(jQuery("#"+divid).prop("scrollHeight")); + } else { + scroll = jQuery("#"+divid).data("scroll", "1"); + jQuery("#"+divid).on("mousewheel DOMMouseScroll", function() { + // disable auto scrolling unless scrolled all to the bottom + var scrollHeight = jQuery("#"+divid).scrollTop()+jQuery("#"+divid).height() + 20; // maybe due to border or scrollbar + var scrollPosition = jQuery("#"+divid).prop("scrollHeight"); + if(scrollHeight >= scrollPosition) { + // scrolled to bottom, enable again + jQuery("#"+divid).data("scroll", "1"); + } else { + // disabled auto scroll + jQuery("#"+divid).data("scroll", "0"); + } + }) + } if(data['is_running']) { head.prepend('
<\/div>'); diff --git a/t/600-scenarios.t b/t/600-scenarios.t index 9cc3c6569..4d60cd9ed 100644 --- a/t/600-scenarios.t +++ b/t/600-scenarios.t @@ -95,7 +95,7 @@ sub _run { ok(1, "$dir: running make $step"); my($rc, $out) = Thruk::Utils::IO::cmd([$make, $step], { print_prefix => ($verbose ? '## ' : undef), - output_prefix => Thruk::Utils::Log::time_prefix(), + output_prefix => \&Thruk::Utils::Log::time_prefix, }); is($rc, 0, sprintf("step %s complete, rc=%d duration=%.1fsec", $step, $rc, tv_interval ($t0))); if($out =~ m/^\[.*?\](FROM.*version:.*)$/mx) { diff --git a/t/scenarios/lmd_federation_multitier_e2e/tier1a/thruk_local.conf b/t/scenarios/lmd_federation_multitier_e2e/tier1a/thruk_local.conf index b2fc9ffc2..d508f9534 100644 --- a/t/scenarios/lmd_federation_multitier_e2e/tier1a/thruk_local.conf +++ b/t/scenarios/lmd_federation_multitier_e2e/tier1a/thruk_local.conf @@ -9,10 +9,10 @@ ssl_verify_hostnames=0 # - hook_update_pre_local = printf "%s" "$(date): $(hostname)\n$(env)" >> /tmp/pre-local.log - hook_update_pre = printf "%s" "$(date): $(hostname)\n$(env)" >> /tmp/pre-remote.log - hook_update_post = printf "%s" "$(date): $(hostname)\n$(env)" >> /tmp/post-remote.log - hook_update_post_local = printf "%s" "$(date): $(hostname)\n$(env)" >> /tmp/post-local.log + hook_update_pre_local = printf "pre local %s: %s\n%s" "$(date): $(hostname)" "$(env | sort | grep -v ^CONFIG_)" + hook_update_pre = printf "pre remote %s: %s\n%s" "$(date): $(hostname)" "$(env | sort | grep -v ^CONFIG_)" + hook_update_post = printf "post remote %s: %s\n%s" "$(date): $(hostname)" "$(env | sort | grep -v ^CONFIG_)" + hook_update_post_local = printf "post local %s: %s\n%s" "$(date): $(hostname)" "$(env | sort | grep -v ^CONFIG_)" ssh_fallback = 0 diff --git a/t/scenarios/lmd_federation_multitier_e2e/tier2b/playbook.yml b/t/scenarios/lmd_federation_multitier_e2e/tier2b/playbook.yml index dd562e9f5..221769270 100644 --- a/t/scenarios/lmd_federation_multitier_e2e/tier2b/playbook.yml +++ b/t/scenarios/lmd_federation_multitier_e2e/tier2b/playbook.yml @@ -2,6 +2,7 @@ - hosts: all roles: - role: common + - role: node_control_client tasks: - copy: src: "/root/thruk_local.conf" diff --git a/t/scenarios/lmd_federation_multitier_e2e/tier3b/playbook.yml b/t/scenarios/lmd_federation_multitier_e2e/tier3b/playbook.yml index da074c175..86bb8ed87 100644 --- a/t/scenarios/lmd_federation_multitier_e2e/tier3b/playbook.yml +++ b/t/scenarios/lmd_federation_multitier_e2e/tier3b/playbook.yml @@ -2,6 +2,7 @@ - hosts: all roles: - role: common + - role: node_control_client tasks: - name: "omd config change" shell: "omd config demo change"