head 1.1; branch 1.1.1; access ; symbols MAXIMUM_RPM_1_0:1.1.1.1 VENDOR:1.1.1; locks ; strict; comment @# @; 1.1 date 2001.08.28.12.07.09; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.08.28.12.07.09; author rse; state Exp; branches ; next ; desc @@ 1.1 log @Initial revision @ text @ 21. Real-World Package Building Subsections

   
21. Real-World Package Building

In chapter [*], we packaged a fairly simple application. Since our goal was to introduce package building, we kept things as simple as possible. However, things aren't always that simple in the real world.

In this chapter, we'll package a more complex application that will call on most of RPM's capabilities. We'll start with a general overview of the application and end with a completed package, just as you would if you were tasked with packaging an application that you'd not seen before.

So without further ado, let's meet amanda...

   
21.1 An Overview of Amanda

Amanda is a network backup utility. The name amanda stands for ``Advanced Maryland Automatic Network Disk Archiver''. If the word ``Maryland'' seems somewhat incongruous, it helps to realize that the program was developed at the University of Maryland by James Da Silva, and has subsequently been enhanced by many people around the world.

The sources are available at ftp.cs.umd.edu, in directory /pub/amanda. At the time of writing, the latest version of amanda is version 2.3.0. Therefore, it should come as no surprise that the amanda source tar file is called amanda-2.3.0.tar.gz.

As with most network-centric applications, amanda has a server component, and a client component. An amanda server controls how the various client systems are backed up to the server's tape drive. Each amanda client uses the operating system's native dump utility to perform the actual backup, which is then compressed and sent to the server. A server can back itself up simply by having the client software installed and configured, just like any other client system.

The software builds with make, and most customization is done in two .h files in the config subdirectory. A fair amount of documentation is available in the doc subdirectory. All in all, amanda is a typical non-trivial application.

Amanda can be built on several Unix-based operating systems. In this chapter, we'll build and package amanda for Red Hat Linux version 4.0.  

   
21.2 Initial Building Without RPM

Since amanda can be built on numerous platforms, there needs to be some initial customization when first building the software. Since customization implies that mistakes will be made, we'll start off by building amanda without any involvement on the part of RPM.

But before we can build amanda, we have to get it and unpack it, first.

   
21.2.1 Setting Up A Test Build Area

As we mentioned above, the home FTP site for amanda is ftp.cs.umd.edu. The sources are in /pub/amanda.

After getting the sources, it's necessary to unpack them. We'll unpack them into RPM's SOURCES directory, so that we can keep all our work in one place:


# tar zxvf amanda-2.3.0.tar.gz
amanda-2.3.0/
amanda-2.3.0/COPYRIGHT
amanda-2.3.0/Makefile
amanda-2.3.0/README
...
amanda-2.3.0/man/amtape.8
amanda-2.3.0/tools/
amanda-2.3.0/tools/munge
#

As we saw, the sources unpacked into a directory called amanda-2.3.0. Let's rename that directory to amanda-2.3.0-orig, and unpack the sources again:


# ls
total 177
drwxr-xr-x 11 adm games 1024 May 19 1996 amanda-2.3.0/
-rw-r-r- 1 root root 178646 Nov 20 10:42 amanda-2.3.0.tar.gz
# mv amanda-2.3.0 amanda-2.3.0-orig
# tar zxvf amanda-2.3.0.tar.gz
amanda-2.3.0/
amanda-2.3.0/COPYRIGHT
amanda-2.3.0/Makefile
amanda-2.3.0/README
...
amanda-2.3.0/man/amtape.8
amanda-2.3.0/tools/
amanda-2.3.0/tools/munge
# ls
total 178
drwxr-xr-x 11 adm games 1024 May 19 1996 amanda-2.3.0/
drwxr-xr-x 11 adm games 1024 May 19 1996 amanda-2.3.0-orig/
-rw-r-r- 1 root root 178646 Nov 20 10:42 amanda-2.3.0.tar.gz
#

Now why did we do that? The reason lies in the fact that we will undoubtedly need to make changes to the original sources in order to get amanda to build on Linux. We'll do all our hacking in the amanda-2.3.0 directory, and leave the amanda-2.3.0-orig untouched.

Since one of RPM's design features is to build packages from the original, unmodified sources, that means the changes we'll make will need to be kept as a set of patches. The amanda-2.3.0-orig directory will let us issue a simple recursive diff command to create our patches when the time comes.

Now that our sources are unpacked, it's time to work on building the software.  

   
21.2.2 Getting Software to build

Looking at the docs/INSTALL file, we find that the steps required to get amanda configured and ready to build are actually fairly simple. The first step is to modify tools/munge to point to cpp, the C preprocessor.

Amanda uses CPP to create makefiles containing the appropriate configuration information. This approach is a bit unusual, but not unheard of. In munge, we find the following section:

# Customize CPP to point to your system's C preprocessor.

# if cpp is on your path:
CPP=cpp

# if cpp is not on your path, try one of these:
# CPP=/lib/cpp                  # traditional
# CPP=/usr/lib/cpp              # also traditional
# CPP=/usr/ccs/lib/cpp          # Solaris 2.x

Since cpp exists in /lib on Red Hat Linux, we need to change this part of munge to:

# Customize CPP to point to your system's C preprocessor.

# if cpp is on your path:
#CPP=cpp

# if cpp is not on your path, try one of these:
CPP=/lib/cpp                    # traditional
# CPP=/usr/lib/cpp              # also traditional
# CPP=/usr/ccs/lib/cpp          # Solaris 2.x

Next, we need to take a look in config/ and create two files:

  1. config.h -- contains platform-specific configuration information

  2. options.h -- contains site-specific configuration information

There are a number of example config.h files for a number of different platforms. There is a Linux-specific version, so we copy that file to config.h and review it. After a few changes to reflect our Red Hat Linux environment, it's ready. Now let's turn our attention to options.h.

In the case of options.h, there's only one example file called options.h-vanilla. As the name implies, this is a basic file that contains a series of #defines that configure amanda for a typical environment. We'll need to make a few changes:

While the first change is pretty much standard fare for anyone used to building software, the last two changes are really due to RPM. With RPM, there's no need to name the programs with a version-specific name, as RPM can easily upgrade to a new version and even downgrade back, if the new version doesn't work as well. The default paths amanda uses segregate the files so that they can be easily maintained. With RPM, there's no need to do this, since every file installed by RPM gets written into the database. In addition, Red Hat Linux systems adhere to the File System Standard, so any package destined for Red Hat systems should really be FSSTND-compliant, too. Fortunately for us, amanda was written to make these types of changes easy. But even if we had to hack an installation script, RPM would pick up the changes as part of its patch handling.

