[Yum] distribution variable works...

Robert G. Brown rgb at phy.duke.edu
Tue Sep 28 16:21:56 UTC 2004


On Tue, 28 Sep 2004, Robert G. Brown wrote:

The following (2.0.7 derived) config.py actually works and does the
substitutions and everything.  It isn't efficient - both variables could
be set with one set of rpm.TransactionSet() calls, but I don't know how
to return two variables from one subroutine fragment in python.
Probably very simply.

I also patched in the required distribution_reg stuff that makes it
actually work, and tested it.  It actually works.

If you decide to implement this, you'll probably need/want to recombine
the two hdr[] assignments into the one transaction set call, and decide
whether or not you want to chop off the -release from the hdr['name']
return.  I would -- it is prettier -- but honestly if distribution were
set to redhat-release, centos-release etc. it would work just as well
for automating $distribution/$releasever/$basearch paths.  

Either way you'll likely want to insert a sanity check here.  I'd
recommend using the 'unknown' fallback/default instead of the 'Null'
default for $distribution (as I attempted below) but whatever.

Just having distribution variable will create a strong incentive to
structure repositories this way.

   rgb

-- 
Robert G. Brown	                       http://www.phy.duke.edu/~rgb/
Duke University Dept. of Physics, Box 90305
Durham, N.C. 27708-0305
Phone: 1-919-660-2567  Fax: 919-660-2525     email:rgb at phy.duke.edu


#!/usr/bin/python -t
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2002 Duke University 

import ConfigParser
import sys
import os
import os.path
import urlparse
import string
import urllib
import rpm
import re
import failover
import archwork
import rpmUtils
import progress_meter

from i18n import _


