From 0d57d970c19517b0fa783378cedfcf86dbcaee79 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 26 Jan 2018 16:56:22 +0100 Subject: [PATCH] Add pkgadmin Our first approach to distribute the packages we want local from the distmaster into /usr/local/pkg gets to its limits, when we update packages and want to remove old versions. We can't just let pdist delete the packages in /usr/local/ because they may be in use and mounted. So we have to make a step towards the original idea, where every system maintains its own set of local packages based on the policy defined in mxpkg (the LOCAL flagxs). Change the directory for local packages from /usr/local/pkg to /var/pkg/. Provide a new tool pkgadmin. When called as `pkgadmin update` this tool removes packages we no longer want to be local and installs new packages which we want local. 'pkgadmin update' is supposed to run automatically from time to time (e.g. cron). To avoid overloading the server of /package/pkg it would be preferable if not all clients run it at the same time. For now, we only run it manually. Because of that we don't need locking yet. --- install.sh | 1 + make-automaps/make-automaps | 2 +- pkgadmin/pkgadmin | 124 ++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100755 pkgadmin/pkgadmin diff --git a/install.sh b/install.sh index 980bae8..0a72f40 100755 --- a/install.sh +++ b/install.sh @@ -90,5 +90,6 @@ install_exec prun/prun "$DESTDIR$usr_bindir/prun" install_exec put_websafe/put_websafe "$DESTDIR$usrlocal_bindir/put_websafe" install_exec switch-passwd/switch-passwd "$DESTDIR$root_sbindir/switch-passwd" install_data switch-passwd/switch-passwd.service "$DESTDIR$systemdunitdir/switch-passwd.service" +install_exec pkgadmin/pkgadmin "$DESTDIR$usr_sbindir/pkgadmin" exit diff --git a/make-automaps/make-automaps b/make-automaps/make-automaps index ac88524..e13b778 100755 --- a/make-automaps/make-automaps +++ b/make-automaps/make-automaps @@ -79,7 +79,7 @@ sub create_pkg_map { s/#.*//; /\S/ or next; my ($pkg,$flags)=split ' '; - my $local="/usr/local/pkg/$pkg"; + my $local="/var/pkg/$pkg"; my $rw = $flags eq 'BUILD' ? ' -rw' : ''; if (-d $local) { print $out "$pkg$rw :$local\n"; diff --git a/pkgadmin/pkgadmin b/pkgadmin/pkgadmin new file mode 100755 index 0000000..825075a --- /dev/null +++ b/pkgadmin/pkgadmin @@ -0,0 +1,124 @@ +#! /usr/bin/perl +use strict; +use warnings; + +our $USAGE=<<"EOF"; +usage: + $0 list # show packag status + $0 update # update /var/pkg according to policy and usage +EOF + +our $PKGDIR='/var/pkg'; + +sub sys { + my @cmd=@_; + print join(' ',@cmd),"\n"; + system @cmd; + $? and exit 1; +} + +sub scandir { + my ($dirname)=@_; + opendir my $dir,$dirname or die "$dirname: $!\n"; + return sort grep !/^\./,readdir $dir; +} + +our %WANT_LOCAL; +our %IS_MOUNTED; + +sub get_mounts { + open my $in,'<','/proc/self/mountinfo' or die "/proc/self/mountinfo $!\n"; + while (<$in>) { + my @f=split; + my $root_within_fs=$f[3]; + if ($root_within_fs=~m"^$PKGDIR/(.+)$") { + my ($pkg)=$1; + $IS_MOUNTED{$pkg}=1; + }; + } +} + +sub read_mxpkg { + open my $in,'<','/etc/mxpkg' or die "/etc/mxpkg: $!\n"; + while (<$in>) { + s/#.*//; + /\S/ or next; + my ($pkg,$flags)=split ' '; + $flags eq 'LOCAL' and $WANT_LOCAL{$pkg}=1; + } +} + +sub list { + my %is_local=map {$_=>1} scandir($PKGDIR); + read_mxpkg(); + get_mounts(); + my %pkg=map {$_=>1} (keys %is_local,keys %WANT_LOCAL); + for my $pkg (sort keys %pkg) { + my $want_local=$WANT_LOCAL{$pkg}; + my $is_local =$is_local{$pkg}; + my $is_mounted=$IS_MOUNTED{$pkg}; + printf "%s %s %s %s\n", + ($want_local?'WANT':' '), + ($is_local ?'HAVE':' '), + ($is_mounted?'MNT':' '), + $pkg; + } +} + +sub update { + read_mxpkg(); + for my $dir (scandir $PKGDIR) { + $dir=~/\.TRASH$/ and next; + $WANT_LOCAL{$dir} and next; + -e "$PKGDIR/$dir.TRASH" and next; + sys('mv',"$PKGDIR/$dir","$PKGDIR/$dir.TRASH"); + sys("/usr/sbin/make-automaps"); + } + get_mounts(); + for my $pkg (scandir $PKGDIR) { + $pkg=~/\.TRASH$/ or next; + if ($IS_MOUNTED{$pkg}) { + print "$pkg: still mounted\n"; + } else { + $pkg or die; + sys('rm','-rf',"$PKGDIR/$pkg"); + } + } + for my $pkg (sort keys %WANT_LOCAL) { + -d "$PKGDIR/$pkg" and next; + -d "/package/pkg/$pkg" or next; + sys( + 'pmirror', + '--allowremotefs', + '--delete', + '--mkdir', + '--exclude','./build', + '--nice', + "/package/pkg/$pkg","$PKGDIR/$pkg.INCOMING" + ); + sys('mv',"$PKGDIR/$pkg.INCOMING","$PKGDIR/$pkg"); + sys("/usr/sbin/make-automaps"); + } +} + +umask 022; +-d $PKGDIR or sys('mkdir','-p',$PKGDIR); + +@ARGV or die $USAGE; +my ($cmd,@args)=@ARGV; +if ($cmd eq 'list') { + @args==0 or die $USAGE; + list(); +} elsif ($cmd eq 'update') { + @args==0 or die $USAGE; + update(); +} else { + die $USAGE; +} + + + + + + +