We'll spare you the usual discovery of typos, incompatibilities, and the resulting rebuilds. After an undisclosed number of iterations, our config.h and options.h files are perfect. Amanda builds:


# make
Making all in common-src
make[1]: Entering directory `/usr/src/redhat/SOURCES/amanda-2.3.0/com
mon-src'
...
make[1]: Leaving directory `/usr/src/redhat/SOURCES/amanda-2.3.0/man'
#

As we noted, amanda is constructed so that most of the time changes will only be necessary in tools/munge, and the two files in config. Our situation was no different -- after all was said and done, that was all we needed to hack.  

   
21.2.3 Installing and testing

As we all know, just because software builds doesn't mean that it's ready for prime-time. It's necessary to test it first. In order to test amanda, we need to install it. Amanda's makefile has an install target, so let's use that to get started. We'll also get a copy of the output, because we'll need that later:


# make install

Making install in common-src
...
make[1]: Entering directory `/usr/src/redhat/SOURCES/amanda-2.3.0/clien
t-src'
Installing Amanda client-side programs:
  install -c -o bin amandad /usr/lib/amanda
  install -c -o bin sendsize /usr/lib/amanda
  install -c -o bin calcsize /usr/lib/amanda
  install -c -o bin sendbackup-dump /usr/lib/amanda
  install -c -o bin sendbackup-gnutar /usr/lib/amanda
  install -c -o bin runtar /usr/lib/amanda
  install -c -o bin selfcheck /usr/lib/amanda
Setting permissions for setuid-root client programs:
  (cd /usr/lib/amanda ; chown root calcsize; chmod u+s calcsize)
  (cd /usr/lib/amanda ; chown root runtar; chmod u+s runtar)
...
Making install in server-src
Installing Amanda libexec programs:
  install -c -o bin taper /usr/lib/amanda
  install -c -o bin dumper /usr/lib/amanda
  install -c -o bin driver /usr/lib/amanda
  install -c -o bin planner /usr/lib/amanda
  install -c -o bin reporter /usr/lib/amanda
  install -c -o bin getconf /usr/lib/amanda
Setting permissions for setuid-root libexec programs:
  (cd /usr/lib/amanda ; chown root dumper; chmod u+s dumper)
  (cd /usr/lib/amanda ; chown root planner; chmod u+s planner)
Installing Amanda user programs:
  install -c -o bin amrestore /usr/sbin
  install -c -o bin amadmin /usr/sbin
  install -c -o bin amflush /usr/sbin
  install -c -o bin amlabel /usr/sbin
  install -c -o bin amcheck /usr/sbin
  install -c -o bin amdump /usr/sbin
  install -c -o bin amcleanup /usr/sbin
  install -c -o bin amtape /usr/sbin
Setting permissions for setuid-root user programs:
  (cd /usr/sbin ; chown root amcheck; chmod u+s amcheck)
...
Installing Amanda changer libexec programs:
  install -c -o bin chg-generic /usr/lib/amanda
...
Installing Amanda man pages:
  install -c -o bin amanda.8 /usr/man/man8
  install -c -o bin amadmin.8 /usr/man/man8
  install -c -o bin amcheck.8 /usr/man/man8
  install -c -o bin amcleanup.8 /usr/man/man8
  install -c -o bin amdump.8 /usr/man/man8
  install -c -o bin amflush.8 /usr/man/man8
  install -c -o bin amlabel.8 /usr/man/man8
  install -c -o bin amrestore.8 /usr/man/man8
  install -c -o bin amtape.8 /usr/man/man8
...
#

OK, no major problems there. Amanda does require a bit of additional effort to get everything running, though. Looking at docs/INSTALL, we follow the steps to get amanda running on our test system, as both a client and a server. As we perform each step, we note it for future reference:

Once everything is ready, we run a few tests. Everything performs flawlessly.1 Looks like we've got a good build. Let's start getting RPM involved.   

   
21.3 Initial Building With RPM

Now that amanda has been configured, built, and is operational on our build system, it's time to have RPM take over each of these tasks. The first task is to have RPM make the necessary changes to the original sources. To do that, RPM needs a patch file.

   
21.3.1 Generating patches

The amanda-2.3.0 directory tree is where we did all our work building amanda. We need to take all the work we've done in that directory tree and compare it against the original sources contained in the amanda-2.3.0-orig directory tree. But before we do that, we need to clean things up a bit.

21.3.1.1 Cleaning up the test build area

Looking through our work tree, it has all sorts of junk in it: emacs save files, object files, and the executable programs. In order to generate a clean set of patches, all these extraneous files must go. Looking over amanda's makefiles, there is a clean target that should take care of most of the junk:


# make clean

Making clean in common-src
...
rm -f *~ *.o *.a genversion version.c Makefile.out
...
Making clean in client-src
...
rm -f amandad sendsize calcsize sendbackup-dump
 sendbackup-gnutar runtar selfcheck  *~ *.o Makefile.out
...
Making clean in server-src
...
rm -f amrestore amadmin amflush amlabel amcheck amdump
 amcleanup amtape taper dumper driver planner reporter
 getconf *~ *.o Makefile.out
...
Making clean in changer-src
...
rm -f chg-generic *~ *.o Makefile.out
...
Making clean in man
...
rm -f *~ Makefile.out
...
#

Looking in the tools and config directories where we did all our work, we see there are still emacs save files there. A bit of studying confirms that the makefiles don't bother to clean these two directories. That's a nice touch because a make clean won't wipe out old copies of the config files, giving you a chance to go back to them in case you've botched something. However, in our case, we're sure we won't need the save files, so out they go:


# cd /usr/src/redhat/SOURCES/amanda-2.3.0
# find . -name "* " -exec rm -vf
\;
./config/config.h 
./config/options.h 
./tools/munge 
#

We let find take a look at the whole directory tree, just in case there was something still out there that we'd forgotten about. As you can see, the only save files are from the three files we've been working on.

You'll note that we've left our modified munge file, as well as the config.h and options.h files we so carefully crafted. That's intentional, as we want to make sure those changes are applied when RPM patches the sources. Everything looks pretty clean, so it's time to make the patches.

21.3.1.2 Actually Generating patches

This step is actually pretty anticlimactic:


# diff -uNr amanda-2.3.0-orig/ amanda-2.3.0/ > amanda-2.3.0-linux.patch
#

With that one command, we've compared each file in the untouched directory tree
(amanda-2.3.0-orig) with the directory tree we've been working in (amanda-2.3.0). If we've done our homework, the only things in the patch file should be related to the files we've changed. Let's take a look through it to make sure:


# cd /usr/src/redhat/SOURCES
# cat amanda-2.3.0-linux.patch

diff -uNr amanda-2.3.0-orig/config/config.h amanda-2.3.0/config/config.h
--- amanda-2.3.0-orig/config/config.h	Wed Dec 31 19:00:00 1969
+++ amanda-2.3.0/config/config.h	Sat Nov 16 16:22:47 1996
@@@@ -0,0 +1,52 @@@@
...
diff -uNr amanda-2.3.0-orig/config/options.h amanda-2.3.0/config/options.h
--- amanda-2.3.0-orig/config/options.h	Wed Dec 31 19:00:00 1969
+++ amanda-2.3.0/config/options.h	Sat Nov 16 17:08:57 1996
@@@@ -0,0 +1,211 @@@@
...
diff -uNr amanda-2.3.0-orig/tools/munge amanda-2.3.0/tools/munge
--- amanda-2.3.0-orig/tools/munge	Sun May 19 22:11:25 1996
+++ amanda-2.3.0/tools/munge	Sat Nov 16 16:23:50 1996
@@@@ -35,10 +35,10 @@@@
 # Customize CPP to point to your system's C preprocessor.
 
 # if cpp is on your path:
-CPP=cpp
+# CPP=cpp
 
 # if cpp is not on your path, try one of these:
-# CPP=/lib/cpp	                # traditional
+CPP=/lib/cpp                   # traditional
 # CPP=/usr/lib/cpp             # also traditional
 # CPP=/usr/ccs/lib/cpp         # Solaris 2.x
#

The patch file contains complete copies of our config.h and options.h files, followed by the changes we've made to munge. Looks good! Time to hand this grunt work over to RPM.  

   
21.3.2 Making a first-cut spec file

Since amanda comes in two parts, it's obvious we'll need to use subpackages: one for the client software, and one for the server. Given that, and the fact that the first part of any spec file consists of tags that are easily filled in, let's sit down and fill in the blanks, tag-wise:

Summary: Amanda Network Backup System
Name: amanda
Version: 2.3.08
Release: 1
Group: System/Backup
Copyright: BSD-like, but see COPYRIGHT file for details
Packager: Edward C. Bailey <bailey@@rpm.org>
URL: http://www.cs.umd.edu/projects/amanda/
Source: ftp://ftp.cs.umd.edu/pub/amanda/amanda-2.3.0.tar.gz
Patch: amanda-2.3.0-linux.patch
%description
Amanda is a client/server backup system.  It uses standard tape
devices and networking, so all you need is any working tape drive
and a network.  You can use it for local backups as well.

That part was pretty easy. We set the package's release number to 1. We'll undoubtedly be changing that as we continue work on the spec file. You'll notice that we've included a URL tag line; the Uniform Resource Locator there points to the homepage for the amanda project, making it easier for the user to get additional information on amanda.

The Source tag above includes the name of the original source tar file and is preceded by the URL pointing to the file's primary location. Again, this makes it easy for the user to grab a copy of the sources from the software's ``birthplace''.

Finally, the patch file that we've just created gets a line of its own on the Patch tag line. Next, let's take a look at the tags for our two subpackages. Let's start with the client:

%package client
Summary: Client-side Amanda package
Group: System/Backup
Requires: dump
%description client
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two packages -- a client (this package), and a server:

The client package enable a network-capable system to have its
filesystems backed up by a system running the Amanda server.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!

The %package directive names the package. Since we wanted the subpackages to be named amanda-<something>, we didn't use the -n option. This means our client subpackage will be called amanda-client, just as we wanted. RPM requires unique summary, %description, and group tags for each subpackage, so we've included them. Of course, it would be a good idea even if RPM didn't require them -- we've used the tags to provide client-specific information.

The requires tag is the only other tag in the client subpackage. Since amanda uses dump on the client system, we included this tag so that RPM will ensure that the dump package is present on client systems.

Next, let's take a look at the tags for the server subpackage:

%package server
Summary: Server-side Amanda package
Group: System/Backup
%description server
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two package -- a client, and a server (this package):

The server package enables a network-capable system to control one
or more Amanda client systems performing backups.  The server system
will direct all backups to a locally attached tape drive.  Therefore,
the server system requires a tape drive.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!

No surprises here, really. You'll note that the server subpackage has no requires tag for the dump package. The reason for that is due to a design decision we've made. Since amanda is comprised of a client and a server component, in order for the server system to perform backups of itself, the client component must be installed. Since we've already made the client subpackage require dump, we've already covered the bases.

Since an amanda server cannot back itself up without the client software, why don't we have the server subpackage require the client subpackage? Well, that could be done, but the fact of the matter is that there are cases where an amanda server won't need to back itself up. So the server subpackage needs no package requirements.

   
21.3.2.1 Adding the build-time scripts

Next we need to add the build-time scripts. There's really not much to them:

%prep
%setup

%build
make

%install
make install

The %prep script consists of one line containing the simplest flavor of %setup macro. Since we only need %setup to unpack one set of sources, there are no options we need to add.

The %build script is just as simple, with the single make command required to build amanda.

Finally, the %install script maintains our singe-line trend for build-time scripts. Here a simple make install will put all the files where they need to be for RPM to package them.   

21.3.2.2 Adding %files Lists

 

The last part of our initial attempt at a spec file is a %files list for each package the spec file will build. Since we're planning on a client and a server subpackage, we'll need two %files lists. For the time being, we'll just add the %files lines -- we'll be adding the actual filenames later:

%files client

%file server

There's certainly more to come, but this is enough to get us started. And the first thing we want RPM to do is to unpack the amanda sources.  

   
21.3.3 Getting the original sources unpacked

In keeping with a step-by-step approach, RPM has an option that let's us stop the build process after the %prep script has run. Let's give the -bp option a try, and see how things look:


# rpm -bp amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
+ umask 022
+ echo Executing: %prep
Executing: %prep
+ cd /usr/src/redhat/BUILD
+ cd /usr/src/redhat/BUILD
+ rm -rf amanda-2.3.0
+ gzip -dc /usr/src/redhat/SOURCES/amanda-2.3.0.tar.gz
+ tar -xvvf -
drwxr-xr-x 3/20              0 May 19 22:10 1996 amanda-2.3.0/
-rw-r--r-- 3/20           1389 May 19 22:11 1996 amanda-2.3.0/COPYRIGHT
-rw-r--r-- 3/20           1958 May 19 22:11 1996 amanda-2.3.0/Makefile
-rw-r--r-- 3/20          11036 May 19 22:11 1996 amanda-2.3.0/README
...
-rw-r--r-- 3/20           2010 May 19 22:11 1996 amanda-2.3.0/man/amtape.8
drwxr-xr-x 3/20              0 May 19 22:11 1996 amanda-2.3.0/tools/
-rwxr-xr-x 3/20           2437 May 19 22:11 1996 amanda-2.3.0/tools/munge
+ [ 0 -ne 0 ]
+ cd amanda-2.3.0
+ cd /usr/src/redhat/BUILD/amanda-2.3.0
+ chown -R root.root .
+ chmod -R a+rX,g-w,o-w .
+ exit 0
#

By looking at the output, it would be pretty hard to miss the fact that the sources were unpacked. If we look in RPM's default build area (/usr/src/redhat/BUILD), we'll see an amanda directory tree:


# cd /usr/src/redhat/BUILD/
# ls -l
total 3
drwxr-xr-x 11 root root 1024 May 19 1996 amanda-2.3.0
#

After a quick look around, it seems like the sources were unpacked properly. But wait -- where are our carefully crafted configuration files in config? Why isn't tools/munge modified?  

   
21.3.4 Getting patches properly applied

Ah, perhaps our %prep script was a bit too simple. We need to apply our patch. So let's add two things to our spec file:

  1. A patch tag line pointing to our patch file

  2. A %patch macro in our %prep script

Easy enough. At the top of the spec file, along with the other tags, let's add:

Patch: amanda-2.3.0-linux.patch

Then we'll make our %prep script look like this:

%prep
%setup
%patch -p 1

There, that should do it. Let's give that -bp option another try:


# rpm -bp amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
+ umask 022
+ echo Executing: %prep
Executing: %prep
+ cd /usr/src/redhat/BUILD
+ cd /usr/src/redhat/BUILD
+ rm -rf amanda-2.3.0
+ gzip -dc /usr/src/redhat/SOURCES/amanda-2.3.0.tar.gz
+ tar -xvvf -
drwxr-xr-x 3/20              0 May 19 22:10 1996 amanda-2.3.0/
-rw-r--r-- 3/20           1389 May 19 22:11 1996 amanda-2.3.0/COPYRIGHT
-rw-r--r-- 3/20           1958 May 19 22:11 1996 amanda-2.3.0/Makefile
-rw-r--r-- 3/20          11036 May 19 22:11 1996 amanda-2.3.0/README
...
-rw-r--r-- 3/20           2010 May 19 22:11 1996 amanda-2.3.0/man/amtape.8
drwxr-xr-x 3/20              0 May 19 22:11 1996 amanda-2.3.0/tools/
-rwxr-xr-x 3/20           2437 May 19 22:11 1996 amanda-2.3.0/tools/munge
+ [ 0 -ne 0 ]
+ cd amanda-2.3.0
+ cd /usr/src/redhat/BUILD/amanda-2.3.0
+ chown -R root.root .
+ chmod -R a+rX,g-w,o-w .
+ echo Patch #0:
Patch #0:
+ patch -p1 -s
+ exit 0
#

Not much difference, until the very end, where we see the patch being applied. Let's take a look into the build area and see if our configuration files are there:


# cd /usr/src/redhat/BUILD/amanda-2.3.0/config
# ls -l

total 58
-rw-r--r--   1 root     root         7518 May 19  1996 config-common.h
-rw-r--r--   1 root     root         1846 Nov 20 20:46 config.h
-rw-r--r--   1 root     root         2081 May 19  1996 config.h-aix
-rw-r--r--   1 root     root         1690 May 19  1996 config.h-bsdi1
...
-rw-r--r--   1 root     root         1830 May 19  1996 config.h-ultrix4
-rw-r--r--   1 root     root            0 Nov 20 20:46 config.h.orig
-rw-r--r--   1 root     root         7196 Nov 20 20:46 options.h
-rw-r--r--   1 root     root         7236 May 19  1996 options.h-vanilla
-rw-r--r--   1 root     root            0 Nov 20 20:46 options.h.orig
#

Much better. Those zero-length .orig files are a dead giveaway that patch has been here, as are the dates on config.h, and options.h. In the tools directory, munge has been modified, too. These sources are ready for building!  

   
21.3.5 Letting RPM do the Building

We know that the sources are ready. We know that the %build script is ready. There shouldn't be much in the way of surprises if we let RPM build amanda. Let's use the -bc option to stop things after the %build script completes:


# rpm -bc amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
...
 echo Executing: %build
Executing: %build
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make
Making all in common-src
make[1]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/common-src'
../tools/munge Makefile.in Makefile.out
make[2]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/common-src'
cc  -g  -I. -I../config   -c error.c -o error.o
cc  -g  -I. -I../config   -c alloc.c -o alloc.o
...
Making all in man
make[1]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
../tools/munge Makefile.in Makefile.out
make[2]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
make[2]: Nothing to be done for `all'.
make[2]: Leaving directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
make[1]: Leaving directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
+ exit 0
#

