source: yum/vendor/yum-3.2.27/utils.py@ 2

Last change on this file since 2 was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1#!/usr/bin/python -t
2# This program is free software; you can redistribute it and/or modify
3# it under the terms of the GNU General Public License as published by
4# the Free Software Foundation; either version 2 of the License, or
5# (at your option) any later version.
6#
7# This program is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10# GNU Library General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program; if not, write to the Free Software
14# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15
16import sys
17import time
18import exceptions
19
20import yum
21from cli import *
22from yum import Errors
23from yum import _
24from yum import logginglevels
25from optparse import OptionGroup
26
27import yum.plugins as plugins
28from urlgrabber.progress import format_number
29
30def suppress_keyboard_interrupt_message():
31 old_excepthook = sys.excepthook
32
33 def new_hook(type, value, traceback):
34 if type != exceptions.KeyboardInterrupt:
35 old_excepthook(type, value, traceback)
36 else:
37 pass
38
39 sys.excepthook = new_hook
40
41def jiffies_to_seconds(jiffies):
42 Hertz = 100 # FIXME: Hack, need to get this, AT_CLKTCK elf note *sigh*
43 return int(jiffies) / Hertz
44
45def seconds_to_ui_time(seconds):
46 if seconds >= 60 * 60 * 24:
47 return "%d day(s) %d:%02d:%02d" % (seconds / (60 * 60 * 24),
48 (seconds / (60 * 60)) % 24,
49 (seconds / 60) % 60,
50 seconds % 60)
51 if seconds >= 60 * 60:
52 return "%d:%02d:%02d" % (seconds / (60 * 60), (seconds / 60) % 60,
53 (seconds % 60))
54 return "%02d:%02d" % ((seconds / 60), seconds % 60)
55
56def get_process_info(pid):
57 if not pid:
58 return
59
60 # Maybe true if /proc isn't mounted, or not Linux ... or something.
61 if (not os.path.exists("/proc/%d/status" % pid) or
62 not os.path.exists("/proc/stat") or
63 not os.path.exists("/proc/%d/stat" % pid)):
64 return
65
66 ps = {}
67 for line in open("/proc/%d/status" % pid):
68 if line[-1] != '\n':
69 continue
70 data = line[:-1].split(':\t', 1)
71 if len(data) < 2:
72 continue
73 if data[1].endswith(' kB'):
74 data[1] = data[1][:-3]
75 ps[data[0].strip().lower()] = data[1].strip()
76 if 'vmrss' not in ps:
77 return
78 if 'vmsize' not in ps:
79 return
80 boot_time = None
81 for line in open("/proc/stat"):
82 if line.startswith("btime "):
83 boot_time = int(line[len("btime "):-1])
84 break
85 if boot_time is None:
86 return
87 ps_stat = open("/proc/%d/stat" % pid).read().split()
88 ps['utime'] = jiffies_to_seconds(ps_stat[13])
89 ps['stime'] = jiffies_to_seconds(ps_stat[14])
90 ps['cutime'] = jiffies_to_seconds(ps_stat[15])
91 ps['cstime'] = jiffies_to_seconds(ps_stat[16])
92 ps['start_time'] = boot_time + jiffies_to_seconds(ps_stat[21])
93 ps['state'] = {'R' : _('Running'),
94 'S' : _('Sleeping'),
95 'D' : _('Uninterruptible'),
96 'Z' : _('Zombie'),
97 'T' : _('Traced/Stopped')
98 }.get(ps_stat[2], _('Unknown'))
99
100 return ps
101
102def show_lock_owner(pid, logger):
103 if not pid:
104 return
105
106 ps = get_process_info(pid)
107 # This yumBackend isn't very friendly, so...
108 if ps['name'] == 'yumBackend.py':
109 nmsg = _(" The other application is: PackageKit")
110 else:
111 nmsg = _(" The other application is: %s") % ps['name']
112
113 logger.critical("%s", nmsg)
114 logger.critical(_(" Memory : %5s RSS (%5sB VSZ)") %
115 (format_number(int(ps['vmrss']) * 1024),
116 format_number(int(ps['vmsize']) * 1024)))
117
118 ago = seconds_to_ui_time(int(time.time()) - ps['start_time'])
119 logger.critical(_(" Started: %s - %s ago") %
120 (time.ctime(ps['start_time']), ago))
121 logger.critical(_(" State : %s, pid: %d") % (ps['state'], pid))
122
123class YumUtilBase(YumBaseCli):
124 def __init__(self,name,ver,usage):
125 YumBaseCli.__init__(self)
126 self._parser = YumOptionParser(base=self,utils=True,usage=usage)
127 self._usage = usage
128 self._utilName = name
129 self._utilVer = ver
130 self._option_group = OptionGroup(self._parser, "%s options" % self._utilName,"")
131 self._parser.add_option_group(self._option_group)
132 suppress_keyboard_interrupt_message()
133 logger = logging.getLogger("yum.util")
134 verbose_logger = logging.getLogger("yum.verbose.util")
135
136
137 def getOptionParser(self):
138 return self._parser
139
140 def getOptionGroup(self):
141 """ Get an option group to add non inherited options"""
142 return self._option_group
143
144 def waitForLock(self):
145 lockerr = ""
146 while True:
147 try:
148 self.doLock()
149 except Errors.LockError, e:
150 if "%s" %(e.msg,) != lockerr:
151 lockerr = "%s" %(e.msg,)
152 self.logger.critical(lockerr)
153 self.logger.critical("Another app is currently holding the yum lock; waiting for it to exit...")
154 show_lock_owner(e.pid, self.logger)
155 time.sleep(2)
156 else:
157 break
158
159 def _printUtilVersion(self):
160 print "%s - %s (yum - %s)" % (self._utilName,self._utilVer,yum.__version__)
161
162 def doUtilConfigSetup(self,args = sys.argv[1:],pluginsTypes=(plugins.TYPE_CORE,)):
163 # Parse only command line options that affect basic yum setup
164 opts = self._parser.firstParse(args)
165 # Just print out the version if that's what the user wanted
166 if opts.version:
167 self._printUtilVersion()
168 sys.exit(0)
169 # get the install root to use
170 root = self._parser.getRoot(opts)
171 if opts.quiet:
172 opts.debuglevel = 0
173 if opts.verbose:
174 opts.debuglevel = opts.errorlevel = 6
175
176 # Read up configuration options and initialise plugins
177 try:
178 pc = self.preconf
179 pc.fn = opts.conffile
180 pc.root = root
181 pc.init_plugins = not opts.noplugins
182 pc.plugin_types = pluginsTypes
183 pc.optparser = self._parser
184 pc.debuglevel = opts.debuglevel
185 pc.errorlevel = opts.errorlevel
186 if hasattr(opts, "disableplugins"):
187 pc.disabled_plugins =self._parser._splitArg(opts.disableplugins)
188 if hasattr(opts, "enableplugins"):
189 pc.enabled_plugins = self._parser._splitArg(opts.enableplugins)
190 self.conf
191
192 except Errors.ConfigError, e:
193 self.logger.critical(_('Config Error: %s'), e)
194 sys.exit(1)
195 except ValueError, e:
196 self.logger.critical(_('Options Error: %s'), e)
197 sys.exit(1)
198 except plugins.PluginYumExit, e:
199 self.logger.critical(_('PluginExit Error: %s'), e)
200 sys.exit(1)
201 except Errors.YumBaseError, e:
202 self.logger.critical(_('Yum Error: %s'), e)
203 sys.exit(1)
204
205 # update usage in case plugins have added commands
206 self._parser.set_usage(self._usage)
207
208 # Now parse the command line for real and
209 # apply some of the options to self.conf
210 (opts, self.cmds) = self._parser.setupYumConfig()
211 if self.cmds:
212 self.basecmd = self.cmds[0] # our base command
213 else:
214 self.basecmd = None
215 self.extcmds = self.cmds[1:] # out extended arguments/commands
216
217 return opts
218
219 def doUtilYumSetup(self):
220 """do a default setup for all the normal/necessary yum components,
221 really just a shorthand for testing"""
222 # FIXME - we need another way to do this, I think.
223 try:
224 self.waitForLock()
225 self._getTs()
226 self._getRpmDB()
227 self._getRepos(doSetup = True)
228 self._getSacks()
229 except Errors.YumBaseError, msg:
230 self.logger.critical(str(msg))
231 sys.exit(1)
232
233 def doUtilTransaction(self):
234 def exUserCancel():
235 self.logger.critical(_('\n\nExiting on user cancel'))
236 if unlock(): return 200
237 return 1
238
239 def exIOError(e):
240 if e.errno == 32:
241 self.logger.critical(_('\n\nExiting on Broken Pipe'))
242 else:
243 self.logger.critical(_('\n\n%s') % str(e))
244 if unlock(): return 200
245 return 1
246
247 def exPluginExit(e):
248 '''Called when a plugin raises PluginYumExit.
249
250 Log the plugin's exit message if one was supplied.
251 ''' # ' xemacs hack
252 exitmsg = str(e)
253 if exitmsg:
254 self.logger.warn('\n\n%s', exitmsg)
255 if unlock(): return 200
256 return 1
257
258 def exFatal(e):
259 self.logger.critical('\n\n%s', to_unicode(e.value))
260 if unlock(): return 200
261 return 1
262
263 def unlock():
264 try:
265 self.closeRpmDB()
266 self.doUnlock()
267 except Errors.LockError, e:
268 return 200
269 return 0
270
271 try:
272 return_code = self.doTransaction()
273 except plugins.PluginYumExit, e:
274 return exPluginExit(e)
275 except Errors.YumBaseError, e:
276 return exFatal(e)
277 except KeyboardInterrupt:
278 return exUserCancel()
279 except IOError, e:
280 return exIOError(e)
281
282 self.verbose_logger.log(logginglevels.INFO_2, _('Complete!'))
283 if unlock(): return 200
284 return return_code
285
286def main():
287 name = 'testutil'
288 ver = '0.1'
289 usage = 'testutil [options] [args]'
290 util = YumUtilBase(name,ver,usage)
291 parser = util.getOptionParser()
292 parser.add_option("", "--myoption", dest="myoption",
293 action="store_true", default=False,
294 help="This is an util option")
295 util.logger.info("Setup Yum Config")
296 opts = util.doUtilConfigSetup()
297 util.logger.info("Setup Yum")
298 util.doUtilYumSetup()
299 print "Command line args: %s" % " ".join(util.cmds)
300 print "Command line options :"
301 print opts
302
303 util.logger.info("%s Completed" % name)
304if __name__ == '__main__':
305 main()
306
307
Note: See TracBrowser for help on using the repository browser.