Product SiteDocumentation Site

Upgrading A Package

Listing 17-7 shows a simple Python script to upgrade or install a package.
Listing 17-7: rpmupgrade.py
#!/usr/bin/python
# Upgrades packages passed on the command line.
# Usage:
# python rpmupgrade.py rpm_file1.rpm rpm_file2.rpm ...
#

import os
import sys

import rpm

# Global file descriptor for the callback.
rpmtsCallback_fd = None

def runCallback(reason, amount, total, key, client_data):
    global rpmtsCallback_fd
    if reason == rpm.RPMCALLBACK_INST_OPEN_FILE:
        print "Opening file. ", reason, amount, total, key, client_data
        rpmtsCallback_fd = os.open(key, os.O_RDONLY)
        return rpmtsCallback_fd
    elif reason == rpm.RPMCALLBACK_INST_START:
        print "Closing file. ", reason, amount, total, key, client_data
        os.close(rpmtsCallback_fd)

def checkCallback(ts, TagN, N, EVR, Flags):
    if TagN == rpm.RPMTAG_REQUIRENAME:
        prev = ""
    Nh = None

    if N[0] == '/':
        dbitag = 'basenames'
    else:
        dbitag = 'providename'

    # What do you need to do.
    if EVR:
        print "Must find package [", N, "-", EVR, "]"
    else:
        print "Must find file [", N, "]"

    if resolved:
        # ts.addIntall(h, h, 'i')
        return -1

    return 1

def readRpmHeader(ts, filename):
    """ Read an rpm header. """
    fd = os.open(filename, os.O_RDONLY)
    try:
        h = ts.hdrFromFdno(fd)
    finally:
        os.close(fd)
    return h

ts = rpm.TransactionSet()

# Set to not verify DSA signatures.
ts.setVSFlags(-1)

for filename in sys.argv[1:]:
    h = readRpmHeader(ts, filename)
    print "Upgrading %s-%s-%s" % (h['name'], h['version'], h['release'])
    ts.addInstall(h, filename, 'u')

unresolved_dependencies = ts.check(checkCallback)

if not unresolved_dependencies:
    ts.order()

    print "This upgrade will install:"
    for te in ts:
        print "%s-%s-%s" % (te.N(), te.V(), te.R())

    print "Running transaction (final step)..."
    ts.run(runCallback, 1)
else:
    print "Error: Unresolved dependencies, transaction failed."
    print unresolved_dependencies
This script expects the name of an RPM package file on the command line, and attempts to upgrade the package. (This will also install new packages.)
When you run the rpmupgrade.py script, you should see output like the following:
# rpm -q jikes
jikes-1.17-1

# python rpmupgrade.py jikes-1.18-1.i386.rpm
Upgrading jikes-1.18-1
This upgrade will install:
jikes-1.18-1
jikes-1.17-1
Running transaction (final step)...
Opening file. 4 0 0 jikes-1.18-1.i386.rpm 1
Closing file. 2 0 2854204 jikes-1.18-1.i386.rpm 1

# rpm -q jikes
jikes-1.18-1
This example shows that the package was upgraded after running the rpmupgrade.py script. Note that with an upgrade, the original package, jikes-1.17-1 in this case, is also added to the transaction set. With an install, this is not the case. That’s because the original package is removed as part of the transaction.
If you run this script as a non-root user, you will likely see an error like the following:
$ python rpmupgrade.py jikes-1.18-1.i386.rpm
Upgrading jikes-1.18-1
This upgrade will install:
jikes-1.18-1
jikes-1.17-1
Running transaction (final step)...
error: cannot get exclusive lock on /var/lib/rpm/Packages
error: cannot open Packages index using db3 - Operation not permitted (1)
error: cannot open Packages database in /var/lib/rpm
If a package has a dependency on a file such as a shared library, you will see output like the following:
# python rpmupgrade.py jikes-1.17-glibc2.2-1.i386.rpm jpilot-0_97-1_i386.rpm
Upgrading jikes-1.17-1
Upgrading jpilot-0.97-1
Must find file [ libpisock.so.3 ]
Error: Unresolved dependencies, transaction failed.
(('jpilot', '0.97', '1'), ('libpisock.so.3', None), 0, None, 0)
If a package has a dependency on another package, you will see output like the following:
# python rpmupgrade.py eruby-devel-0.9.8-2.i386.rpm
Upgrading eruby-devel-0.9.8-2
Must find package [ eruby-libs - 0.9.8 ]
Error: Unresolved dependencies, transaction failed.
(('eruby-devel', '0.9.8', '2'), ('eruby-libs', '0.9.8'), 8, None, 0)