As we thought, no surprises. A quick look through the build area shows a full assortment of binaries, all ready to be installed. So it seems that the most natural thing to do next would be to let RPM install amanda.  

   
21.3.6 Letting RPM do the Installing

And that's just what we're going to do! Our %install script has the necessary make install command, so let's give it a shot:


# rpm -bi amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
...
 echo Executing: %build
Executing: %build
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make
Making all in common-src
make[1]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/common-src'
../tools/munge Makefile.in Makefile.out
make[2]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/common-src'
cc  -g  -I. -I../config   -c error.c -o error.o
cc  -g  -I. -I../config   -c alloc.c -o alloc.o
...
+ umask 022
+ echo Executing: %install
Executing: %install
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make install
Making install in common-src
make[1]: Entering directory `/usr/src/redhat/BUILD/amanda-2.3.0/common-src'
...
  install -c -o bin amrestore.8 /usr/man/man8
  install -c -o bin amtape.8 /usr/man/man8
make[2]: Leaving directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
make[1]: Leaving directory `/usr/src/redhat/BUILD/amanda-2.3.0/man'
+ exit 0
+ umask 022
+ echo Executing: special doc
Executing: special doc
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ DOCDIR=//usr/doc/amanda-2.3.0-1
+ DOCDIR=//usr/doc/amanda-client-2.3.0-1
+ DOCDIR=//usr/doc/amanda-server-2.3.0-1
+ exit 0
#

