summaryrefslogtreecommitdiffstats
path: root/src/plugins/abrt-action-install-debuginfo.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/abrt-action-install-debuginfo.py')
-rwxr-xr-xsrc/plugins/abrt-action-install-debuginfo.py160
1 files changed, 79 insertions, 81 deletions
diff --git a/src/plugins/abrt-action-install-debuginfo.py b/src/plugins/abrt-action-install-debuginfo.py
index b16cc3e9..9253c87f 100755
--- a/src/plugins/abrt-action-install-debuginfo.py
+++ b/src/plugins/abrt-action-install-debuginfo.py
@@ -6,6 +6,7 @@
from subprocess import Popen, PIPE
import sys
import os
+import time
import getopt
import shutil
from yum import _, YumBase
@@ -51,7 +52,11 @@ def unmute_stdout():
def ask_yes_no(prompt, retries=4):
while True:
- response = raw_input(prompt)
+ try:
+ response = raw_input(prompt)
+ except EOFError:
+ log1("got eof, probably executed from helper, assuming - yes")
+ response = 'y'
if response in ('y', 'Y'):
return True
if response in ('n', 'N', ''):
@@ -65,30 +70,30 @@ def ask_yes_no(prompt, retries=4):
# ..that can lead to: foo.c No such file and directory
# files is not used...
def unpack_rpm(package_nevra, files, tmp_dir, destdir, keeprpm):
- package_file_suffix = ".rpm"
- package_full_path = tmp_dir + "/" + package_nevra + package_file_suffix
+ package_name = package_nevra + ".rpm"
+ package_full_path = tmp_dir + "/" + package_name
log1("Extracting %s to %s" % (package_full_path, destdir))
log2(files)
- print (_("Extracting cpio from %s") % (package_full_path))
+ print _("Extracting cpio from %s") % (package_full_path)
unpacked_cpio_path = tmp_dir + "/unpacked.cpio"
try:
unpacked_cpio = open(unpacked_cpio_path, 'wb')
except IOError, ex:
- print (_("Can't write to:"), (unpacked_cpio_path,ex))
+ print _("Can't write to '%s': %s") % (unpacked_cpio_path, ex)
return RETURN_FAILURE
rpm2cpio = Popen(["rpm2cpio", package_full_path],
- stdout=unpacked_cpio, bufsize=-1)
+ stdout = unpacked_cpio, bufsize = -1)
retcode = rpm2cpio.wait()
if retcode == 0:
log1("cpio written OK")
if not keeprpm:
log1("keeprpms = False, removing %s" % package_full_path)
- print _("Removing the temporary rpm file")
+ #print _("Removing temporary rpm file")
os.unlink(package_full_path)
else:
unpacked_cpio.close()
- print (_("Can't extract package: %s") % package_full_path)
+ print _("Can't extract package '%s'") % package_full_path
return RETURN_FAILURE
# close the file
@@ -96,18 +101,17 @@ def unpack_rpm(package_nevra, files, tmp_dir, destdir, keeprpm):
# and open it for reading
unpacked_cpio = open(unpacked_cpio_path, 'rb')
- print (_("Caching files from %s made from %s") %
- (unpacked_cpio_path, package_full_path))
+ print _("Caching files from %s made from %s") % ("unpacked.cpio", package_name)
cpio = Popen(["cpio","-i", "-d", "--quiet"],
stdin=unpacked_cpio, cwd=destdir, bufsize=-1)
retcode = cpio.wait()
if retcode == 0:
log1("files extracted OK")
- print _("Removing the temporary cpio file")
+ #print _("Removing temporary cpio file")
os.unlink(unpacked_cpio_path)
else:
- print (_("Can't extract files from: %s") % unpacked_cpio_path)
+ print _("Can't extract files from '%s'") % unpacked_cpio_path
return RETURN_FAILURE
class MyDownloadCallback(DownloadBaseCallback):
@@ -115,36 +119,42 @@ class MyDownloadCallback(DownloadBaseCallback):
self.total_pkgs = total_pkgs
self.downloaded_pkgs = 0
self.last_pct = 0
+ self.last_time = 0
DownloadBaseCallback.__init__(self)
def updateProgress(self, name, frac, fread, ftime):
- pct = int( frac*100 )
+ pct = int(frac * 100)
if pct == self.last_pct:
log2("percentage is the same, not updating progress")
return
self.last_pct = pct
- # if run from terminal we can have a fancy output
+ # if run from terminal we can have fancy output
if sys.stdout.isatty():
- sys.stdout.write("\033[sDownloading (%i of %i) %.30s : %.3s %%\033[u"
- % (self.downloaded_pkgs + 1, self.total_pkgs,
- name, pct)
- )
+ sys.stdout.write("\033[sDownloading (%i of %i) %s: %3u%%\033[u"
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
if pct == 100:
- print _("Downloading (%i of %i) %.30s : %.3s %%"
- % (self.downloaded_pkgs + 1, self.total_pkgs,
- name, pct)
- )
+ print (_("Downloading (%i of %i) %s: %3u%%")
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
# but we want machine friendly output when spawned from abrt-server
else:
- print (_("Downloading (%i of %i) %.30s : %.3s %%")
- % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
- )
+ t = time.time()
+ if self.last_time == 0:
+ self.last_time = t
+ # update only every 10 seconds
+ if pct == 100 or self.last_time > t or t - self.last_time >= 10:
+ print (_("Downloading (%i of %i) %s: %3u%%")
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
+ self.last_time = t
+ if pct == 100:
+ self.last_time = 0
sys.stdout.flush()
class DebugInfoDownload(YumBase):
- """abrt-debuginfo-install --core=CORE tmpdir cachedir"""
def __init__(self, cache, tmp, keep_rpms=False):
self.cachedir = cache
self.tmpdir = tmp
@@ -166,13 +176,13 @@ class DebugInfoDownload(YumBase):
if not files:
return
- print _("Searching the missing debuginfo packages")
- # this suppress yum messages about setting up repositories
- mute_stdout()
+ if verbose == 0:
+ # this suppress yum messages about setting up repositories
+ mute_stdout()
# make yumdownloader work as non root user.
if not self.setCacheDir():
- self.logger.error("Error: Could not make cachedir, exiting")
+ self.logger.error("Error: can't make cachedir, exiting")
sys.exit(50)
# disable all not needed
@@ -191,13 +201,14 @@ class DebugInfoDownload(YumBase):
self.repos.populateSack(mdtype='metadata', cacheonly=1)
self.repos.populateSack(mdtype='filelists', cacheonly=1)
- # re-enable the output to stdout
- unmute_stdout()
+ if verbose == 0:
+ # re-enable the output to stdout
+ unmute_stdout()
not_found = []
package_files_dict = {}
for debuginfo_path in files:
- log2("yum whatprovides %s" %debuginfo_path)
+ log2("yum whatprovides %s" % debuginfo_path)
pkg = self.pkgSack.searchFiles(debuginfo_path)
# sometimes one file is provided by more rpms, we can use either of
# them, so let's use the first match
@@ -210,29 +221,23 @@ class DebugInfoDownload(YumBase):
installed_size += float(pkg[0].installedsize)
total_pkgs += 1
- log2("found pkg for %s" % debuginfo_path)
+ log2("found pkg for %s: %s" % (debuginfo_path, pkg[0]))
else:
log2("not found pkg for %s" % debuginfo_path)
not_found.append(debuginfo_path)
# connect our progress update callback
dnlcb = MyDownloadCallback(total_pkgs)
- self.repos.setProgressBar( dnlcb )
-
- log1("%i files in %i packages" % (len(files), total_pkgs))
+ self.repos.setProgressBar(dnlcb)
- print (_("To download: (%.2f) M / Installed size: %.2f M" %
- (
- todownload_size / (1024**2),
- installed_size / (1024**2))
- )
- )
- #print _("%i debug infos not found" % len(not_found))
-
- log1("packages: %i\nTo download: %f \nUnpacked size: %f" %
- (total_pkgs,
- todownload_size / (1024**2),
- installed_size / (1024**2)))
+ if verbose != 0 or len(not_found) != 0:
+ print _("Can't find packages for %u debuginfo files") % len(not_found)
+ if verbose != 0 or total_pkgs != 0:
+ print _("Found %u packages to download") % total_pkgs
+ print _("Downloading %.2fMb, installed size: %.2fMb") % (
+ todownload_size / (1024**2),
+ installed_size / (1024**2)
+ )
# ask only if we have terminal, because for now we don't have a way
# how to pass the question to gui and the response back
@@ -271,13 +276,13 @@ class DebugInfoDownload(YumBase):
downloaded_pkgs += 1
- if not self.keeprpms:
+ if not self.keeprpms and os.path.exists(self.tmpdir):
print (_("All downloaded packages have been extracted, removing %s")
% self.tmpdir)
try:
os.rmdir(self.tmpdir)
except OSError:
- print _("Can't remove %s, probably contains an error log")
+ print _("Can't remove %s, probably contains an error log" % self.tmpdir)
verbose = 0
def log1(message):
@@ -302,8 +307,7 @@ def extract_info_from_core(corefile):
#SEP = 3
EXECUTABLE = 4
- print (_("Analyzing corefile: %(corefile_path)s") %
- {"corefile_path":corefile})
+ print _("Analyzing corefile '%s'") % corefile
eu_unstrip_OUT = Popen(["eu-unstrip","--core=%s" % corefile, "-n"], stdout=PIPE, bufsize=-1).communicate()[0]
# parse eu_unstrip_OUT and return the list of build_ids
@@ -323,7 +327,7 @@ def extract_info_from_core(corefile):
#print eu_unstrip_OUT
# we failed to get build ids from the core -> die
if not eu_unstrip_OUT:
- log1("can't get build ids from the core")
+ print "Can't get build ids from %s" % corefile
return RETURN_FAILURE
lines = eu_unstrip_OUT.split('\n')
@@ -344,7 +348,7 @@ def extract_info_from_core(corefile):
libraries.add(library)
build_ids.add(build_id)
else:
- log2("skipping line %s" % line)
+ log2("skipping line '%s'" % line)
log1("Found %i build_ids" % len(build_ids))
log1("Found %i libs" % len(libraries))
return build_ids
@@ -354,7 +358,7 @@ def build_ids_to_path(build_ids):
build_id1=${build_id:0:2}
build_id2=${build_id:2}
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
- """
+ """
return ["/usr/lib/debug/.build-id/%s/%s.debug" % (b_id[:2], b_id[2:]) for b_id in build_ids]
# beware this finds only missing libraries, but not the executable itself ..
@@ -381,9 +385,7 @@ def clean_up():
try:
shutil.rmtree(tmpdir)
except OSError, ex:
- print (_("Can't remove %(tmpdir_path)s: %(reason)s")
- % {"tmpdir_path":tmpdir, "reason": ex }
- )
+ print _("Can't remove '%s': %s") % (tmpdir, ex)
def sigterm_handler(signum, frame):
clean_up()
@@ -391,10 +393,11 @@ def sigterm_handler(signum, frame):
def sigint_handler(signum, frame):
clean_up()
- print "\n", _("Exiting on user Command")
+ print "\n", _("Exiting on user command")
exit(RETURN_OK)
import signal
+
if __name__ == "__main__":
# abrt-server can send SIGTERM to abort the download
signal.signal(signal.SIGTERM, sigterm_handler)
@@ -404,15 +407,14 @@ if __name__ == "__main__":
cachedir = None
tmpdir = None
keeprpms = False
- result = RETURN_OK
noninteractive = False
# localization
init_gettext()
- help_text = _("Usage: %s --core=<COREFILE> "
- "--tmpdir=<TMPDIR> "
- "--cachedir=<CACHEDIR>") % sys.argv[0]
+ help_text = _("Usage: %s --core=COREFILE "
+ "--tmpdir=TMPDIR "
+ "--cache=CACHEDIR") % sys.argv[0]
try:
opts, args = getopt.getopt(sys.argv[1:], "vyhc:", ["help", "core=",
"cache=", "tmpdir=",
@@ -426,7 +428,7 @@ if __name__ == "__main__":
verbose += 1
elif opt == "-y":
noninteractive = True
- elif opt in ("--core","-c"):
+ elif opt in ("--core", "-c"):
core = arg
elif opt in ("--cache"):
cachedir = arg
@@ -443,30 +445,26 @@ if __name__ == "__main__":
print help_text
exit(RETURN_FAILURE)
if not cachedir:
- print _("You have to specify the path to cachedir.")
- print help_text
- exit(RETURN_FAILURE)
+ cachedir = "/var/cache/abrt-di"
if not tmpdir:
- print _("You have to specify the path to tmpdir.")
- print help_text
- exit(RETURN_FAILURE)
+ # security people prefer temp subdirs in app's private dir, like /var/run/abrt
+ # for now, we use /tmp...
+ tmpdir = "/tmp/abrt-tmp-debuginfo-%s.%u" % (time.strftime("%Y-%m-%d-%H:%M:%S"), os.getpid())
b_ids = extract_info_from_core(core)
if b_ids == RETURN_FAILURE:
exit(RETURN_FAILURE)
+
missing = filter_installed_debuginfos(b_ids, cachedir)
if missing:
log2(missing)
+ print _("Coredump references %u debuginfo files, %u of them are not installed") % (len(b_ids), len(missing))
downloader = DebugInfoDownload(cache=cachedir, tmp=tmpdir)
result = downloader.download(missing)
- else:
- print _("All debuginfo seems to be available")
- exit(RETURN_OK)
-
- missing = filter_installed_debuginfos(b_ids, cachedir)
- for bid in missing:
- log1("MISSING:%s" % bid)
-
- print _("Complete!")
- exit(result)
+ missing = filter_installed_debuginfos(b_ids, cachedir)
+ for bid in missing:
+ print _("Missing debuginfo file: %s") % bid
+ exit(result)
+ print _("All %u debuginfo files are available") % len(b_ids)
+ exit(RETURN_OK)