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 def start(self
, filename
, url
, *args
, **kwargs
):
32 sys
.stdout
.write("Retrieving %s " % (url
,))
34 def update(self
, *args
):
37 sys
.stdout
.write("...OK\n")
39 class LiveCDYum(yum
.YumBase
):
40 def __init__(self
, releasever
=None):
42 releasever = optional value to use in replacing $releasever in repos
44 yum
.YumBase
.__init
__(self
)
45 self
.releasever
= releasever
47 def doFileLogSetup(self
, uid
, logfile
):
48 # don't do the file log for the livecd as it can lead to open fds
49 # being left and an inability to clean up after ourself
54 os
.unlink(self
.conf
.installroot
+ "/yum.conf")
57 yum
.YumBase
.close(self
)
62 def _writeConf(self
, confpath
, installroot
):
64 conf
+= "installroot=%s\n" % installroot
65 conf
+= "cachedir=/var/cache/yum\n"
68 conf
+= "failovermethod=priority\n"
69 conf
+= "keepcache=1\n"
71 f
= file(confpath
, "w+")
75 os
.chmod(confpath
, 0644)
77 def _cleanupRpmdbLocks(self
, installroot
):
78 # cleans up temporary files left by bdb so that differing
79 # versions of rpm don't cause problems
80 for f
in glob
.glob(installroot
+ "/var/lib/rpm/__db*"):
83 def setup(self
, confpath
, installroot
):
84 self
._writeConf
(confpath
, installroot
)
85 self
._cleanupRpmdbLocks
(installroot
)
86 self
.doConfigSetup(fn
= confpath
, root
= installroot
)
93 def selectPackage(self
, pkg
):
94 """Select a given package. Can be specified with name.arch or name*"""
95 return self
.install(pattern
= pkg
)
97 def deselectPackage(self
, pkg
):
98 """Deselect package. Can be specified as name.arch or name*"""
99 sp
= pkg
.rsplit(".", 2)
102 txmbrs
= self
.tsInfo
.matchNaevr(name
=sp
[0], arch
=sp
[1])
105 exact
, match
, unmatch
= yum
.packages
.parsePackages(self
.pkgSack
.returnPackages(), [pkg
], casematch
=1)
106 for p
in exact
+ match
:
111 self
.tsInfo
.remove(x
.pkgtup
)
112 # we also need to remove from the conditionals
113 # dict so that things don't get pulled back in as a result
114 # of them. yes, this is ugly. conditionals should die.
115 for req
, pkgs
in self
.tsInfo
.conditionals
.iteritems():
118 self
.tsInfo
.conditionals
[req
] = pkgs
120 logging
.warn("No such package %s to remove" %(pkg
,))
122 def selectGroup(self
, grp
, include
= pykickstart
.parser
.GROUP_DEFAULT
):
123 # default to getting mandatory and default packages from a group
124 # unless we have specific options from kickstart
125 package_types
= ['mandatory', 'default']
126 if include
== pykickstart
.parser
.GROUP_REQUIRED
:
127 package_types
.remove('default')
128 elif include
== pykickstart
.parser
.GROUP_ALL
:
129 package_types
.append('optional')
130 yum
.YumBase
.selectGroup(self
, grp
, group_package_types
=package_types
)
132 def addRepository(self
, name
, url
= None, mirrorlist
= None):
133 def _varSubstitute(option
):
134 # takes a variable and substitutes like yum configs do
135 option
= option
.replace("$basearch", rpmUtils
.arch
.getBaseArch())
136 option
= option
.replace("$arch", rpmUtils
.arch
.getCanonArch())
137 # If the url includes $releasever substitute user's value or
138 # current system's version.
139 if option
.find("$releasever") > -1:
141 option
= option
.replace("$releasever", self
.releasever
)
144 option
= option
.replace("$releasever", yum
.config
._getsysver
("/", "redhat-release"))
145 except yum
.Errors
.YumBaseError
:
146 raise CreatorError("$releasever in repo url, but no releasever set")
149 repo
= yum
.yumRepo
.YumRepository(name
)
151 repo
.baseurl
.append(_varSubstitute(url
))
153 repo
.mirrorlist
= _varSubstitute(mirrorlist
)
154 conf
= yum
.config
.RepoConf()
155 for k
, v
in conf
.iteritems():
156 if v
or not hasattr(repo
, k
):
157 repo
.setAttribute(k
, v
)
158 repo
.basecachedir
= self
.conf
.cachedir
159 repo
.failovermethod
= "priority"
160 repo
.metadata_expire
= 0
161 repo
.mirrorlist_expire
= 0
162 repo
.timestamp_check
= 0
163 # disable gpg check???
167 repo
.setCallback(TextProgress())
171 def installHasFile(self
, file):
172 provides_pkg
= self
.whatProvides(file, None, None)
173 dlpkgs
= map(lambda x
: x
.po
, filter(lambda txmbr
: txmbr
.ts_state
in ("i", "u"), self
.tsInfo
.getMembers()))
175 for q
in provides_pkg
:
181 def runInstall(self
):
182 os
.environ
["HOME"] = "/"
184 (res
, resmsg
) = self
.buildTransaction()
185 except yum
.Errors
.RepoError
, e
:
186 raise CreatorError("Unable to download from repo : %s" %(e
,))
187 # Empty transactions are generally fine, we might be rebuilding an
188 # existing image with no packages added
189 if resmsg
and resmsg
[0].endswith(" - empty transaction"):
192 raise CreatorError("Failed to build transaction : %s" % str.join("\n", resmsg
))
194 dlpkgs
= map(lambda x
: x
.po
, filter(lambda txmbr
: txmbr
.ts_state
in ("i", "u"), self
.tsInfo
.getMembers()))
195 self
.downloadPkgs(dlpkgs
)
199 self
.populateTs(keepold
=0)
200 deps
= self
.ts
.check()
202 raise CreatorError("Dependency check failed!")
205 raise CreatorError("ordering packages for installation failed!")
207 # FIXME: callback should be refactored a little in yum
208 sys
.path
.append('/usr/share/yum-cli')
210 yum
.misc
.setup_locale()
212 cb
= callback
.RPMInstallCallback()
213 cb
.tsInfo
= self
.tsInfo
215 ret
= self
.runTransaction(cb
)
217 self
._cleanupRpmdbLocks
(self
.conf
.installroot
)