Re: updating woes with apt and rpm

"Herton Krzesinski" <[email protected]> Wed, 22 Mar 2006 14:54:57 -0300
Newsgroups gmane.linux.conectiva.apt-rpm
Message-ID <[email protected]>
First, about rpm, you can modify the spec of rpm you are building to
do automatically do the removal of __db* files and rebuild rpm
database, along with doing a --rebuilddb. You probably had an older
rpm version with a package database using an older bdb format. For
example, Conectiva Linux rpm package do this in rpm package:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D
%triggerun -n rpm -- rpm =3D 4.0.4
[ "$2" =3D "0" ] || exit 0
rpm --rebuilddb

%post -n rpm
rm -f %{_sysconfdir}/rpm/macros.db1*
if [ ! -f %{_localstatedir}/lib/rpm/Packages ]; then
       /bin/rpm --initdb
fi

# Based on the scriptlet of the spec included in the tarball.
if [ -w /var/lib/rpm/__db.001 ] &&
  /usr/lib/rpm/rpmdb_stat -CA -h /var/lib/rpm 2>&1 |
  grep -q "db_stat: Program version 4.3 doesn't match environment version"
then
       rm -f /var/lib/rpm/__db*
fi
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D

The first four lines in the %post section above is irrelevant for you
in this case. You can make code like that on spec to do the job. But
be careful and test. Good  documentation about rpm scriptlets and rpm
packaging in general can be found in those links:
http://www-106.ibm.com/developerworks/library/l-rpm1/
http://www-106.ibm.com/developerworks/library/l-rpm2/
http://www-106.ibm.com/developerworks/library/l-rpm3/
(this last one talks about scriptlets)

On 3/22/06, Matthew Smith <[email protected]> wrote:
> Hello!
>
> I hope this is appropriate for this list, sorry if it is not. I am runnin=
g out
> of ideas...
>
> I maintain an apt repository that updates 100+ servers (running a custom =
RHEL
> respin). I don't have direct access to these servers, so I can't run comm=
and
> or alter them directly. The servers are updated when the people responsib=
le
> for each machine triggers an update (then a cron job triggers apt-get
> --assume-yes dist-upgrade that night).
>
> I have a series of updates that I'd like to roll out to these machines, b=
ut I
> am having trouble with 2 critical packages. When both these packages are
> updated (along with all the other packages in my update) the RPM database
> becomes corrupt, with the following error:
>
> rpmdb: PANIC: fatal region error detected; run recovery
> error: db4 error(-30978) from dbenv->close: DB_RUNRECOVERY: Fatal error, =
run
> database recovery
>
> If I then do the following:
> rm -f /var/lib/rpm/__db*
> db_verify /var/lib/rpm/Packages
> rpm --rebuilddb
>
> the rpm errors no longer occur, and everything works fine from then on in=
.
> Sadly it is not feasible to run this on every machine after the update, a=
s
> the ends users to not have the required knowedge and the task of getting
> access to every one and altering them is rather daunting.
>
> I discovered that by installing rpm 4.2.3-24 onto my test server beforeha=
nd,
> then doing a 'dist-upgrade', everything runs through fine. If I add that
> version of rpm to my repository, then any subsequent runs of apt-get
> dist-upgrade gives me a massive list of dependency errors, and a "-f inst=
all"
> gets apt to reinstall the missing packages. In other words, the rpm datab=
ase
> is still getting corrupted in some slightly different way. I assume the n=
ew
> version of rpm would only be used after the work apt-get is doing complet=
es,
> so this is not a supprise.

Pay attention to (so)name changes on libs, if dependency errors occurs
you may have to recompile all packages that depends on new librpm, in
this case is strange why rpm wouldn't complain about dependencies
before the installation, may be you forced the rpm install with
--nodeps?
Example: you have installed rpm 4.2 that have /usr/lib/librpm-4.2.so,
with some  applications compiled against librpm-4.2.so. If you install
newer rpm 4.4 package, that have /usr/lib/librpm-4.4.so, the forced
upgrade process remove /usr/lib/librpm-4.2.so, making all applications
compiled against it broken and without a package providing
librpm-4.2.so in case of rpm automatic dependencies. So what you need
to do is or recompiling all programs with new rpm 4.4 or including
soname inside the package name to avoid rpm to remove old lib on
upgrade, example, if you had the package providing the libs named
librpm you must rename it to librpm4.4 for example to rpm not remove
old librpm.

Generally to avoid these problems on upgrades for any package that
contains something like libfoobar.so.N you generally split the package
in subpackages, one containing common files if they exist, and the
others for the libs that have/will have different soname versions, to
avoid problems on upgrades. Or you recompile all aplications against
newer libraries. You can found on many distros examples of how this is
done, for example libtiff3 instead of libtiff etc.

Example: foobar project, foobar package subdivided in following
subpackages with their files:
foobar (could be also libfoobar or foobar-progs etc.): /usr/bin/foobar
libfoobar1: /usr/lib/libfoobar.so.1 /usr/lib/libfoobar.so.1.4
libfoobar-devel: /usr/lib/foobar.so /usr/libfoobar.la

Note that the soname on name of libfoobar makes upgrade easier when
libfoobar changes soname, example, a major version 2 is released with
/usr/lib/libfoobar.so.2 file, when making an package update all foobar
and libfoobar-devel can be updated but you then can have libfoobar1
and libfoobar2 coexisting on the same system because of diferent name
and not breaking packages still compiled with older libfoobar.so.1. So
you divide the package placing common files under the same name to
avoid conflicts on upgrades, and placing *.so.* files on packages with
diferent name putting the soname information on it. This is generally
how you can play with package names that have libraries with different
major versions to easier upgrades.

>
> So the only way that I can see to upgrade these machines is by getting a
> select few packages to install, then install the rest on a second run of =
apt.
> All of this needs to be done by altering the apt repository, as I cannot =
make
> changes to the servers directly.
>
> I can't simply make one lot of packages available, then after a period of=
 time
> make another lot available, as I can only inform the users that updates a=
re
> there - I cannot force them to make the upgrade. I can be sure that many =
of
> the users will not update when prompted. Any solution would need to be ab=
le
> to work now and into the future.
>
> Is there a way that I can stagger the updates to my machines? I notice th=
at
> apt will hold back a package if a dependency is not met. Is there a way t=
o
> set up my dependencies to solve this? alternatively, is there any other
> solution that can get around this problem?
>
> Thanks for any help that can be given.
>
> Cheers,
>
> Matthew Smith
>

[]'s
Herton.