class yumconf:

    def __init__(self, configfile = '/etc/yum.conf'):
        self.cfg = ConfigParser.ConfigParser()
        (s,b,p,q,f,o) = urlparse.urlparse(configfile)
        if s in ('http', 'ftp','file'):
            configfh = urllib.urlopen(configfile)
            try:
                self.cfg.readfp(configfh)
            except ConfigParser.MissingSectionHeaderError, e:
                print _('Error accessing URL: %s') % configfile
                sys.exit(1)
        else:
            if os.access(configfile, os.R_OK):
                self.cfg.read(configfile)
            else:
                print _('Error accessing File: %s') % configfile
                sys.exit(1)
        self.servers = []
        self.servername = {}
        self.serverurl = {}
        self.serverpkgdir = {}
        self.serverhdrdir = {}
        self.servercache = {}
        self.servergpgcheck= {}
        self.serverexclude= {}
        self.failoverclass = {}
        self.groupsenable = {}
        self.excludes = []
        
        #defaults
        self.cachedir = '/var/cache/yum'
        self.debuglevel = 2
        self.logfile = '/var/log/yum.log'
        self.pkgpolicy = 'newest'
        self.assumeyes = 0
        self.errorlevel = 2
        self.cache = 0
        self.uid = 0
        self.yumversion = 'unversioned'
        self.commands = None
        self.exactarch = 0
        self.overwrite_groups = 0
        self.groups_enabled = 0
        self.diskspacecheck = 1
        self.tolerant = 0
        self.yumvar = self._getEnvVar()
        self.distroverpkg = 'redhat-release'
        self.yumvar['basearch'] = archwork.getArch()
        self.yumvar['arch'] = os.uname()[4]
        # this is ugly and dirty like Zebra - but I'd like for a lot of users
        # of fedora to hush about the header download until I get the
        # new metadata work done.
        self.hdlist = '/usr/share/comps/%s/hdlist' % self.yumvar['basearch']
        self.hdlist2 = '/usr/share/comps/%s/hdlist2' % self.yumvar['basearch']
        self.usecomps = 1
        self.cachedb = '/usr/lib/rpmdb/%s-redhat-linux/redhat/' % self.yumvar['basearch']
        self.usecachedb = 1
        self.downloadonly = 0
        self.bandwidth = None
        self.throttle = None
        self.retries = 6
        self.keepalive = 1
        self.modifybootloader = 1
        self.progress_obj = progress_meter.text_progress_meter(fo=sys.stdout)
        self.installroot = '/'
        self.installonlypkgs = ['kernel', 'kernel-bigmem', 'kernel-enterprise',
                           'kernel-smp', 'kernel-debug', 'kernel-unsupported', 
                           'kernel-source', 'kernel-modules-unsupported']
        self.kernelpkgnames = ['kernel','kernel-smp','kernel-enterprise',
                           'kernel-bigmem','kernel-BOOT']
      
        if self._getoption('main','cachedir') != None:
            self.cachedir = self._getoption('main','cachedir')
        if self._getoption('main','debuglevel') != None:
            self.debuglevel = self._getoption('main','debuglevel')
        if self._getoption('main','logfile') != None:
            self.logfile = self._getoption('main','logfile')
        if self._getoption('main','pkgpolicy') != None:
            self.pkgpolicy = self._getoption('main','pkgpolicy')
        if self._getoption('main','assumeyes') != None:
            self.assumeyes = self.cfg.getboolean('main', 'assumeyes')
        if self._getoption('main','errorlevel') != None:
            self.errorlevel = self._getoption('main', 'errorlevel')
        if self._getoption('main','exactarch') != None:
            self.exactarch = self.cfg.getboolean('main', 'exactarch')
        if self._getoption('main','overwrite_groups') != None:
            self.overwrite_groups = self.cfg.getboolean('main', 'overwrite_groups')
        if self._getoption('main','diskspacecheck') != None:
            self.diskspacecheck = self.cfg.getboolean('main', 'diskspacecheck')
        if self._getoption('main','tolerant') != None:
            self.tolerant = self.cfg.getboolean('main', 'tolerant')
        if self._getoption('main', 'distroverpkg') != None:
            self.distroverpkg = self._getoption('main','distroverpkg')
        if self._getoption('main', 'bandwidth') != None:
            self.bandwidth = self._getoption('main','bandwidth')
        if self._getoption('main', 'throttle') != None:
            self.throttle = self._getoption('main','throttle')
        if self._getoption('main', 'keepalive') != None:
            self.keepalive = self.cfg.getboolean('main','keepalive')
        if self._getoption('main', 'retries') != None:
            self.retries = self.cfg.getint('main','retries')
        if self._getoption('main', 'installroot') != None:
            self.installroot = self._getoption('main','installroot')
        if self._getoption('main', 'hdlist') != None:
            self.hdlist = self._getoption('main', 'hdlist')
        if self._getoption('main', 'hdlist2') != None:
            self.hdlist2 = self._getoption('main', 'hdlist2')
        if self._getoption('main','usecomps') != None:
            self.usecomps = self.cfg.getboolean('main', 'usecomps')
        if self._getoption('main','download-only') != None:
            self.downloadonly = self.cfg.getboolean('main', 'download-only')
        if self._getoption('main','bootloader') != None:
            self.modifybootloader = self.cfg.getboolean('main', 'bootloader')
        if self._getoption('main', 'cachedb') != None:
            self.cachedb = self._getoption('main', 'cachedb')
        if self._getoption('main', 'usecachedb') != None:
            self.usecachedb = self.cfg.getboolean('main', 'usecachedb')
            
            
        # figure out what the releasever really is from the distroverpkg
        self.yumvar['distribution'] = self._getsysdist()
        self.yumvar['releasever'] = self._getsysver()
        
        if self._getoption('main','commands') != None:
            self.commands = self._getoption('main', 'commands')
            self.commands = self._doreplace(self.commands)
            self.commands = self.parseList(self.commands)

        if self._getoption('main','installonlypkgs') != None:
            self.installonlypkgs = self._getoption('main', 'installonlypkgs')
            self.installonlypkgs = self._doreplace(self.installonlypkgs)
            self.installonlypkgs = self.parseList(self.installonlypkgs)

        if self._getoption('main','kernelpkgnames') != None:
            self.kernelpkgnames = self._getoption('main', 'kernelpkgnames')
            self.kernelpkgnames = self._doreplace(self.kernelpkgnames)
            self.kernelpkgnames = self.parseList(self.kernelpkgnames)

        # get the global exclude lists.
        if self._getoption('main','exclude') != None:
            self.excludes = self._getoption('main','exclude')
            self.excludes = self._doreplace(self.excludes)
            self.excludes = self.parseList(self.excludes)
            

        if len(self.cfg.sections()) > 1:
            for section in self.cfg.sections(): # loop through the list of sections
                if section != 'main': # must be a serverid
                    if self._getoption(section, 'baseurl') != None:
                        name = self._getoption(section, 'name')
                        urls = self._getoption(section, 'baseurl')
                        urls = self._doreplace(urls)
                        urls = self.parseList(urls)
                    else:
                        name = None
                        urls = []
                        
                    if name != None and len(urls) > 0 and urls[0] != None:
                        self.servers.append(section)
                        name = self._doreplace(name)
                        self.servername[section] = name
                        self.serverurl[section] = urls
                        
                        failmeth = self._getoption(section,'failovermethod')
                        if failmeth == 'roundrobin':
                            failclass = failover.roundRobin(self, section)
                        elif failmeth == 'priority':
                            failclass = failover.priority(self, section)
                        else:
                            failclass = failover.roundRobin(self, section)
                        self.failoverclass[section] = failclass
                        
                        if self._getoption(section,'gpgcheck') != None:
                            self.servergpgcheck[section]=self.cfg.getboolean(section,'gpgcheck')
                        else:
                            self.servergpgcheck[section]=0
                        if self._getoption(section, 'exclude') != None:
                            srvexcludelist = self._getoption(section, 'exclude')
                            srvexcludelist = self._doreplace(srvexcludelist)
                            srvexcludelist = self.parseList(srvexcludelist)
                        else:
                            srvexcludelist = []
                        self.serverexclude[section] = srvexcludelist
                        
                        for url in self.serverurl[section]:
                            (s,b,p,q,f,o) = urlparse.urlparse(url)
                            # currently only allowing http and ftp servers 
                            if s not in ['http', 'ftp', 'file', 'https']:
                                print _('using ftp, http[s], or file for servers, Aborting - %s') % (url)
                                sys.exit(1)
                        
                        enablegroups=1
                        if self._getoption(section, 'enablegroups') != None:
                            enablegroups=self.cfg.getboolean(section, 'enablegroups')
                        self.groupsenable[section] = enablegroups
                        
                        cache = os.path.join(self.cachedir,section)
                        pkgdir = os.path.join(cache, 'packages')
                        hdrdir = os.path.join(cache, 'headers')
                        self.servercache[section] = cache
                        self.serverpkgdir[section] = pkgdir
                        self.serverhdrdir[section] = hdrdir
                    else:
                        print _('Error: Cannot find baseurl or name for server \'%s\'. Skipping') %(section)    
        else:
            print _('Insufficient server config - no servers found. Aborting.')
            sys.exit(1)

    def _getoption(self, section, option):
        try:
            return self.cfg.get(section, option)
        except ConfigParser.NoSectionError, e:
            print _('Failed to find section: %s') % section
        except ConfigParser.NoOptionError, e:
            return None
            
    def parseList(self, value):
        listvalue = []
        # we need to allow for the '\n[whitespace]' continuation - easier
        # to sub the \n with a space and then read the lines
        slashnrepl = re.compile('\n')
        commarepl = re.compile(',')
        (value, count) = slashnrepl.subn(' ', value)
        (value, count) = commarepl.subn(' ', value)
        listvalue = value.split()
        return listvalue

    def remoteGroups(self, serverid):
        return os.path.join(self.baseURL(serverid), 'yumgroups.xml')
    
    def localGroups(self, serverid):
        return os.path.join(self.servercache[serverid], 'yumgroups.xml')
        
    def baseURL(self, serverid):
        return self.get_failClass(serverid).get_serverurl()
        
    def server_failed(self, serverid):
        self.failoverclass[serverid].server_failed()
    
    def get_failClass(self, serverid):
        return self.failoverclass[serverid]
        
    def remoteHeader(self, serverid):
        return os.path.join(self.baseURL(serverid), 'headers/header.info')
        
    def localHeader(self, serverid):
        return os.path.join(self.servercache[serverid], 'header.info')

    def _getsysdist(self):
        ts = rpm.TransactionSet()
        ts.setVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS))
        idx = ts.dbMatch('provides', self.distroverpkg)
        # we're going to take the first one - if there is more than one of these
        # then the user needs a beating
        if idx.count() == 0:
            distribution = 'unknown'
        else:
            hdr = idx.next()
            distribution = hdr['name']
            del hdr
        del idx
        del ts
        return distribution
    
    def _getsysver(self):
        ts = rpm.TransactionSet()
        ts.setVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS))
        idx = ts.dbMatch('provides', self.distroverpkg)
        # we're going to take the first one - if there is more than one of these
        # then the user needs a beating
        if idx.count() == 0:
            releasever = 'Null'
        else:
            hdr = idx.next()
            releasever = hdr['version']
            del hdr
        del idx
        del ts
        return releasever
    
    def _getEnvVar(self):
        yumvar = {}
        yumvar[0] = os.environ.get('YUM0','$YUM0')
        yumvar[1] = os.environ.get('YUM1','$YUM1')
        yumvar[2] = os.environ.get('YUM2','$YUM2')
        yumvar[3] = os.environ.get('YUM3','$YUM3')
        yumvar[4] = os.environ.get('YUM4','$YUM4')
        yumvar[5] = os.environ.get('YUM5','$YUM5')
        yumvar[6] = os.environ.get('YUM6','$YUM6')
        yumvar[7] = os.environ.get('YUM7','$YUM7')
        yumvar[8] = os.environ.get('YUM8','$YUM8')
        yumvar[9] = os.environ.get('YUM9','$YUM9')
        
        return yumvar
        
    def _doreplace(self, string):
        """ do the replacement of yumvar, release, arch and basearch on any 
            string passed to it"""
        if string is None:
            return string
        basearch_reg = re.compile('\$basearch')
        arch_reg = re.compile('\$arch')
        releasever_reg = re.compile('\$releasever')
        distribution_reg = re.compile('\$distribution')
        yum0_reg = re.compile('\$YUM0')
        yum1_reg = re.compile('\$YUM1')
        yum2_reg = re.compile('\$YUM2')
        yum3_reg = re.compile('\$YUM3')
        yum4_reg = re.compile('\$YUM4')
        yum5_reg = re.compile('\$YUM5')
        yum6_reg = re.compile('\$YUM6')
        yum7_reg = re.compile('\$YUM7')
        yum8_reg = re.compile('\$YUM8')
        yum9_reg = re.compile('\$YUM9')
        
        (string, count) = basearch_reg.subn(self.yumvar['basearch'], string)
        (string, count) = arch_reg.subn(self.yumvar['arch'], string)
        (string, count) = releasever_reg.subn(self.yumvar['releasever'], string)
        (string, count) = distribution_reg.subn(self.yumvar['distribution'], string)
        (string, count) = yum0_reg.subn(self.yumvar[0], string)
        (string, count) = yum1_reg.subn(self.yumvar[1], string)
        (string, count) = yum2_reg.subn(self.yumvar[2], string)
        (string, count) = yum3_reg.subn(self.yumvar[3], string)
        (string, count) = yum4_reg.subn(self.yumvar[4], string)
        (string, count) = yum5_reg.subn(self.yumvar[5], string)
        (string, count) = yum6_reg.subn(self.yumvar[6], string)
        (string, count) = yum7_reg.subn(self.yumvar[7], string)
        (string, count) = yum8_reg.subn(self.yumvar[8], string)
        (string, count) = yum9_reg.subn(self.yumvar[9], string)
        
        return string




More information about the Yum mailing list