Everything looks pretty good. At this point, the amanda software, built by RPM, has been installed on the build system. Since performed all the configuration steps before, when we were manually building amanda, everything should still be configured properly to test this new build.2 So why don't we give the new binaries a try?  

   
21.3.7 Testing RPM's Handiwork

After a quick double-check to ensure that all the configuration steps were still in place from our manual build, we reran our tests. No problems were found. It's time to build some packages!   

   
21.4 Package Building

OK, let's go for broke and tell RPM to do the works, including the creation of the binary and source packages:


# rpm -ba amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
...
 echo Executing: %build
Executing: %build
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make
Making all in common-src
...
+ echo Executing: %install
Executing: %install
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make install
Making install in common-src
...
+ echo Executing: special doc
Executing: special doc
...
Binary Packaging: amanda-client-2.3.0-1
Finding dependencies...
Requires (1): dump
1 block
Generating signature: 0
Wrote: /usr/src/redhat/RPMS/i386/amanda-client-2.3.0-1.i386.rpm
Binary Packaging: amanda-server-2.3.0-1
Finding dependencies...
1 block
Generating signature: 0
Wrote: /usr/src/redhat/RPMS/i386/amanda-server-2.3.0-1.i386.rpm
+ umask 022
+ echo Executing: %clean
Executing: %clean
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ exit 0
Source Packaging: amanda-2.3.0-1
amanda-2.3.0.spec
amanda-2.3.0-linux.patch
amanda-2.3.0.tar.gz
374 blocks
Generating signature: 0
Wrote: /usr/src/redhat/SRPMS/amanda-2.3.0-1.src.rpm
#

