1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from yum import YumBase
17 from optparse import OptionParser
18 from yum.plugins import TYPE_CORE, TYPE_INTERACTIVE
19 from gofer.decorators import *
20 from gofer.agent.plugin import Plugin
21 from logging import getLogger, Logger
22
23 log = getLogger(__name__)
24 plugin = Plugin.find(__name__)
25
26
27 -class Yum(YumBase):
28 """
29 Provides custom configured yum object.
30 """
31
33 """
34 @param importkeys: Allow the import of GPG keys.
35 @type importkeys: bool
36 """
37 parser = OptionParser()
38 parser.parse_args([])
39 self.__parser = parser
40 YumBase.__init__(self)
41 self.preconf.optparser = self.__parser
42 self.preconf.plugin_types = (TYPE_CORE, TYPE_INTERACTIVE)
43 self.conf.assumeyes = importkeys
44
46 """
47 Set command line arguments.
48 Support TYPE_INTERACTIVE plugins.
49 """
50 YumBase.doPluginSetup(self, *args, **kwargs)
51 p = self.__parser
52 options, args = p.parse_args([])
53 self.plugins.setCmdLine(options, args)
54
56 """
57 Support TYPE_INTERACTIVE plugins.
58 Commands ignored.
59 """
60 pass
61
63 """
64 Clean handlers leaked by yum.
65 """
66 for n,lg in Logger.manager.loggerDict.items():
67 if not n.startswith('yum.'):
68 continue
69 for h in lg.handlers:
70 lg.removeHandler(h)
71
73 """
74 This should be handled by __del__() but YumBase
75 objects never seem to completely go out of scope and
76 garbage collected.
77 """
78 YumBase.close(self)
79 self.closeRpmDB()
80 self.cleanLoggers()
81
87 """
88 Package management.
89 Returned I{Package} NEVRA+ objects:
90 - qname : qualified name
91 - repoid : repository id
92 - name : package name
93 - epoch : package epoch
94 - version : package version
95 - release : package release
96 - arch : package arch
97 """
98
99 @classmethod
100 - def summary(cls, tsInfo, states=('i','u')):
101 """
102 Get transaction summary.
103 @param tsInfo: A yum transaction.
104 @type tsInfo: YumTransaction
105 @param states: A list of yum transaction states.
106 @type states: tuple|list
107 @return: (resolved[],deps[])
108 @rtype: tuple
109 """
110 resolved = []
111 deps = []
112 for t in tsInfo:
113 if t.ts_state not in states:
114 continue
115 qname = str(t.po)
116 package = dict(
117 qname=qname,
118 repoid=t.repoid,
119 name=t.po.name,
120 version=t.po.ver,
121 release=t.po.rel,
122 arch=t.po.arch,
123 epoch=t.po.epoch)
124 if t.isDep:
125 deps.append(package)
126 else:
127 resolved.append(package)
128 return (resolved, deps)
129
130 @classmethod
132 """
133 Get transaction summary for installed packages.
134 @param tsInfo: A yum transaction.
135 @type tsInfo: YumTransaction
136 @return: (resolved[],deps[])
137 @rtype: tuple
138 """
139 return cls.summary(tsInfo)
140
141 @classmethod
143 """
144 Get transaction summary for erased packages.
145 @param tsInfo: A yum transaction.
146 @type tsInfo: YumTransaction
147 @return: (resolved[],deps[])
148 @rtype: tuple
149 """
150 return cls.summary(tsInfo, ('e',))
151
152 - def __init__(self, apply=True, importkeys=False):
153 """
154 @param apply: Apply changes (not dry-run).
155 @type apply: bool
156 @param importkeys: Allow the import of GPG keys.
157 @type importkeys: bool
158 """
159 self.apply = apply
160 self.importkeys = importkeys
161
162 @remote
163 @pam(user='root')
165 """
166 Install packages by name.
167 @param names: A list of package names.
168 @type names: [str,]
169 @return: Packages installed.
170 {resolved=[Package,],deps=[Package,]}
171 @rtype: dict
172 """
173 yb = Yum(self.importkeys)
174 try:
175 for info in names:
176 yb.install(pattern=info)
177 yb.resolveDeps()
178 resolved, deps = self.installed(yb.tsInfo)
179 if self.apply and resolved:
180 yb.processTransaction()
181 finally:
182 yb.close()
183 return dict(resolved=resolved, deps=deps)
184
185 @remote
186 @pam(user='root')
188 """
189 Uninstall (erase) packages by name.
190 @param names: A list of package names to be removed.
191 @type names: list
192 @return: Packages uninstalled (erased).
193 {resolved=[Package,],deps=[Package,]}
194 @rtype: dict
195 """
196 yb = Yum()
197 try:
198 for info in names:
199 yb.remove(pattern=info)
200 yb.resolveDeps()
201 resolved, deps = self.erased(yb.tsInfo)
202 if self.apply and resolved:
203 yb.processTransaction()
204 finally:
205 yb.close()
206 return dict(resolved=resolved, deps=deps)
207
208 @remote
209 @pam(user='root')
210 - def update(self, names=None):
211 """
212 Update installed packages.
213 When (names) is not specified, all packages are updated.
214 @param names: A list of package names.
215 @type names: [str,]
216 @return: Packages installed (updated).
217 {resolved=[Package,],deps=[Package,]}
218 @rtype: dict
219 """
220 yb = Yum(self.importkeys)
221 try:
222 if names:
223 for info in names:
224 yb.update(pattern=info)
225 else:
226 yb.update()
227 yb.resolveDeps()
228 resolved, deps = self.installed(yb.tsInfo)
229 if self.apply and resolved:
230 yb.processTransaction()
231 finally:
232 yb.close()
233 return dict(resolved=resolved, deps=deps)
234
237 """
238 PackageGroup management.
239 """
240
241 - def __init__(self, apply=True, importkeys=False):
242 """
243 @param apply: Apply changes (not dry-run).
244 @type apply: bool
245 @param importkeys: Allow the import of GPG keys.
246 @type importkeys: bool
247 """
248 self.apply = apply
249 self.importkeys = importkeys
250
251 @remote
252 @pam(user='root')
254 """
255 Install package groups by name.
256 @param names: A list of package group names.
257 @type names: list
258 @return: Packages installed.
259 {resolved=[Package,],deps=[Package,]}
260 @rtype: dict
261 """
262 yb = Yum(self.importkeys)
263 try:
264 for name in names:
265 yb.selectGroup(name)
266 yb.resolveDeps()
267 resolved, deps = Package.installed(yb.tsInfo)
268 if self.apply and resolved:
269 yb.processTransaction()
270 finally:
271 yb.close()
272 return dict(resolved=resolved, deps=deps)
273
274 @remote
275 @pam(user='root')
277 """
278 Uninstall package groups by name.
279 @param names: A list of package group names.
280 @type names: [str,]
281 @return: Packages uninstalled.
282 {resolved=[Package,],deps=[Package,]}
283 @rtype: dict
284 """
285 removed = {}
286 yb = Yum()
287 try:
288 for name in names:
289 yb.groupRemove(name)
290 yb.resolveDeps()
291 resolved, deps = Package.erased(yb.tsInfo)
292 if self.apply and resolved:
293 yb.processTransaction()
294 finally:
295 yb.close()
296 return dict(resolved=resolved, deps=deps)
297