Tags

redhat
employment
ripple
interfaces
ncurses
ruby
refs
filesystems
retro gaming
raspberry pi
sinatra
3d printing
nethack
gcc
compiler
fedora
virtfs
project
gaming
vim
grep
sed
aikido
philosophy
splix
android
lvm
storage
bitcoin
projects
sig315
miq
db
polisher
meditation
hopex
conferences
omega
simulator
bundler_ext
rubygems
book review
google code in
isitfedoraruby
svn
gsoc
design patters
jsonrpc
rjr
aeolus
ohiolinuxfest
rome
europe
travel
brno
gtk
python
puppet
conference
fudcon
snap
html5
tips
ssh
linux
hardware
libvirt
virtualization
engineering expo
cloud
rpm
yum
rake
redmine
plugins
screencasting
jruby
fosscon
pidgin
gnome-shell
distros
notacon
presentation
rails
deltacloud
apache
qmf
passenger
syrlug
hackerspace
music
massive attack
crypto
backups
vnc
xsd
rxsd
x3d
mercurial
ovirt
qpid
webdev
haikus
poetry
legaleese
jquery
selenium
testing
xpath
git
sshfs
svg
ldap
autotools
pygtk
xmlrpc
slackware

Dec 7 2007 yum

Deciphering the Yum API

My current side project (to be announced/released soon) involves using the Yum Python API. Unfortunately I have yet to find a good tutorial or guide, though there are many apps which use the Yum API such as yumex, so I figure I’d share some knowledge about my findings. Note that I am using Yum version 3.2.7 and everything presented here is derived from my studying of the code.

/usr/bin/yum simply calls out to /usr/share/yum/yummain.py which then instantiates classes deriving from YumBase. YumBase defined in the yum library /usr/lib/python2.5/site-packages/yum/, specifically init.py, is the main interface into the API and will provide alot of the high level functionality that you would want to access.

Perhaps one of the simpler actions is listing the packages installed on a system. This is accomplished by accessing the rpmdb member of a YumBase instance, representing your local rpm database, which if iterated over will return the list of installed packages. The rpm interface is invoked to generate the package list from which instances of YumInstalledPackage (defined in packages.py) are created. The base class, YumHeaderPackage, contains all the fields which you would want to access, including name, arch, epoch, version, release, summary, description, pkgid, packageSize, hdr[“buildtime”]

To put it shortly, to access all of your installed packages via yum you would:

import yum
class Test(yum.YumBase):
    def init(self):
        yum.YumBase.init(self)
        i=0
        for pkg in self.rpmdb:
            print pkg.name + " " + pkg.description
            i += 1
        print str(i) + " packages"

Test()

RPMDBPackageSack implements several useful functions including “installed” which takes a package and tells you if it is installed, “searchAll” which searches for packages based on name, and “getProvides” which searches based on files they provide. The drawback of these routines though is that only the local rpm database is searched. To search yum’s repositories you must use YumBase’s searchGenerator and searchPackageProvides functions. searchGenerator takes a list of fields to search and a list of criteria to match. For its search functionality the yum command uses the criteria [‘name’, ‘summary’, ‘description’, ‘packager’, ‘group’, ‘url’] (or course you can simply just include “name” to a name based search). To search for the dovecot and k3b packages you would:

import yum
class Test(yum.YumBase):
    def __init__(self):
        yum.YumBase.__init__(self)
        searchlist = ['name', 'summary', 'description', 'packager', 'group', 'url']
        args = ["dovecot", "k3b"]
        matching = self.searchGenerator(searchlist, args)
        for (po, matched_value) in matching:
            print po.name + " " + po.description

Test()

The problem with searching is it will match any package with your search criteria in it. So for example, if you search for “k3b”, you will get the k3b-devel package in addition to k3b. To retrieve an exact match you need to invoke the ‘list’ functionality of the yum api. Unlike search, you instruct yum to list all packages and then apply filters to the package lists to isolate what you are looking for. So to list the k3b package you would:

import yum
class Test(yum.yumBase):
     def init(self):
        yum.YumBase.init(self)
        pl = self.doPackageLists('all') # can specify installed, updatable, available, and more
        exactmatch, matched, unmatched = yum.packages.parsePackages(pl.installed, ["k3b"])
        exactmatch = yum.misc.unique(exactmatch)
        # loop is used because multiple matches will be returned
        # if more than one package is found with the name in the
        # repo (different versions or arches for example)
        for pkg in exactmatch:
            print po.name

Test()

Installing, removing, deleting packages is slightly more complicated as you need to mark the package operations before building a transaction, and finally processing it. To install dovecot and remove k3b you would:

import yum
class Test(yum.YumBase):
    def __init__(self):
        yum.YumBase.__init__(self)
        searchlist = ['name']
        args = ["dovecot", "k3b"]
        matching = self.searchGenerator(searchlist, args)
        for (po, matched_value) in matching:
           if po.name == "dovecot":
              self.install(po)
           elif po.name == "k3b":
              self.delete(po)
        # build and process the batch transaction
        self.buildTransaction()
        self.processTransaction()
Test()

Of course there is a lot more to the Yum API than summarized here. Unfortunately, there isn’t much way of documentation on it on the net (remember while Yum makes it simple to access its API with invoking the command, it is primarily a program as opposed to a library). Probably your best bet is going to the Yumex online API which partially covers the yum api (most importantly, the yum.YumBase class, the main interface into Yum). Of course all the yum library and application code is out there, along with the code behind other tools which use yum, including yumex, pirut, and pup. Good luck!