Great! Let's take a look at our handiwork:


# cd /usr/src/redhat/RPMS/i386/
# ls -l

total 2
-rw-r--r-- 1 root  root   1246 Nov 20 21:19 amanda-client-2.3.0-1.i386.rpm
-rw-r--r-- 1 root  root   1308 Nov 20 21:19 amanda-server-2.3.0-1.i386.rpm
# 
rpm-first-look

Hmmm, those binary packages look sort of small. We'd better see what's in there:


# rpm -qilp amanda-*-1.i386.rpm

Name        : amanda-client         Distribution: (none)
Version     : 2.3.0                       Vendor: (none)
Release     : 1                       Build Date: Wed Nov 20 21:19:44 1996
Install date: (none)                  Build Host: moocow.rpm.org
Group       : System/Backup           Source RPM: amanda-2.3.0-1.src.rpm
Size        : 0
Summary     : Client-side Amanda package
Description :
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two packages -- a client (this package), and a server:

The client package enable a network-capable system to have its
filesystems backed up by a system running the Amanda server.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!
(contains no files)

Name        : amanda-server         Distribution: (none)
Version     : 2.3.0                       Vendor: (none)
Release     : 1                       Build Date: Wed Nov 20 21:19:44 1996
Install date: (none)                  Build Host: moocow.rpm.org
Group       : System/Backup           Source RPM: amanda-2.3.0-1.src.rpm
Size        : 0
Summary     : Server-side Amanda package
Description :
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two package -- a client, and a server (this package):

The server package enables a network-capable system to control one
or more Amanda client systems performing backups.  The server system
will direct all backups to a locally attached tape drive.  Therefore,
the server system requires a tape drive.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!
(contains no files)

#

What do they mean, (contains no files)? The spec file has perfectly good %files lists...

Oops.  

21.4.1 Creating the %files list

 

Everything was going so smoothly, we forgot that the %files lists were going to need files. No problem, we just need to put the filenames in there, and we'll be all set. But is it really that easy?

21.4.1.1 How to find the installed files?

Luckily, it's not too bad. Since we saved the output from our first make install, we can see the filenames as they're installed. Of course, it's important to make sure the install output is valid. Fortunately for us, amanda didn't require much fiddling by the time we got it built and tested. If it had, we would have had to get more recent output from the installation phase.

It's time for more decisions. We have one list of installed files, and two %files lists. It would be silly to put all the files in both %files lists, so we have to decide which file goes where.

This is where experience with the software really pays off, because the wrong decision made here can result in awkward, ill-featured packages. Here's the %files list we came up with for the client subpackage:

%files client
/usr/lib/amanda/amandad
/usr/lib/amanda/sendsize
/usr/lib/amanda/calcsize
/usr/lib/amanda/sendbackup-dump
/usr/lib/amanda/selfcheck
/usr/lib/amanda/sendbackup-gnutar
/usr/lib/amanda/runtar
README
COPYRIGHT
docs/INSTALL
docs/SYSTEM.NOTES
docs/WHATS.NEW

The files in /usr/lib/amanda are all the client-side amanda programs, so that part was easy. The remaining files are part of the original source archive. Amanda doesn't install them, but they contain information that users should see.

Realizing that RPM can't package these files specified as they are, let's leave the client %files list for a moment, and check out the list for the server subpackage:

%files server
/usr/sbin/amadmin
/usr/sbin/amcheck
/usr/sbin/amcleanup
/usr/sbin/amdump
/usr/sbin/amflush
/usr/sbin/amlabel
/usr/sbin/amrestore
/usr/sbin/amtape
/usr/lib/amanda/taper
/usr/lib/amanda/dumper
/usr/lib/amanda/driver
/usr/lib/amanda/planner
/usr/lib/amanda/reporter
/usr/lib/amanda/getconf
/usr/lib/amanda/chg-generic
/usr/man/man8/amanda.8
/usr/man/man8/amadmin.8
/usr/man/man8/amcheck.8
/usr/man/man8/amcleanup.8
/usr/man/man8/amdump.8
/usr/man/man8/amflush.8
/usr/man/man8/amlabel.8
/usr/man/man8/amrestore.8
/usr/man/man8/amtape.8
README
COPYRIGHT
docs/INSTALL
docs/KERBEROS
docs/SUNOS4.BUG
docs/SYSTEM.NOTES
docs/TAPE.CHANGERS
docs/WHATS.NEW
docs/MULTITAPE
example

The files in /usr/sbin are programs that will be run by the amanda administrator in order to perform backups and restores. The files in /usr/lib/amanda are the server-side programs that do the actual work during backups. Following that are a number of man pages: one for each program to be run by the amanda administrator, and one with an overview of amanda.

Bringing up the rear are a number of files that are not installed, but would be handy for the amanda administrator to have available. There is some overlap with the files that will be part of the client subpackage, but the additional files here discuss features that would interest only amanda administrators. Included here is the example subdirectory, which contains a few example configuration files for the amanda server.

As in the client %files list, these last files can't be packaged by RPM as we've listed them. We need to use a few more of RPM's tricks to get them packaged.

   
21.4.1.2 Applying Directives

Since we'd like the client subpackage to include those files that are not normally installed, and since the files are documentation, let's use the %doc directive on them. That will accomplish two things:

  1. When the client subpackage is installed, it will direct RPM to place them in a package-specific directory in /usr/doc

  2. It will tag the files as being documentation, making it possible for users to easily track down the documentation with a simple rpm -qd command

In the course of looking over the %files lists, it becomes apparent that the directory /usr/lib/amanda will contain only files from the two amanda subpackages. If the subpackages are erased, the directory will remain, which won't hurt anything, but it isn't as neat as it could be. But if we add the directory to the list, RPM will automatically package every file in the directory. Since the files in that directory are part of both the client and the server subpackages, we'll need to use the %dir directive to instruct RPM to package only the directory.

After these changes, here's what the client %files list looks like now:

