From 08c5831aadde67b372373bd785186c16a691c071 Mon Sep 17 00:00:00 2001 From: Andrii Nikitin Date: Tue, 14 Oct 2025 19:15:57 +0200 Subject: [PATCH 1/2] Add Exec service to schedule and execute bash cmds --- .../mirrorcache-backstage-exec.service | 19 +++ lib/MirrorCache/Task/Exec.pm | 141 ++++++++++++++++++ lib/MirrorCache/WebAPI.pm | 39 ++--- lib/MirrorCache/WebAPI/Plugin/Backstage.pm | 7 +- script/mirrorcache-backstage-exec | 2 + script/mirrorcache-daemon | 2 +- script/mirrorcache-hypnotoad | 2 +- t/environ/02-exec.sh | 25 ++++ t/lib/Dockerfile.environ.mariadb | 2 +- t/lib/Dockerfile.environ.mariadb.experimental | 2 +- t/lib/Dockerfile.environ.postgresql | 2 +- t/lib/environ/mc/source/_exec.m4 | 2 +- .../mc/source/backstage-exec/shoot.sh.m4 | 12 ++ .../mc/source/backstage-exec/start.sh.m4 | 17 +++ .../mc/source/backstage-exec/status.sh.m4 | 2 + .../mc/source/backstage-exec/stop.sh.m4 | 14 ++ t/lib/environ/mc/source/sub/start.sh.m4 | 2 +- 17 files changed, 259 insertions(+), 33 deletions(-) create mode 100644 dist/systemd/mirrorcache-backstage-exec.service create mode 100644 lib/MirrorCache/Task/Exec.pm create mode 100644 script/mirrorcache-backstage-exec create mode 100755 t/environ/02-exec.sh create mode 100644 t/lib/environ/mc/source/backstage-exec/shoot.sh.m4 create mode 100644 t/lib/environ/mc/source/backstage-exec/start.sh.m4 create mode 100644 t/lib/environ/mc/source/backstage-exec/status.sh.m4 create mode 100644 t/lib/environ/mc/source/backstage-exec/stop.sh.m4 diff --git a/dist/systemd/mirrorcache-backstage-exec.service b/dist/systemd/mirrorcache-backstage-exec.service new file mode 100644 index 00000000..b54a6efd --- /dev/null +++ b/dist/systemd/mirrorcache-backstage-exec.service @@ -0,0 +1,19 @@ +[Unit] +Description=MirrorCache daemon for executing scheduled tasks + +[Service] +User=mirrorcache-exec +Group=mirrorcache-exec +ExecStart=/usr/share/mirrorcache/script/mirrorcache-backstage-exec +Nice=19 +Restart=on-failure +RestartSec=10 +EnvironmentFile=/etc/mirrorcache/conf.env +WorkingDirectory=/var/lib/mirrorcache +Environment="MOJO_TMPDIR=/var/lib/mirrorcache/tmp" +Environment="MOJO_LOG_LEVEL=error" +MemoryHigh=2G +MemoryMax=3G + +[Install] +WantedBy=multi-user.target diff --git a/lib/MirrorCache/Task/Exec.pm b/lib/MirrorCache/Task/Exec.pm new file mode 100644 index 00000000..7badf578 --- /dev/null +++ b/lib/MirrorCache/Task/Exec.pm @@ -0,0 +1,141 @@ +# Copyright (C) 2025 SUSE LLC +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see . + +package MirrorCache::Task::Exec; +use diagnostics; +use IPC::Open3; +use IO::Select; +use Symbol 'gensym'; +use POSIX ":sys_wait_h"; + +use Mojo::Base 'Mojolicious::Plugin'; +use MirrorCache::Utils 'datetime_now'; + +# Exec command will execute bash commands provided by argv +# +# Examples to print string "1 2" +# perl: +# my $res = $minion->enqueue(exec => ("echo 1 2")); +# my $res = $minion->enqueue(exec => ("echo", 1, 2)); +# my %args = (CMD => 'echo 1', DESC => 'Command that prints "1 2"', TIMEOUT => 1200, LOCK => 'mylock', LOCK_TIMEOUT => 60); +# my $res = $minion->enqueue(exec => (\%args, 1, 2)); +# +# shell: +# /usr/share/mirrorcache/script/mirrorcache minion job -e exec -q myqueue -a '["echo 1 2"]' +# /usr/share/mirrorcache/script/mirrorcache minion job -e exec -q myqueue -a '["echo", 1, 2]' +# /usr/share/mirrorcache/script/mirrorcache minion job -e exec -q myqueue -a '[{"CMD":"echo","DESC":"Command that prints","LOCK":"mylock"}, 1, 2]' + +sub register { + my ($self, $app) = @_; + $app->minion->add_task(exec => sub { _run($app, @_) }); +} + +sub _run { + my ($app, $job, $arg0, @argv) = @_; + my $minion = $app->minion; + + return $job->finish('No command provided') unless $arg0; + + my ($cmd, $cmdline, $desc, $timeout, $lockname, $locktimeout, @args); + + if (ref $arg0 eq "HASH") { + $cmdline = $arg0->{CMD}; + $desc = $arg0->{DESC}; + $timeout = $arg0->{TIMEOUT}; + $lockname = $arg0->{LOCK}; + $locktimeout = $arg0->{LOCK_TIMEOUT}; + } else { + $cmdline = $arg0; + } + + my @cmdline = split(/\s/, $cmdline, 2); + if (scalar(@cmdline) > 1) { + $cmd = $cmdline[0]; + } else { + $cmd = $cmdline; + } + $desc = $desc // "Command $cmd"; + $timeout = $timeout // 1200; + $lockname = $lockname // "EXEC_LOCK_$cmd"; + $locktimeout = $locktimeout // $timeout; + + return $job->finish("Cannot lock $lockname") + unless my $guard = $minion->guard($lockname, $locktimeout); + + my $pid; + my ($infh,$outfh,$errfh); + $errfh = gensym(); + + my $success = 0; + my $error; + eval { + $pid = open3($infh, $outfh, $errfh, $cmdline, @argv); + $success = 1; + }; + return $job->fail("open3: $@") unless $success; + close($infh); + + my $sel = new IO::Select; + $sel->add($outfh, $errfh); + + my $start_time = time; + $job->note(pid => $pid, start_time => $start_time, cmdline => $cmdline); + + while(1) { + $! = 0; + my @ready = $sel->can_read(5); + my $last = 0; + if ($!) { # error + $job->note(error_code => $!); + print STDERR "ERRR: $!\n"; + waitpid(-1, WNOHANG); + $last = 1; + } + my $curr_time = time; + my (@lines, @elines); + foreach my $fh (@ready) { + my $line = <$fh>; + if(not defined $line){ + $sel->remove($fh); + next; + } + chomp($line); + if($fh == $outfh) { + push @lines, $line; + } elsif($fh == $errfh) {# do the same for errfh + push @elines, $line; + } + } + $job->note("$curr_time O" => @lines) if @lines; + $job->note("$curr_time E" => @elines) if @elines; + + my $x = waitpid($pid, WNOHANG); + if ($x < 0) { + $job->note(finished => $pid); + $last = 1; + } + + last if $last; + if (($curr_time - $start_time) >= $timeout) { + waitpid(-1, WNOHANG); + return $job->fail("timeout expired!"); + } + } + + waitpid(-1, WNOHANG); + return $job->finish('finish'); +} + +1; diff --git a/lib/MirrorCache/WebAPI.pm b/lib/MirrorCache/WebAPI.pm index 801396c8..ae0ace30 100644 --- a/lib/MirrorCache/WebAPI.pm +++ b/lib/MirrorCache/WebAPI.pm @@ -31,23 +31,6 @@ sub new { # setting pid_file in startup will not help, need to set it earlier $self->config->{hypnotoad}{pid_file} = $ENV{MIRRORCACHE_HYPNOTOAD_PID} // '/run/mirrorcache/hypnotoad.pid'; - # I wasn't able to find reliable way in Mojolicious to detect when WebUI is started - # (e.g. in daemon or hypnotoad in contrast to other commands like backend start / shoot) - # so the code below tries to detect if _setup_ui is needed to be called - - my $started = 0; - for (my $i = 0; my @r = caller($i); $i++) { - next unless $r[3] =~ m/Hypnotoad/; - $self->_setup_webui; - $started = 1; - last; - } - - $self->hook(before_command => sub { - my ($command, $arg) = @_; - $self->_setup_webui if ref($command) =~ m/daemon|prefork/; - }) unless $started; - $self; } @@ -104,15 +87,8 @@ sub startup { $self->defaults(branding => $ENV{MIRRORCACHE_BRANDING}); $self->defaults(custom_footer_message => $ENV{MIRRORCACHE_CUSTOM_FOOTER_MESSAGE}); - $self->plugin('RenderFile'); - push @{$self->plugins->namespaces}, 'MirrorCache::WebAPI::Plugin'; - $self->plugin('Backstage'); - $self->plugin('AuditLog'); - $self->plugin('RenderFileFromMirror'); - $self->plugin('ReportMirror'); - $self->plugin('HashedParams'); if ($geodb_file && $geodb_file =~ /\.mmdb$/i) { require MaxMind::DB::Reader; @@ -153,6 +129,21 @@ sub startup { warn("Could not load plugin from {$plug}: $@\n") } } + + $self->_setup_webui_plugins if ($ENV{MIRRORCACHE_INTERNAL_SETUP_WEBAPI}); +} + +sub _setup_webui_plugins { + my ($self) = shift; + my $root = $self->mcconfig->root; + $self->log->info("initializing WebUI"); + $self->plugin('RenderFile'); + $self->plugin('AuditLog'); + $self->plugin('RenderFileFromMirror'); + $self->plugin('ReportMirror'); + $self->plugin('HashedParams'); + + $self->_setup_webui; } sub _setup_webui { diff --git a/lib/MirrorCache/WebAPI/Plugin/Backstage.pm b/lib/MirrorCache/WebAPI/Plugin/Backstage.pm index f49bcca2..019ebfc8 100644 --- a/lib/MirrorCache/WebAPI/Plugin/Backstage.pm +++ b/lib/MirrorCache/WebAPI/Plugin/Backstage.pm @@ -47,8 +47,8 @@ sub register_tasks { push @permanent_jobs, 'mirror_provider_sync'; } - $app->plugin($_) - for ( + unless ($ENV{MIRRORCACHE_INTERNAL_BACKSTAGE_EXEC}) { + $app->plugin($_) for ( qw(MirrorCache::Task::MirrorCheckFromStat), qw(MirrorCache::Task::MirrorFileCheck), qw(MirrorCache::Task::MirrorScanScheduleFromMisses), @@ -73,6 +73,9 @@ sub register_tasks { qw(MirrorCache::Task::StatAggSchedule), qw(MirrorCache::Task::StatAggPkg), ); + } else { + $app->plugin("MirrorCache::Task::Exec"); + } } sub register { diff --git a/script/mirrorcache-backstage-exec b/script/mirrorcache-backstage-exec new file mode 100644 index 00000000..05d16d39 --- /dev/null +++ b/script/mirrorcache-backstage-exec @@ -0,0 +1,2 @@ +#!/bin/sh -e +MIRRORCACHE_INTERNAL_BACKSTAGE_EXEC=1 exec "$(dirname "$0")"/mirrorcache backstage run -j ${MIRRORCACHE_BACKSTAGE_WORKERS:-2} -q ${MIRRORCACHE_BACKSTAGE_EXEC_QUEUE:-exec} diff --git a/script/mirrorcache-daemon b/script/mirrorcache-daemon index c722148e..550c66e0 100644 --- a/script/mirrorcache-daemon +++ b/script/mirrorcache-daemon @@ -1,3 +1,3 @@ #!/bin/sh -e echo $MOJO_LISTEN -exec "$(dirname "$0")"/mirrorcache prefork -m production --proxy -w ${MIRRORCACHE_WORKERS:-8} "$@" +MIRRORCACHE_INTERNAL_SETUP_WEBAPI=1 exec "$(dirname "$0")"/mirrorcache prefork -m production --proxy -w ${MIRRORCACHE_WORKERS:-8} "$@" diff --git a/script/mirrorcache-hypnotoad b/script/mirrorcache-hypnotoad index 355de0fc..22e78298 100644 --- a/script/mirrorcache-hypnotoad +++ b/script/mirrorcache-hypnotoad @@ -1,6 +1,6 @@ #!/bin/sh -e echo $MOJO_LISTEN -hypnotoad "$(dirname "$0")"/mirrorcache +MIRRORCACHE_INTERNAL_SETUP_WEBAPI=1 hypnotoad "$(dirname "$0")"/mirrorcache [ -f ${MIRRORCACHE_HYPNOTOAD_PID:-/run/mirrorcache/hypnotoad.pid} ] || sleep 0.5 [ -f ${MIRRORCACHE_HYPNOTOAD_PID:-/run/mirrorcache/hypnotoad.pid} ] || sleep 0.5 [ -f ${MIRRORCACHE_HYPNOTOAD_PID:-/run/mirrorcache/hypnotoad.pid} ] || sleep 0.5 diff --git a/t/environ/02-exec.sh b/t/environ/02-exec.sh new file mode 100755 index 00000000..768eede3 --- /dev/null +++ b/t/environ/02-exec.sh @@ -0,0 +1,25 @@ +#!lib/test-in-container-environ.sh +set -exo pipefail + +mc=$(environ mc $(pwd)) + +# pass too big value for prev_stat_id and make sure it is automatically adjusted +$mc/backstage/job -e exec -a '["ping google.com -c 3 & (sleep 1; pwd; errreerr; pwd)"]' +$mc/backstage/job -e exec -a '["mkdir tttttt"]' +$mc/backstage/job -e exec -a '["touch", "aaaaaa"]' +$mc/backstage-exec/shoot + +$mc/backstage/job -e exec -a '["(sleep 1; pwd; errreerr; pwd) & ping -c 20 google.com"]' +$mc/backstage/job -e exec -a '[{"CMD": "(sleep 1; pwd; errreerr; pwd) & ping -c 20 google.com", "TIMEOUT": 6}]' +$mc/backstage-exec/shoot + +# mc1/start +ls -lRa $mc | grep tttttt +ls -lRa $mc | grep aaaaaa + +$mc/sql 'select * from minion_jobs' + +$mc/sql_test 4 == "select count(*) from minion_jobs where state = 'finished'" +$mc/sql_test 1 == "select count(*) from minion_jobs where state = 'failed'" + +echo success diff --git a/t/lib/Dockerfile.environ.mariadb b/t/lib/Dockerfile.environ.mariadb index edbf4bef..74ad5b62 100644 --- a/t/lib/Dockerfile.environ.mariadb +++ b/t/lib/Dockerfile.environ.mariadb @@ -14,7 +14,7 @@ RUN zypper -vvv -n install MirrorCache perl-MaxMind-DB-Reader perl-Mojolicious-P perl-Config-IniFiles environ eatmydata # optional dependencies used in testing -RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync perl-DateTime-Format-MySQL libxml2-tools +RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync perl-DateTime-Format-MySQL libxml2-tools iputils # this hack is needed because old nginx versions cannot run as non-root RUN bbe -e 's,/var/log/nginx/error.log,/tmp/log_nginx_error.log,' /usr/sbin/nginx > /usr/sbin/nginx.hacked diff --git a/t/lib/Dockerfile.environ.mariadb.experimental b/t/lib/Dockerfile.environ.mariadb.experimental index 81df100f..1dcf46c6 100644 --- a/t/lib/Dockerfile.environ.mariadb.experimental +++ b/t/lib/Dockerfile.environ.mariadb.experimental @@ -16,7 +16,7 @@ RUN zypper -vvv -n install MirrorCache perl-MaxMind-DB-Reader perl-Mojolicious-P perl-Config-IniFiles environ eatmydata # optional dependencies used in testing -RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync perl-DateTime-Format-MySQL libxml2-tools +RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync perl-DateTime-Format-MySQL libxml2-tools iputils RUN zypper -vvv -n install MariaDB-server-compat MariaDB-client-compat diff --git a/t/lib/Dockerfile.environ.postgresql b/t/lib/Dockerfile.environ.postgresql index 2e44750f..8ac35528 100644 --- a/t/lib/Dockerfile.environ.postgresql +++ b/t/lib/Dockerfile.environ.postgresql @@ -13,7 +13,7 @@ RUN zypper -vvv -n install MirrorCache perl-MaxMind-DB-Reader perl-Mojolicious-P apache2 perl-Digest-MD4 tidy nginx bbe perl-DateTime-HiRes perl-Config-IniFiles environ # optional dependencies used in testing -RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync libxml2-tools +RUN zypper -vvv -n install perl-Geo-IP2Location perl-Digest-Zsync libxml2-tools iputils # this hack is needed because old nginx versions cannot run as non-root RUN bbe -e 's,/var/log/nginx/error.log,/tmp/log_nginx_error.log,' /usr/sbin/nginx > /usr/sbin/nginx.hacked diff --git a/t/lib/environ/mc/source/_exec.m4 b/t/lib/environ/mc/source/_exec.m4 index dd536098..128aa085 100644 --- a/t/lib/environ/mc/source/_exec.m4 +++ b/t/lib/environ/mc/source/_exec.m4 @@ -18,7 +18,7 @@ elif test "${MIRRORCACHE_HYPNOTOAD:-}" == 1 ; then perl __srcdir/script/mirrorcache-hypnotoad >> __workdir/.cout 2>> __workdir/.cerr & sleep 3 else - __srcdir/script/mirrorcache daemon >> __workdir/.cout 2>> __workdir/.cerr & + MIRRORCACHE_INTERNAL_SETUP_WEBAPI=1 __srcdir/script/mirrorcache daemon >> __workdir/.cout 2>> __workdir/.cerr & pid=$! echo $pid > __workdir/.pid fi diff --git a/t/lib/environ/mc/source/backstage-exec/shoot.sh.m4 b/t/lib/environ/mc/source/backstage-exec/shoot.sh.m4 new file mode 100644 index 00000000..5fbfd059 --- /dev/null +++ b/t/lib/environ/mc/source/backstage-exec/shoot.sh.m4 @@ -0,0 +1,12 @@ +set -e + +__workdir/../gen_env +source __workdir/../conf.env + +__workdir/../db/status >& /dev/null || __workdir/../db/start +[ -e __workdir/../db/sql_mc_test ] || __workdir/../db/create_db mc_test + +( +cd __workdir +MIRRORCACHE_INTERNAL_BACKSTAGE_EXEC=1 __srcdir/script/mirrorcache backstage run --oneshot "$@" +) diff --git a/t/lib/environ/mc/source/backstage-exec/start.sh.m4 b/t/lib/environ/mc/source/backstage-exec/start.sh.m4 new file mode 100644 index 00000000..8d3169b5 --- /dev/null +++ b/t/lib/environ/mc/source/backstage-exec/start.sh.m4 @@ -0,0 +1,17 @@ +set -e + +__workdir/../gen_env +source __workdir/../conf.env + +__workdir/../db/status >& /dev/null || __workdir/../db/start +[ -e __workdir/../db/sql_mc_test ] || __workdir/../db/create_db mc_test + +( +cd __workdir +MIRRORCACHE_INTERNAL_BACKSTAGE_EXEC=1 __srcdir/script/mirrorcache backstage run -C 1 -j ${MIRRORCACHE_BACKSTAGE_WORKERS:-2} >> __workdir/.cout 2>> __workdir/.cerr & + +pid=$! +echo $pid > __workdir/.pid +sleep 0.2 +__workdir/status +) diff --git a/t/lib/environ/mc/source/backstage-exec/status.sh.m4 b/t/lib/environ/mc/source/backstage-exec/status.sh.m4 new file mode 100644 index 00000000..1dc90111 --- /dev/null +++ b/t/lib/environ/mc/source/backstage-exec/status.sh.m4 @@ -0,0 +1,2 @@ +[ -f __workdir/.pid ] || ( echo backstage not started; exit 1 ) +( kill -0 $(cat __workdir/.pid) && ! ps -p "$(cat __workdir/.pid)" | grep -q defunc && echo backstage seems running ) || ( echo backstage seems be down; exit 1 ) diff --git a/t/lib/environ/mc/source/backstage-exec/stop.sh.m4 b/t/lib/environ/mc/source/backstage-exec/stop.sh.m4 new file mode 100644 index 00000000..fd377777 --- /dev/null +++ b/t/lib/environ/mc/source/backstage-exec/stop.sh.m4 @@ -0,0 +1,14 @@ +[ -f __workdir/.pid ] || exit 0 + +kill "$(cat __workdir/.pid)" + +# wait ~5 sec, then kill hard +cnt=50 +while kill -0 "$(cat __workdir/.pid)" 2>/dev/null && ! ps -p "$(cat __workdir/.pid)" | grep -q defunc ; do + sleep 0.1 + if [ $((cnt--)) -le 1 ]; then + kill -9 "$(cat __workdir/.pid)" + sleep 0.1 + break + fi +done diff --git a/t/lib/environ/mc/source/sub/start.sh.m4 b/t/lib/environ/mc/source/sub/start.sh.m4 index d70d372e..1dfaf85d 100644 --- a/t/lib/environ/mc/source/sub/start.sh.m4 +++ b/t/lib/environ/mc/source/sub/start.sh.m4 @@ -5,7 +5,7 @@ source __workdir/conf.env ( cd __workdir -__srcdir/script/mirrorcache daemon run >> __workdir/.cout 2>> __workdir/.cerr & +MIRRORCACHE_INTERNAL_SETUP_WEBAPI=1 __srcdir/script/mirrorcache daemon run >> __workdir/.cout 2>> __workdir/.cerr & pid=$! echo $pid > __workdir/.pid From f2c3ef7f65ddc2ac43ecaed216bd43de6f9a789a Mon Sep 17 00:00:00 2001 From: Andrii Nikitin Date: Wed, 15 Oct 2025 15:23:11 +0200 Subject: [PATCH 2/2] Adjust spec file with MirrorCache-Exec --- dist/rpm/MirrorCache-Exec-tmpfilesd.conf | 3 + dist/rpm/MirrorCache-Exec-user.conf | 3 + dist/rpm/MirrorCache.spec | 81 ++++++++++++++++--- .../mirrorcache-backstage-exec.service | 6 +- 4 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 dist/rpm/MirrorCache-Exec-tmpfilesd.conf create mode 100644 dist/rpm/MirrorCache-Exec-user.conf diff --git a/dist/rpm/MirrorCache-Exec-tmpfilesd.conf b/dist/rpm/MirrorCache-Exec-tmpfilesd.conf new file mode 100644 index 00000000..b0025ddf --- /dev/null +++ b/dist/rpm/MirrorCache-Exec-tmpfilesd.conf @@ -0,0 +1,3 @@ +# Type Path Mode UID GID Age Argument +d /var/lib/mirrorcache-exec 0750 mirrorcache-exec mirrorcache - - +d /run/mirrorcache-exec 0750 mirrorcache-exec mirrorcache - - diff --git a/dist/rpm/MirrorCache-Exec-user.conf b/dist/rpm/MirrorCache-Exec-user.conf new file mode 100644 index 00000000..34e14087 --- /dev/null +++ b/dist/rpm/MirrorCache-Exec-user.conf @@ -0,0 +1,3 @@ +# Type Name ID GECOS [HOME] +u mirrorcache-exec - "MirrorCache" /var/lib/mirrorcache-exec +g mirrorcache diff --git a/dist/rpm/MirrorCache.spec b/dist/rpm/MirrorCache.spec index 064527a8..3c73ec48 100644 --- a/dist/rpm/MirrorCache.spec +++ b/dist/rpm/MirrorCache.spec @@ -1,7 +1,7 @@ # # spec file for package MirrorCache # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2021,2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,10 +19,11 @@ %define mirrorcache_services_restart mirrorcache.service mirrorcache-backstage.service mirrorcache-backstage-hashes.service mirrorcache-subtree.service %define mirrorcache_services %{mirrorcache_services_restart} mirrorcache-hypnotoad.service %define assetpack_requires perl(CSS::Minifier::XS) >= 0.01 perl(JavaScript::Minifier::XS) >= 0.11 perl(Mojolicious::Plugin::AssetPack) >= 1.36 perl(IO::Socket::SSL) -%define main_requires %{assetpack_requires} perl(Carp) perl(DBD::Pg) >= 3.7.4 perl(DBI) >= 1.632 perl(DBIx::Class) >= 0.082801 perl(DBIx::Class::DynamicDefault) perl(DateTime) perl(Encode) perl(Time::Piece) perl(Time::Seconds) perl(Time::ParseDate) perl(DateTime::Format::Pg) perl(Exporter) perl(File::Basename) perl(LWP::UserAgent) perl(Mojo::Base) perl(Mojo::ByteStream) perl(Mojo::IOLoop) perl(Mojo::JSON) perl(Mojo::Pg) perl(Mojo::URL) perl(Mojo::Util) perl(Mojolicious::Commands) perl(Mojolicious::Plugin) perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Static) perl(Net::OpenID::Consumer) perl(POSIX) perl(Sort::Versions) perl(URI::Escape) perl(XML::Writer) perl(base) perl(constant) perl(diagnostics) perl(strict) perl(warnings) shadow rubygem(sass) perl(Net::DNS) perl(LWP::Protocol::https) perl(Digest::SHA) perl(Config::IniFiles) +%define common_requires perl(Carp) perl(DBD::Pg) >= 3.7.4 perl(DBI) >= 1.632 perl(DBIx::Class) >= 0.082801 perl(DBIx::Class::DynamicDefault) perl(DateTime) perl(Encode) perl(Time::Piece) perl(Time::Seconds) perl(Time::ParseDate) perl(DateTime::Format::Pg) perl(Exporter) perl(File::Basename) perl(LWP::UserAgent) perl(Mojo::Base) perl(Mojo::ByteStream) perl(Mojo::IOLoop) perl(Mojo::JSON) perl(Mojo::Pg) perl(Mojo::URL) perl(Mojo::Util) perl(Mojolicious::Commands) perl(Mojolicious::Plugin) perl(POSIX) perl(Sort::Versions) perl(URI::Escape) perl(XML::Writer) perl(base) perl(constant) perl(diagnostics) perl(strict) perl(warnings) shadow perl(Net::DNS) perl(LWP::Protocol::https) perl(Digest::SHA) perl(Config::IniFiles) +%define main_requires %{assetpack_requires} perl(Mojolicious::Plugin::RenderFile) perl(Mojolicious::Static) perl(Net::OpenID::Consumer) rubygem(sass) %define build_requires %{assetpack_requires} rubygem(sass) tidy sysuser-shadow sysuser-tools Name: MirrorCache -Version: 0.1 +Version: 0 Release: 0 Summary: WebApp to redirect and manage mirrors License: GPL-2.0-or-later @@ -32,11 +33,13 @@ Source0: %{name}-%{version}.tar.xz Source1: cache.tar.xz Source2: %{name}-user.conf Source3: %{name}-tmpfilesd.conf +Source4: %{name}-Exec-user.conf +Source5: %{name}-Exec-tmpfilesd.conf # use update-cache (or tools/generate-packed-assets) to generate/update cache.tar.xz Source101: update-cache.sh BuildRequires: %{build_requires} +Requires: MirrorCache-common Requires: %{main_requires} -Requires: perl(Minion) >= 10.0 BuildArch: noarch %sysusers_requires @@ -49,6 +52,7 @@ Mirror redirector web service, which automatically scans the main server and mir %build # make {?_smp_mflags} %sysusers_generate_pre %{SOURCE2} %{name} +%sysusers_generate_pre %{SOURCE4} %{name}-Exec %check @@ -63,6 +67,8 @@ ln -s ../sbin/service %{buildroot}%{_sbindir}/rcmirrorcache-backstage-hashes ln -s ../sbin/service %{buildroot}%{_sbindir}/rcmirrorcache-subtree install -D -m 0644 %{SOURCE2} %{buildroot}%{_sysusersdir}/%{name}.conf install -D -m 0644 %{SOURCE3} %{buildroot}%{_tmpfilesdir}/%{name}.conf +install -D -m 0644 %{SOURCE4} %{buildroot}%{_sysusersdir}/%{name}-Exec.conf +install -D -m 0644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/%{name}-Exec.conf %pre -f %{name}.pre %service_add_pre %{mirrorcache_services} @@ -79,25 +85,74 @@ install -D -m 0644 %{SOURCE3} %{buildroot}%{_tmpfilesdir}/%{name}.conf %service_del_postun_without_restart mirrorcache-hypnotoad.service %files -%doc README.md -%license LICENSE +%{_sysusersdir}/%{name}.conf +%{_tmpfilesdir}/%{name}.conf +%config(noreplace) %attr(-,root,mirrorcache) %{_sysconfdir}/mirrorcache/ +%ghost %dir %attr(0750,mirrorcache,-) %{_localstatedir}/lib/mirrorcache/ %{_sbindir}/rcmirrorcache %{_sbindir}/rcmirrorcache-hypnotoad %{_sbindir}/rcmirrorcache-backstage %{_sbindir}/rcmirrorcache-backstage-hashes %{_sbindir}/rcmirrorcache-subtree -%{_sysusersdir}/%{name}.conf -%{_tmpfilesdir}/%{name}.conf -%config(noreplace) %attr(-,root,mirrorcache) %{_sysconfdir}/mirrorcache/ -%ghost %dir %attr(0750,mirrorcache,-) %{_localstatedir}/lib/mirrorcache/ -# init -%dir %{_unitdir} %{_unitdir}/mirrorcache.service %{_unitdir}/mirrorcache-hypnotoad.service %{_unitdir}/mirrorcache-backstage.service %{_unitdir}/mirrorcache-backstage-hashes.service %{_unitdir}/mirrorcache-subtree.service + +%changelog + +%package common + +Summary: MirrorCache shared files +License: GPL-2.0-or-later +Group: Productivity/Networking/Web/Servers +URL: https://github.com/openSUSE/MirrorCache +Requires: %{common_requires} +Requires: perl(Minion) >= 10.0 +BuildArch: noarch +%sysusers_requires + +%description common +Shared files for MirrorCache packages + +%files common +%doc README.md +%license LICENSE +%{_sbindir}/rcmirrorcache +%dir %{_unitdir} # web libs %{_datadir}/mirrorcache -%changelog +%package Exec + +Summary: MirrorCache worker to execute scheduled tasks +License: GPL-2.0-or-later +Group: Productivity/Networking/Web/Servers +URL: https://github.com/openSUSE/MirrorCache +Requires: MirrorCache-common +BuildArch: noarch +%sysusers_requires + +%description Exec +MirrorCache worker to execute scheduled shell scripts + +%files Exec +%{_sysusersdir}/%{name}-Exec.conf +%{_tmpfilesdir}/%{name}-Exec.conf +%ghost %dir %attr(0750,mirrorcache,-) %{_localstatedir}/lib/mirrorcache-exec/ +%{_unitdir}/mirrorcache-backstage-exec.service + +%pre -f %{name}-Exec.pre Exec +%service_add_pre mirrorcache-backstage-exec.service + +%post Exec +%tmpfiles_create %{_tmpfilesdir}/%{name}-Exec.conf +%service_add_post mirrorcache-backstage-exec.service + +%preun Exec +%service_del_preun mirrorcache-backstage-exec.service + +%postun Exec +%service_del_postun mirrorcache-backstage-exec.service + diff --git a/dist/systemd/mirrorcache-backstage-exec.service b/dist/systemd/mirrorcache-backstage-exec.service index b54a6efd..3f3e4b81 100644 --- a/dist/systemd/mirrorcache-backstage-exec.service +++ b/dist/systemd/mirrorcache-backstage-exec.service @@ -3,14 +3,14 @@ Description=MirrorCache daemon for executing scheduled tasks [Service] User=mirrorcache-exec -Group=mirrorcache-exec +Group=mirrorcache ExecStart=/usr/share/mirrorcache/script/mirrorcache-backstage-exec Nice=19 Restart=on-failure RestartSec=10 EnvironmentFile=/etc/mirrorcache/conf.env -WorkingDirectory=/var/lib/mirrorcache -Environment="MOJO_TMPDIR=/var/lib/mirrorcache/tmp" +WorkingDirectory=/var/lib/mirrorcache-exec +Environment="MOJO_TMPDIR=/var/lib/mirrorcache-exec" Environment="MOJO_LOG_LEVEL=error" MemoryHigh=2G MemoryMax=3G