2 # yum.py : yum utilities
4 # Copyright 2007, Red Hat Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Library General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 import pykickstart
.parser
28 from imgcreate
.errors
import *
30 class TextProgress(object):
31 logger
= logging
.getLogger()
32 def emit(self
, lvl
, msg
):
33 '''play nice with the logging module'''
34 for hdlr
in self
.logger
.handlers
:
35 if lvl
>= self
.logger
.level
:
36 hdlr
.stream
.write(msg
)
39 def start(self
, filename
=None, url
=None, *args
, **kwargs
):
40 text
= kwargs
.get("text", "")
41 self
.emit(logging
.INFO
, "Retrieving %s " % (url
or text
))
43 def update(self
, *args
):
46 self
.emit(logging
.INFO
, "...OK\n")
48 class LiveCDYum(yum
.YumBase
):
49 def __init__(self
, releasever
=None, useplugins
=False):
51 releasever = optional value to use in replacing $releasever in repos
53 yum
.YumBase
.__init
__(self
)
54 self
.releasever
= releasever
55 self
.useplugins
= useplugins
57 def doFileLogSetup(self
, uid
, logfile
):
58 # don't do the file log for the livecd as it can lead to open fds
59 # being left and an inability to clean up after ourself
64 os
.unlink(self
.conf
.installroot
+ "/yum.conf")
67 yum
.YumBase
.close(self
)
72 def _writeConf(self
, confpath
, installroot
):
74 conf
+= "installroot=%s\n" % installroot
75 conf
+= "cachedir=/var/cache/yum\n"
81 conf
+= "failovermethod=priority\n"
82 conf
+= "keepcache=1\n"
83 conf
+= "tsflags=nocontexts\n"
85 f
= file(confpath
, "w+")
89 os
.chmod(confpath
, 0644)
91 def _cleanupRpmdbLocks(self
, installroot
):
92 # cleans up temporary files left by bdb so that differing
93 # versions of rpm don't cause problems
94 for f
in glob
.glob(installroot
+ "/var/lib/rpm/__db*"):
97 def setup(self
, confpath
, installroot
, cacheonly
=False):
98 self
._writeConf
(confpath
, installroot
)
99 self
._cleanupRpmdbLocks
(installroot
)
100 self
.doConfigSetup(fn
= confpath
, root
= installroot
)
110 def selectPackage(self
, pkg
):
111 """Select a given package. Can be specified with name.arch or name*"""
112 return self
.install(pattern
= pkg
)
114 def deselectPackage(self
, pkg
):
115 """Deselect package. Can be specified as name.arch or name*"""
116 sp
= pkg
.rsplit(".", 2)
119 txmbrs
= self
.tsInfo
.matchNaevr(name
=sp
[0], arch
=sp
[1])
122 exact
, match
, unmatch
= yum
.packages
.parsePackages(self
.pkgSack
.returnPackages(), [pkg
], casematch
=1)
123 for p
in exact
+ match
:
128 self
.tsInfo
.remove(x
.pkgtup
)
129 # we also need to remove from the conditionals
130 # dict so that things don't get pulled back in as a result
131 # of them. yes, this is ugly. conditionals should die.
132 for req
, pkgs
in self
.tsInfo
.conditionals
.iteritems():
135 self
.tsInfo
.conditionals
[req
] = pkgs
137 logging
.warn("No such package %s to remove" %(pkg
,))
139 def selectGroup(self
, grp
, include
= pykickstart
.parser
.GROUP_DEFAULT
):
140 # default to getting mandatory and default packages from a group
141 # unless we have specific options from kickstart
142 package_types
= ['mandatory', 'default']
143 if include
== pykickstart
.parser
.GROUP_REQUIRED
:
144 package_types
.remove('default')
145 elif include
== pykickstart
.parser
.GROUP_ALL
:
146 package_types
.append('optional')
147 yum
.YumBase
.selectGroup(self
, grp
, group_package_types
=package_types
)
149 def addRepository(self
, name
, url
= None, mirrorlist
= None):
150 def _varSubstitute(option
):
151 # takes a variable and substitutes like yum configs do
152 option
= option
.replace("$basearch", rpmUtils
.arch
.getBaseArch())
153 option
= option
.replace("$arch", rpmUtils
.arch
.getCanonArch())
154 # If the url includes $releasever substitute user's value or
155 # current system's version.
156 if option
.find("$releasever") > -1:
158 option
= option
.replace("$releasever", self
.releasever
)
161 option
= option
.replace("$releasever", yum
.config
._getsysver
("/", "redhat-release"))
162 except yum
.Errors
.YumBaseError
:
163 raise CreatorError("$releasever in repo url, but no releasever set")
166 repo
= yum
.yumRepo
.YumRepository(name
)
168 repo
.baseurl
.append(_varSubstitute(url
))
170 repo
.mirrorlist
= _varSubstitute(mirrorlist
)
171 conf
= yum
.config
.RepoConf()
172 for k
, v
in conf
.iteritems():
173 if v
or not hasattr(repo
, k
):
174 repo
.setAttribute(k
, v
)
175 repo
.basecachedir
= self
.conf
.cachedir
176 repo
.base_persistdir
= self
.conf
.cachedir
177 repo
.failovermethod
= "priority"
178 repo
.metadata_expire
= 0
179 repo
.mirrorlist_expire
= 0
180 repo
.timestamp_check
= 0
181 # disable gpg check???
184 repo
.setup(self
.conf
.cache
)
185 repo
.setCallback(TextProgress())
189 def installHasFile(self
, file):
190 provides_pkg
= self
.whatProvides(file, None, None)
191 dlpkgs
= map(lambda x
: x
.po
, filter(lambda txmbr
: txmbr
.ts_state
in ("i", "u"), self
.tsInfo
.getMembers()))
193 for q
in provides_pkg
:
199 def runInstall(self
):
200 os
.environ
["HOME"] = "/"
202 (res
, resmsg
) = self
.buildTransaction()
203 except yum
.Errors
.RepoError
, e
:
204 raise CreatorError("Unable to download from repo : %s" %(e
,))
205 # Empty transactions are generally fine, we might be rebuilding an
206 # existing image with no packages added
207 if resmsg
and resmsg
[0].endswith(" - empty transaction"):
210 raise CreatorError("Failed to build transaction : %s" % str.join("\n", resmsg
))
212 dlpkgs
= map(lambda x
: x
.po
, filter(lambda txmbr
: txmbr
.ts_state
in ("i", "u"), self
.tsInfo
.getMembers()))
213 self
.downloadPkgs(dlpkgs
)
217 self
.populateTs(keepold
=0)
218 deps
= self
.ts
.check()
220 raise CreatorError("Dependency check failed : %s" % "\n".join([str(d
) for d
in deps
]))
223 raise CreatorError("ordering packages for installation failedr. rc = %s" % rc
)
225 # FIXME: callback should be refactored a little in yum
226 sys
.path
.append('/usr/share/yum-cli')
228 yum
.misc
.setup_locale()
230 cb
= callback
.RPMInstallCallback()
231 cb
.tsInfo
= self
.tsInfo
233 ret
= self
.runTransaction(cb
)
235 self
._cleanupRpmdbLocks
(self
.conf
.installroot
)