%files client
%dir /usr/lib/amanda/
/usr/lib/amanda/amandad
/usr/lib/amanda/sendsize
/usr/lib/amanda/calcsize
/usr/lib/amanda/sendbackup-dump
/usr/lib/amanda/selfcheck
/usr/lib/amanda/sendbackup-gnutar
/usr/lib/amanda/runtar
%doc README
%doc COPYRIGHT
%doc docs/INSTALL
%doc docs/SYSTEM.NOTES
%doc docs/WHATS.NEW

We've also applied the same directives to the server %files list:

%files server
/usr/sbin/amadmin
/usr/sbin/amcheck
/usr/sbin/amcleanup
/usr/sbin/amdump
/usr/sbin/amflush
/usr/sbin/amlabel
/usr/sbin/amrestore
/usr/sbin/amtape
%dir /usr/lib/amanda/
/usr/lib/amanda/taper
/usr/lib/amanda/dumper
/usr/lib/amanda/driver
/usr/lib/amanda/planner
/usr/lib/amanda/reporter
/usr/lib/amanda/getconf
/usr/lib/amanda/chg-generic
/usr/man/man8/amanda.8
/usr/man/man8/amadmin.8
/usr/man/man8/amcheck.8
/usr/man/man8/amcleanup.8
/usr/man/man8/amdump.8
/usr/man/man8/amflush.8
/usr/man/man8/amlabel.8
/usr/man/man8/amrestore.8
/usr/man/man8/amtape.8
%doc README
%doc COPYRIGHT
%doc docs/INSTALL
%doc docs/KERBEROS
%doc docs/SUNOS4.BUG
%doc docs/SYSTEM.NOTES
%doc docs/TAPE.CHANGERS
%doc docs/WHATS.NEW
%doc docs/MULTITAPE
%doc example

You'll note that we neglected to use the %doc directive on the man page files. The reason is that RPM automatically tags any file destined for /usr/man as documentation. Now our spec file has a complete set of tags, the two subpackages are defined, it has build-time scripts that work, and now, %files lists for each subpackage. Why don't we try that build again?


# rpm -ba amanda-2.3.0.spec

* Package: amanda
* Package: amanda-client
* Package: amanda-server
...
 echo Executing: %build
Executing: %build
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make
Making all in common-src
...
+ echo Executing: %install
Executing: %install
+ cd /usr/src/redhat/BUILD
+ cd amanda-2.3.0
+ make install
Making install in common-src
...
+ echo Executing: special doc
Executing: special doc
...
Binary Packaging: amanda-client-2.3.0-6
Finding dependencies...
Requires (3): libc.so.5 libdb.so.2 dump
usr/doc/amanda-client-2.3.0-6
usr/doc/amanda-client-2.3.0-6/COPYRIGHT
usr/doc/amanda-client-2.3.0-6/INSTALL
...
usr/lib/amanda/sendbackup-gnutar
usr/lib/amanda/sendsize
1453 blocks
Generating signature: 0
Wrote: /usr/src/redhat/RPMS/i386/amanda-client-2.3.0-6.i386.rpm
Binary Packaging: amanda-server-2.3.0-6
Finding dependencies...
Requires (2): libc.so.5 libdb.so.2
usr/doc/amanda-server-2.3.0-6
usr/doc/amanda-server-2.3.0-6/COPYRIGHT
usr/doc/amanda-server-2.3.0-6/INSTALL
...
usr/sbin/amrestore
usr/sbin/amtape
3404 blocks
Generating signature: 0
Wrote: /usr/src/redhat/RPMS/i386/amanda-server-2.3.0-6.i386.rpm
...
Source Packaging: amanda-2.3.0-6
amanda-2.3.0.spec
amanda-2.3.0-linux.patch
amanda-rpm-instructions.tar.gz
amanda-2.3.0.tar.gz
393 blocks
Generating signature: 0
Wrote: /usr/src/redhat/SRPMS/amanda-2.3.0-6.src.rpm
#

If we take a quick look at the client and server subpackages, we find that, sure enough, this time they contain files:


# cd /usr/src/redhat/RPMS/i386/
# ls -l amanda-*

-rw-r--r-- 1 root  root  211409 Nov 21 15:56 amanda-client-2.3.0-1.i386.rpm
-rw-r--r-- 1 root  root  512814 Nov 21 15:57 amanda-server-2.3.0-1.i386.rpm
# rpm -qilp amanda-*
Name        : amanda-client         Distribution: (none)
Version     : 2.3.0                       Vendor: (none)
Release     : 1                       Build Date: Thu Nov 21 15:55:59 1996
Install date: (none)                  Build Host: moocow.rpm.org
Group       : System/Backup           Source RPM: amanda-2.3.0-1.src.rpm
Size        : 737101
Summary     : Client-side Amanda package
Description :
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two packages -- a client (this package), and a server:

The client package enable a network-capable system to have its
filesystems backed up by a system running the Amanda server.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!

/usr/doc/amanda-client-2.3.0-1
/usr/doc/amanda-client-2.3.0-1/COPYRIGHT
/usr/doc/amanda-client-2.3.0-1/INSTALL
...
/usr/lib/amanda/sendbackup-gnutar
/usr/lib/amanda/sendsize

Name        : amanda-server         Distribution: (none)
Version     : 2.3.0                       Vendor: (none)
Release     : 1                       Build Date: Thu Nov 21 15:55:59 1996
Install date: (none)                  Build Host: moocow.rpm.org
Group       : System/Backup           Source RPM: amanda-2.3.0-1.src.rpm
Size        : 1733825
Summary     : Server-side Amanda package
Description :
The Amanda Network Backup system contains software necessary to
automatically perform backups across a network.  Amanda consists of
two package -- a client, and a server (this package):

The server package enables a network-capable system to control one
or more Amanda client systems performing backups.  The server system
will direct all backups to a locally attached tape drive.  Therefore,
the server system requires a tape drive.

NOTE: In order for a system to perform backups of itself, install both
the client and server packages!

/usr/doc/amanda-server-2.3.0-1
/usr/doc/amanda-server-2.3.0-1/COPYRIGHT
/usr/doc/amanda-server-2.3.0-1/INSTALL
...
/usr/sbin/amrestore
/usr/sbin/amtape
#

We're finally ready to test these packages!   

   
21.4.2 Testing those first packages

The system we've built the packages on already has amanda installed. This is due to the build process itself. However, we can install the new packages on top of the already-existing files:


# cd /usr/src/redhat/RPMS/i386
# rpm -ivh amanda-*-1.i386.rpm

amanda-client       ##################################################
amanda-server       ##################################################
#

