Subject: Re: How to quarterly releases?
To: Ryan Cresawn <cresawn@chass.utoronto.ca>
From: D'Arcy J.M. Cain <darcy@NetBSD.org>
List: tech-pkg
Date: 11/08/2005 07:19:27
On Mon, 7 Nov 2005 23:17:10 -0500
Ryan Cresawn <cresawn@chass.utoronto.ca> wrote:
> I've been struggling with this problem for a while and I decided that
> I should ask the list because someone here has surely solved this
> before.  The trouble is that I haven't found an intelligent way to
> update from one quarterly release to the next on a production server.
> A mail delivery host that I administer is running Solaris 8 with
> pkgsrc-2005Q1.  Obviously, I would like to update this to the latest
> release.  What is a good way to do this with minimal downtime?

I recently changed the way I do package builds to reduce downtime and
it seems to be working for me so let me take this opportunity to
describe my arrangement for others' information as well as input to
improve it.

First of all, you should look at the pkgtools/pkg_comp package for
automating the build of binary packages in a chroot environment.  I
wound up not using this but it may very well be what you are looking
for.  It looks like a good package but it seemed a mite complicated for
what I wanted to do.  If it makes sense for you then ignore my solution
below.

Having decided that I needed a different solution I set up a new chroot
environment to build packages using a few simple scripts.  First I
created a jail directory.  You could put it anywhere.  I
created /usr/pkg_jail for my systems.  In this directory I installed a
few data files and scripts.  Note that the names are suggestions only.
Feel free to use your own naming scheme if it makes it easier to
remember.

First, create a file called .jail and put a line of text to identify
what kind of jail this is.  I use "PKG-JAIL" in mine.  You can then add
the following lines to your startup script:

if [ -f /.JAIL ]
then export PS1="`cat /.JAIL`::$PS1"
fi

Csh users will need to modify that.  The idea there is to add something
to your prompt whenever you are in a chrooted environment so that you
don't forget where you are.  So far I haven't found a second situation
for it but it never hurts to think ahead.

Next you need to create the mount points for the directories that you
need to build packages other than the ones that you are replacing as
well as creating those replacement directories.  I do this from a
script and keep the list in a file called mountpoints.  Here is my list
but you may need something different in your environment:

bin
dev
etc
lib
libexec
sbin
usr/NetBSD/cvs/pkgsrc
usr/NetBSD/cvs/src
usr/NetBSD/cvs/xsrc
usr/X11R6
usr/bin
usr/ftp
usr/home
usr/include
usr/lib
usr/libdata
usr/libexec
usr/local
usr/sbin
usr/share
var/mail

Note that these need to be real directories.  Don't use "usr/pkgsrc"
for example if, like me, it is a symlink to the real pkgsrc directory
in CVS.

Next create an executable file called mkjail and link it to umkjail
with the following script:

#! /bin/sh

JAIL=/usr/pkg_jail

for i in tmp usr var usr/obj usr/pkg usr/tmp
do
  if [ ! -d $JAIL/$i ]
  then mkdir $JAIL/$i
  fi
done

for i in `cat $JAIL/mountpoints`
do
  if [ ! -d $JAIL/$i ]
  then mkdir -p $JAIL/$i
  fi
  if [ `basename $0` = "umkjail" ]
  then umount $JAIL/$i
  else mount_null /$i $JAIL/$i
  fi
done

Change the JAIL= line if you have it elsewhere.  The first for loop
creates working directories in your jail if they don't already exists.
The second one creates the mount points that you specified in the above
mountpoints file if they don't exist and then null mounts the live
directory onto it or, if called as umkjail, unmounts it.  A nice
enhancement here would be a way to only mount if it wasn't already
mounted so as not to mount on mounted systems.

Now you are ready to build your packages.  Simply chroot
to /usr/pkg_jail (your prompt will change to signify your current
state) and build your packages as you normally would.  You can build,
install and update without affecting your live system.  Once you have
successfully built all your packages you exit from the chrooted
environment and run the following script which I call sync_pkg.

#! /bin/sh

# This syncs up the pkg tree after building packages in the pkgsrc chroot jail

JAIL=/usr/pkg_jail

# we do it twice only deleting files the second time
for i in usr var/db
do
    rsync -av $JAIL/$i/pkg /$i
    rsync -av --delete $JAIL/$i/pkg /$i
done

Again, change the JAIL= line for your environment.

Note that I do an rsync twice above.  The reason is so that it first
installs all the new files and then deletes any old files not needed
any more.  This assures me that I am never without a version of all my
programs while upgrading to a new version that may have new names in
the installed area.  There may occasionally be times when things are
mismatched and fail but in most cases the system never has to be down
while installing.

That's it.  So far I have this running on two machines and I am about
to install it on a third one.  It works quite nice.  I just had to
replace a package due to a security alert and make update wound up
deinstalling and reinstalling KDE.  It was nice to have a working
system the whole time it was building those packages.

-- 
D'Arcy J.M. Cain <darcy@NetBSD.org>
http://www.NetBSD.org/