Running some tests, it looks like everything is running well. But back in chapter [*], specifically section [*] on page [*], we mentioned that it was possible to install a newly-built package on the build system, and not realize that the package was missing files. Well, there's another reason why installing the package on the build-system for testing is a bad idea. Let's bring our packages to a different system, test them there, and see what happens.

21.4.2.1 Installing the Package On A Different System

Looks like we're almost through. Let's install the packages on another system that had not previously run amanda, and test it there:


# rpm -ivh amanda-*-1.i386.rpm

amanda-client       ##################################################
amanda-server       ##################################################
#

The install went smoothly enough. However, testing did not. Why? Nothing was set up! The server configuration files, the inetd.conf entry for the client, everything was missing. If we stop and thing about it for a moment that makes sense: we had gone through all those steps on the build system, but none of those steps can be packaged as files.

After following the steps in the installation instructions, everything works. While we could expect users to do most of the grunt work associated with getting amanda configured, RPM does have the ability to run scripts when packages are installed and erased. Why don't we use that feature to make life easier for our users?  

21.4.3 Finishing Touches

At this point in the build process, we're on the home stretch. The software builds correctly and is packaged. It's time to stop looking at things from a ``build the software'' perspective, and time to starting looking at things from a ``package the software'' point of view.

The difference lies in looking at the packages from the user's perspective. Does the package install easily, or does it require a lot of effort to make it operative? When the package is removed, does it clean up after itself, or does it leave bits and pieces strewn throughout the filesystem?

Let's put a bit more effort into this spec file, and make life easier on our users.

   
21.4.3.1 Creating Install Scripts

When it comes to needing post-installation configuration, amanda certainly is no slouch! We'll work on the client first. Let's look at a section of the script we wrote, comment on it, and move on:

%post client

# See if they've installed amanda before...
# If they have, none of this should be necessary...

if [ "$1" = 1 ];
then

First, we start the script with a %post statement, and indicate that this script is for the client subpackage. As the comments indicate, we only want to perform the following tasks if this is the first time the client subpackage has been installed. To do this, we use the first and only argument passed to the script. It is a number indicating how many instances of this package will be installed after the current installation is complete.

If the argument is equal to 1, that means that no other instances of the client subpackage are presently installed, and that this one is the first. Let's continue:

# Set disk devices so that bin can read them
# (This is actually done on Red Hat Linux; only need to add bin to
#  group disk)

if grep "^disk::.*bin" /etc/group > /dev/null
then
        true
else

# If there are any members in group disk, add bin after a comma...
 sed -e 's/\(^disk::[0-9]\{1,\}:.\{1,\}\)/\1,bin/' /etc/group > /etc/grou
p.tmp

# If there are no members in group disk, add bin...
sed -e 's/\(^disk::[0-9]\{1,\}:$\)/\1bin/' /etc/group.tmp > /etc/group

# clean up!
 rm -f /etc/group.tmp
fi

One of amanda's requirements is that the user ID running the dumps on the client needs to be able to read from every disk's device file. The folks at Red Hat have done half the work for us by creating a group disk and giving that group read/write access to every disk device. Since our dumpuser is bin, we only need to add bin to the disk group. Two lines of sed, and we're done!

The next section is related to the last. It also focuses on making sure bin can access everything it needs while doing backups:

# Also set /etc/dumpdates to be writable by group disk

chgrp disk /etc/dumpdates
chmod g+w /etc/dumpdates

Since amanda uses dump to obtain the backups, and since dump keeps track of the backups in /etc/dumpdates, it's only natural that bin will need read/write access to the file. In a perfect world, /etc/dumpdates would have already been set to allow group disk to read and write, but we had to do it ourselves. It's not a big problem, though.

Next, we need to create the appropriate network-related entries, so that amanda clients can communicate with amanda servers, and vice versa:

# Add amanda line to /etc/services

if grep "^amanda" /etc/services >/dev/null
then
        true
else
        echo "amanda    10080/udp # Added by package amanda-client" >>
/etc/services
fi

By using grep to look for lines that begin with the letters amanda, we can easily see if /etc/services is already configured properly. It it isn't, we simply append a line to the end.

We also added a comment so that sysadmins will know where the entry came from, and either take our word for it or issue an rpm -q - -scripts amanda-client command and see for themselves. We did it all on one line because it makes the script simpler.

Let's look at the rest of the network-related part of this script:

# Add amanda line to /etc/inetd.conf

if grep "^amanda" /etc/inetd.conf >/dev/null
then
        true 
else
        echo "amanda dgram udp wait bin /usr/lib/amanda/amandad amandad
  # added by package amanda-client" >>/etc/inetd.conf

# Kick inetd

if [ -f /var/run/inetd.pid ];
then
        kill -HUP `cat /var/run/inetd.pid`
fi
fi
fi

Here, we've used the same approach to add an entry to /etc/inetd.conf. We then hup inetd so the change will take affect, and we're done!

Oh, and that last fi at the end? That's to close the if [ "$1" = 1 ] at the start of the script. Now let's look at the server's post-install script:

%post server

# See if they've installed amanda before...

if [ "$1" = 1 ];
then

# Add amanda line to /etc/services

if grep "^amanda" /etc/services >/dev/null
then
        true
else
        echo "amanda    10080/udp # Added by package amanda-server"
 >>/etc/services
fi

fi

That was short! And this huge difference brings up a good point about writing install scripts: It's important to understand what you as the package builder should do for the user, and what they should do for themselves.

In the case of the client package, every one of the steps performed by the post-install script was something that a fairly knowledgeable user could have done. But each of these steps have one thing in common. No matter how the user configures amanda, these steps will never change. And given the nature of client/server applications, there's a good chance that many more amanda client packages will be installed than amanda servers. Would you like to be tasked with installing this package on twenty systems, and performing each of the steps we've automated, twenty times? We thought not.

There is one step that we did not automate for the client package. The step we left out is the creation of a .rhosts file. Since this file must contain the name of the amanda server, we have no way of knowing what the file should look like. Therefore, that's one step we can't automate.

The server's post-install script is so short because there's little else that can be automated. The other steps required to set up an amanda server include:

  1. Choosing a configuration name, which requires user input

  2. Creating a directory to hold the server configuration files, named according to the configuration name, which depends on the first step

  3. Modifying example configuration files to suit the site, which requires user input

  4. Adding crontab entries to run amanda nightly, which requires user input

Since every step depends on the user making decisions, the best way to handle them is to not handle them at all. Let the user do it!

21.4.3.2 Creating Uninstall Scripts

Where there are install scripts, there are uninstall scripts. While there is no ironclad rule to that effect, it is a good practice. Following this practice, we have an uninstall script for the client package, and one for the server. Let's take the client first:

%postun client

# First, see if we're the last amanda-client package on the system...
# If not, then we don't need to do this stuff...

if [ "$1" = 0 ];
then

As before, we start out with a declaration of the type of script this is, and which subpackage it is for. Following that we have an if statement similar to the one we used in the install scripts, save one difference. Here, we're comparing the argument against zero. The reason is that we are trying to see if there will be zero instances of this package after the uninstall is complete. If this is the case, the remainder of the script needs to be run, since there are no other amanda client packages left.

Next, we remove bin from the disk group:

# First, get rid of bin from the disk group...

if grep "^disk::.*bin" /etc/group > /dev/null
then

#       Nuke bin at the end of the line...
        sed -e 's/\(^disk::[0-9]\{1,\}:.\{1,\}\),bin$/\1/' /etc/group
 > /etc/group.tmp

#       Nuke bin on the line by itself...
        sed -e 's/\(^disk::[0-9]\{1,\}:\)bin$/\1/' /etc/group.tmp
 > /etc/group1.tmp

#       Nuke bin in the middle of the line...
        sed -e 's/\(^disk::[0-9]\{1,\}:.\{1,\}\),bin,\(.\{1,\}\)/\1,\2/'
 /etc/group1.tmp > /etc/group2.tmp

#       Nuke bin at the start of the line...
        sed -e 's/\(^disk::[0-9]\{1,\}:\)bin,\(.\{1,\}\)/\1\2/'
 /etc/group2.tmp > /etc/group

#       Clean up after ourselves...
        rm -f /etc/group.tmp /etc/group1.tmp /etc/group2.tmp
fi

No surprises there. Continuing our uninstall, we start on the network-related tasks:

# Next, lose the amanda line in /etc/services...
# We only want to do this if the server package isn't installed
# Look for /usr/sbin/amdump, and leave it if there...

if [ ! -f /usr/sbin/amdump ];
then

        if grep "^amanda" /etc/services > /dev/null
        then
                grep -v "^amanda" /etc/services > /etc/services.tmp
                mv -f /etc/services.tmp /etc/services
        fi
fi

That's odd. Why are we looking for a file from the server package? If you look back at the install scripts for the client and server packages, you'll find that the one thing they have in common is that both the client and the server require the same entry in /etc/services.

If an amanda server is going to back itself up, it also needs the amanda client software. Therefore, both subpackages need to add an entry to /etc/services. But what if one of the packages is removed? Perhaps the server is being demoted to a client, or maybe the server is no longer going to be backed up using amanda. In these cases, the entry in/etc/services must stay. So, in the case of the client, we look for a file from the server subpackage, and if it's there, we leave the entry alone.

Granted, this is a somewhat unsightly way to see if a certain package is installed. Some of you are probably even saying, ``Why can't RPM be used? Just do an rpm -q amanda-server, and decide what to do based on that.'' And that would be the best way to do it, except for one small point:

Only one invocation of RPM can run at any given time.

Since RPM is running to perform the uninstall, if the uninstall-script were to attempt to run RPM again, it would fail. The reason it would fail is because only one copy of RPM can access the database at a time. So we are stuck with our unsightly friend.

Continuing the network-related uninstall tasks:

# Finally, the amanda entry in /etc/inetd.conf

if grep "^amanda" /etc/inetd.conf > /dev/null
then
        grep -v "^amanda" /etc/inetd.conf > /etc/inetd.conf.tmp
        mv -f /etc/inetd.conf.tmp /etc/inetd.conf

# Kick inetd

if [ -f /var/run/inetd.pid ];
then
        kill -HUP `cat /var/run/inetd.pid`
fi
fi

fi

Here, we're using grep's ability to return lines that don't match the search string, in order to remove every trace of amanda from /etc/inetd.conf. After issuing a hup on inetd, we're done.

On to the server. If you've been noticing a pattern between the various scripts, you won't be disappointed here:

%postun server

# See if we're the last server package on the system...
# If not, we don't need to do any of this stuff...

if [ "$1" = 0 ];
then

# Lose the amanda line in /etc/services...
# We only want to do this if the client package isn't installed
# Look for /usr/lib/amandad, and leave it if there...

if [ ! -f /usr/lib/amanda/amandad ];
then

        if grep "^amanda" /etc/services > /dev/null
        then
                grep -v "^amanda" /etc/services > /etc/services.tmp
                mv -f /etc/services.tmp /etc/services
        fi
fi

fi

By now the opening if statement is an old friend. As you might have expected, we are verifying whether the client package is installed, by looking for a file from that package. If the client package isn't there, the entry is removed from /etc/services. And that, is that.

Obviously, these scripts must be carefully tested. In the case of amanda, since the two subpackages have some measure of interdependency, it's necessary to try different sequences of installing and erasing the two packages to make sure the /etc/services logic works properly in all cases.

After a bit of testing, our install and uninstall scripts pass with flying colors. From a technological standpoint, the client and server subpackages are ready to go.  

21.4.3.3 Bits and Pieces

However, just because a package has been properly built, and installs and can be erased without problems, doesn't mean that the package builder's job is done. It's necessary to look at each newly-built package from the user's perspective. Does the package contain everything the user needs in order to deploy it effectively? Or will the user need to fiddle with it, guessing as they go?

In the case of our amanda packages, it was obvious that some additional documentation was required so that the user would know what needed to be done in order to finalize the installation. Simply directing the user to the standard amanda documentation wasn't the right solution, either. Many of the steps outlined in the INSTALL document had already been done by the post-install scripts. No, an interim documente was required. Two, actually: one for the client, and one for the server.

So two files were created, one to be added to each subpackage. The question was, how to do it? Essentially, there were two options:

  1. Put the files in the amanda directory tree that had been used to perform the initial builds and generate a new patch file

  2. Create a tar file containing the two files, and modify the spec file to unpack the documentation into the amanda directory tree.

  3. Drop the files directly into the amanda directory tree without using tar.

Since the second approach was more interesting, that's the approach we chose. It required an additional source tag in the spec file:

Source1: amanda-rpm-instructions.tar.gz

Also required was an additional %setup macro in the %prep script:

%setup -T -D -a 1

While the %setup macro might look intimidating, it wasn't that hard to construct. Here's what each options means:

-T
-- Do not perform the default archive unpacking.

-D
-- Do not delete the directory before unpacking.

-a 1
-- Unpack the archive specified by the source1 tag after changing directory.

Finally, two additions to the %files lists were required. One for the client:

%doc amanda-client.README

And one for the server:

%doc amanda-server.README

At this point, the packages were complete. Certainly there is software out there that doesn't require this level of effort to package. Just as certainly there is software that is much more of a challenge. Hopefully this chapter has given you some idea about how to approach package building for more complex applications.  



Ralf S. Engelschall 2000-12-15
@ 1.1.1.1 log @Import book 'Maximum RPM' by Ed Bailey, version 1.0 @ text @@