summaryrefslogtreecommitdiffstats
path: root/src/retrace
diff options
context:
space:
mode:
Diffstat (limited to 'src/retrace')
-rw-r--r--src/retrace/Makefile.am31
-rwxr-xr-xsrc/retrace/abrt-retrace-cleanup60
-rwxr-xr-xsrc/retrace/abrt-retrace-reposync118
-rw-r--r--src/retrace/backtrace.wsgi46
-rwxr-xr-xsrc/retrace/coredump2packages293
-rw-r--r--src/retrace/create.wsgi111
-rwxr-xr-xsrc/retrace/install.sh212
-rw-r--r--src/retrace/log.wsgi46
-rw-r--r--src/retrace/plugins/Makefile.am2
-rw-r--r--src/retrace/plugins/__init__.py24
-rw-r--r--src/retrace/plugins/fedora.py29
-rw-r--r--src/retrace/retrace.conf33
-rw-r--r--src/retrace/retrace.py412
-rw-r--r--src/retrace/retrace.repo23
-rw-r--r--src/retrace/retrace_httpd.conf5
-rw-r--r--src/retrace/settings.wsgi18
-rw-r--r--src/retrace/status.wsgi49
-rw-r--r--src/retrace/worker.c77
-rwxr-xr-xsrc/retrace/worker.py305
19 files changed, 0 insertions, 1894 deletions
diff --git a/src/retrace/Makefile.am b/src/retrace/Makefile.am
deleted file mode 100644
index 684d0f5a..00000000
--- a/src/retrace/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-SUBDIRS = plugins
-
-bin_PROGRAMS = abrt-retrace-worker
-abrt_retrace_worker_SOURCES = worker.c
-
-dist_bin_SCRIPTS = abrt-retrace-cleanup abrt-retrace-reposync coredump2packages
-
-python_PYTHON = retrace.py
-
-worker_PYTHON = worker.py
-workerdir = $(datadir)/abrt-retrace
-
-interface_PYTHON = backtrace.wsgi create.wsgi log.wsgi settings.wsgi status.wsgi
-# interfacedir should probably be $$(pkgdatadir)/retrace
-interfacedir = $(datadir)/abrt-retrace
-
-repo_DATA = retrace.repo
-repodir = ${sysconfdir}/yum.repos.d
-
-retraceconf_DATA = retrace.conf
-retraceconfdir = ${sysconfdir}/abrt
-
-httpdconf_DATA = retrace_httpd.conf
-httpdconfdir = ${sysconfdir}/httpd/conf.d
-
-EXTRA_DIST = retrace.conf retrace_httpd.conf retrace.repo
-
-# Apache config files can be owned by root, httpd just needs read
-# access.
-#install-data-hook:
-# chown apache:apache $(DESTDIR)$(httpdconfdir)/retrace_httpd.conf
diff --git a/src/retrace/abrt-retrace-cleanup b/src/retrace/abrt-retrace-cleanup
deleted file mode 100755
index cbe1b818..00000000
--- a/src/retrace/abrt-retrace-cleanup
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python
-
-import os
-import sys
-import time
-from retrace import *
-
-if __name__ == "__main__":
- now = int(time.time())
-
- logfile = "%s/cleanup.log" % CONFIG["LogDir"]
-
- try:
- log = open(logfile, "a")
- except IOError, ex:
- print "Error opening log file: %s" % ex
- sys.exit(1)
-
- log.write(time.strftime("[%Y-%m-%d %H:%M:%S] Running cleanup\n"))
-
- # kill tasks running > 1 hour
- ps_output = run_ps()
- running_tasks = get_running_tasks(ps_output)
- for pid, taskid, runtime in running_tasks:
- # ToDo: 5 = mm:ss, >5 = hh:mm:ss
- if len(runtime) > 5:
- log.write("Killing task %d running for %s\n" % (taskid, runtime))
- kill_process_and_childs(pid, ps_output)
-
- # kill orphaned tasks
- running_tasks = get_running_tasks()
- running_ids = []
- for pid, taskid, runtime in running_tasks:
- running_ids.append(taskid)
-
- for task in get_active_tasks():
- if not task in running_ids:
- log.write("Cleaning up orphaned task %d\n" % task)
- cleanup_task(task)
-
- # clean up old tasks
- try:
- files = os.listdir(CONFIG["SaveDir"])
- except OSError, ex:
- files = []
- log.write("Error listing task directory: %s\n" % ex)
-
- for filename in files:
- try:
- taskid = int(filename)
- except:
- continue
-
- dirpath = "%s/%s" % (CONFIG["SaveDir"], filename)
- if os.path.isdir(dirpath) and \
- (now - os.path.getatime(dirpath)) / 3600 >= CONFIG["DeleteTaskAfter"]:
- log.write("Deleting old task %s\n" % filename)
- call(["rm", "-rf", dirpath])
-
- log.close()
diff --git a/src/retrace/abrt-retrace-reposync b/src/retrace/abrt-retrace-reposync
deleted file mode 100755
index 30b437f2..00000000
--- a/src/retrace/abrt-retrace-reposync
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/python
-
-import argparse
-import os
-import pwd
-import sys
-from retrace import *
-
-sys.path = ["/usr/share/abrt-retrace"] + sys.path
-from plugins import *
-
-TARGET_USER = "abrt"
-
-if __name__ == "__main__":
- # parse arguments
- argparser = argparse.ArgumentParser(description="Retrace Server repository downloader")
- argparser.add_argument("distribution", type=str, help="Distribution name")
- argparser.add_argument("version", type=str, help="Release version")
- argparser.add_argument("architecture", type=str, help="CPU architecture")
- args = argparser.parse_args()
-
- distribution = args.distribution
- version = args.version
- arch = args.architecture
-
- if arch == "i686":
- arch = "i386"
-
- # drop privilegies if possible
- try:
- pw = pwd.getpwnam(TARGET_USER)
- os.setgid(pw.pw_gid)
- os.setuid(pw.pw_uid)
- print "Privilegies set to '%s'." % TARGET_USER
- except KeyError:
- print "User '%s' does not exist. Running with default privilegies." % TARGET_USER
- except OSError:
- print "Unable to switch UID or GID. Running with default privilegies."
-
- # load plugin
- plugin = None
- for iplugin in PLUGINS:
- if iplugin.distribution == distribution:
- plugin = iplugin
- break
-
- if not plugin:
- print "Unknown distribution: '%s'" % distribution
- sys.exit(1)
-
- lockfile = "/tmp/abrt-retrace-lock-%s-%s-%s" % (distribution, version, arch)
-
- if os.path.isfile(lockfile):
- print "Another process with repository download is running."
- sys.exit(2)
-
- # set lock
- if not lock(lockfile):
- print "Unable to set lock."
- sys.exit(3)
-
- null = open("/dev/null", "w")
-
- targetdir = "%s/%s-%s-%s" % (CONFIG["RepoDir"], distribution, version, arch)
-
- # run rsync
- for repo in plugin.repos:
- retcode = -1
- for mirror in repo:
- repourl = mirror.replace("$ARCH", arch).replace("$VER", version)
-
- print "Running rsync on '%s'..." % repourl,
- sys.stdout.flush()
-
- if repourl.startswith("rsync://"):
- files = [repourl]
- else:
- files = []
- try:
- for package in os.listdir(repourl):
- files.append("%s/%s" % (repourl, package))
- except Exception as ex:
- print "Error: %s. Trying another mirror..." % ex
- continue
-
- pipe = Popen(["rsync", "-t"] + files + [targetdir], stdout=null, stderr=null)
- pipe.wait()
- retcode = pipe.returncode
-
- if retcode == 0:
- print "OK"
- break
-
- print "Error. Trying another mirror..."
-
- if retcode != 0:
- print "No more mirrors to try."
-
- # run createrepo
- print "Running createrepo on '%s'..." % targetdir,
- sys.stdout.flush()
-
- pipe = Popen(["createrepo", targetdir], stdout=null, stderr=null)
- pipe.wait()
-
- null.close()
-
- if pipe.returncode != 0:
- print "Failed"
- unlock(lockfile)
- sys.exit(4)
-
- print "OK"
-
- # remove lock
- if not unlock(lockfile):
- print "Unable to remove lock."
- sys.exit(5)
diff --git a/src/retrace/backtrace.wsgi b/src/retrace/backtrace.wsgi
deleted file mode 100644
index 92c4d040..00000000
--- a/src/retrace/backtrace.wsgi
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python
-
-from retrace import *
-
-def application(environ, start_response):
- request = Request(environ)
-
- match = URL_PARSER.match(request.script_name)
- if not match:
- return response(start_response, "404 Not Found",
- "Invalid URL")
-
- taskdir = "%s/%s" % (CONFIG["SaveDir"], match.group(1))
-
- if not os.path.isdir(taskdir):
- return response(start_response, "404 Not Found",
- "There is no such task")
-
- pwdpath = "%s/password" % taskdir
- try:
- pwdfile = open(pwdpath, "r")
- pwd = pwdfile.read()
- pwdfile.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to verify password")
-
- if not "X-Task-Password" in request.headers or \
- request.headers["X-Task-Password"] != pwd:
- return response(start_response, "403 Forbidden",
- "Invalid password")
-
- btpath = "%s/retrace_backtrace" % taskdir
- if not os.path.isfile(btpath):
- return response(start_response, "404 Not Found",
- "There is no backtrace for the specified task")
-
- try:
- btfile = open(btpath, "r")
- output = btfile.read()
- btfile.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to read backtrace file")
-
- return response(start_response, "200 OK", output)
diff --git a/src/retrace/coredump2packages b/src/retrace/coredump2packages
deleted file mode 100755
index ac2db9f2..00000000
--- a/src/retrace/coredump2packages
+++ /dev/null
@@ -1,293 +0,0 @@
-#! /usr/bin/python
-# -*- coding:utf-8;mode:python -*-
-# Gets list of packages necessary for processing of a coredump.
-# Uses eu-unstrip and yum.
-
-import subprocess
-import yum
-import sys
-import argparse
-
-parser = argparse.ArgumentParser(description='Get packages for coredump processing.')
-parser.add_argument('--repos', default='*', metavar='WILDCARD',
- help='Yum repository wildcard to be enabled')
-parser.add_argument('coredump', help='Coredump')
-parser.add_argument('--log', metavar='FILENAME',
- help='Store debug output to a file')
-args = parser.parse_args()
-
-if args.log:
- log = open(args.log, "w")
-else:
- log = open("/dev/null", "w")
-
-#
-# Initialize yum, enable only repositories specified via command line
-# --repos option.
-#
-stdout = sys.stdout
-sys.stdout = log
-yumbase = yum.YumBase()
-yumbase.doConfigSetup()
-if not yumbase.setCacheDir():
- exit(2)
-log.write("Closing all enabled repositories...\n")
-for repo in yumbase.repos.listEnabled():
- log.write(" - {0}\n".format(repo.name))
- repo.close()
- yumbase.repos.disableRepo(repo.id)
-log.write("Enabling repositories matching \'{0}\'...\n".format(args.repos))
-for repo in yumbase.repos.findRepos(args.repos):
- log.write(" - {0}\n".format(repo.name))
- repo.enable()
- repo.skip_if_unavailable = True
-yumbase.repos.doSetup()
-yumbase.repos.populateSack(mdtype='metadata', cacheonly=1)
-yumbase.repos.populateSack(mdtype='filelists', cacheonly=1)
-sys.stdout = stdout
-
-#
-# Get eu-unstrip output, which contains build-ids and binary object
-# paths
-#
-log.write("Running eu-unstrip...\n")
-unstrip_args = ['eu-unstrip', '--core={0}'.format(args.coredump), '-n']
-unstrip_proc = subprocess.Popen(unstrip_args, stdout=subprocess.PIPE)
-unstrip = unstrip_proc.communicate()[0]
-log.write("{0}\n".format(unstrip))
-if not unstrip:
- exit(1)
-
-def binary_packages_from_debuginfo_package(debuginfo_package, binobj_path):
- """
- Returns a list of packages corresponding to the provided debuginfo
- package. One of the packages in the list contains the binary
- specified in binobj_path; this is a list because if binobj_patch
- is not specified (and sometimes it is not, binobj_path might
- contain just '-'), we do not know which package contains the
- binary, we know only packages from the same SRPM as the debuginfo
- package.
- """
- package_list = []
- if binobj_path == '-': # [exe] without binary name
- log.write(" Yum search for [exe] without binary name, "
- "packages with NVR {0}:{1}-{2}.{3}...\n".format(debuginfo_package.epoch,
- debuginfo_package.ver,
- debuginfo_package.rel,
- debuginfo_package.arch))
- # Append all packages with the same base package name.
- # Other possibility is to download the debuginfo RPM,
- # unpack it, and get the name of the binary from the
- # /usr/lib/debug/.build-id/xx/yyyyyy symlink.
- evra_list = yumbase.pkgSack.searchNevra(epoch=debuginfo_package.epoch,
- ver=debuginfo_package.ver,
- rel=debuginfo_package.rel,
- arch=debuginfo_package.arch)
- for package in evra_list:
- log.write(" - {0}: base name \"{1}\"\n".format(str(package), package.base_package_name))
- if package.base_package_name != debuginfo_package.base_package_name:
- continue
- package_list.append(package)
- else:
- log.write(" Yum search for {0}...\n".format(binobj_path))
- binobj_package_list = yumbase.pkgSack.searchFiles(binobj_path)
- for binobj_package in binobj_package_list:
- log.write(" - {0}".format(str(binobj_package)))
- if 0 != binobj_package.returnEVR().compare(debuginfo_package.returnEVR()):
- log.write(": NVR doesn't match\n")
- continue
- log.write(": NVR matches\n")
- package_list.append(binobj_package)
- return package_list
-
-def process_unstrip_entry(build_id, binobj_path):
- """
- Returns a tuple of two items.
-
- First item is a list of packages which we found to be associated
- with the unstrip entry defined by build_id and binobj_path.
-
- Second item is a list of package versions (same package name,
- different epoch-version-release), which contain the binary object
- (an executable or shared library) corresponding to this unstrip
- entry. If this method failed to find an unique package name (with
- only different versions), this list contains the list of base
- package names. This item can be used to associate a coredump with
- some crashing package.
- """
- package_list = []
- coredump_package_list = []
- coredump_base_package_list = []
- # Ask for a known path from debuginfo package.
- debuginfo_path = "/usr/lib/debug/.build-id/{0}/{1}.debug".format(build_id[:2], build_id[2:])
- log.write("Yum search for {0}...\n".format(debuginfo_path))
- debuginfo_package_list = yumbase.pkgSack.searchFiles(debuginfo_path)
-
- # A problem here is that some libraries lack debuginfo. Either
- # they were stripped during build, or they were not stripped by
- # /usr/lib/rpm/find-debuginfo.sh because of wrong permissions or
- # something. The proper solution is to detect such libraries and
- # fix the packages.
- for debuginfo_package in debuginfo_package_list:
- log.write(" - {0}\n".format(str(debuginfo_package)))
- package_list.append(debuginfo_package)
- binary_packages = binary_packages_from_debuginfo_package(debuginfo_package, binobj_path)
- coredump_base_package_list.append(debuginfo_package.base_package_name)
- if len(binary_packages) == 1:
- coredump_package_list.append(str(binary_packages[0]))
- package_list.extend(binary_packages)
- if len(coredump_package_list) == len(coredump_base_package_list):
- return package_list, coredump_package_list
- else:
- return package_list, coredump_base_package_list
-
-
-def process_unstrip_output():
- """
- Parse the eu-unstrip output, and search for packages via yum.
-
- Returns a tuple containing three items:
- - a list of package objects
- - a list of missing buildid entries
- - a list of coredump package adepts
- """
- # List of packages found in yum repositories and matching the
- # coredump.
- package_list = []
- # List of pairs (library/executable path, build id) which were not
- # found via yum.
- missing_buildid_list = []
- # coredump package adepts
- coredump_package_list = []
- first_entry = True
- for line in unstrip.split('\n'):
- parts = line.split()
- if not parts or len(parts) < 3:
- continue
- build_id = parts[1].split('@')[0]
- binobj_path = parts[2]
- if binobj_path[0] != '/' and parts[4] != '[exe]':
- continue
- entry_package_list, entry_coredump_package_list = process_unstrip_entry(build_id, binobj_path)
- if first_entry:
- coredump_package_list = entry_coredump_package_list
- first_entry = False
- if len(entry_package_list) == 0:
- missing_buildid_list.append([binobj_path, build_id])
- else:
- for entry_package in entry_package_list:
- found = False
- for package in package_list:
- if str(entry_package) == str(package):
- found = True
- break
- if not found:
- package_list.append(entry_package)
- return package_list, missing_buildid_list, coredump_package_list
-
-package_list, missing_buildid_list, coredump_package_list = process_unstrip_output()
-
-#
-# The package list might contain multiple packages with the same name,
-# but different version. This happens because some binary had the same
-# build id over multiple package releases.
-#
-def find_duplicates(package_list):
- for p1 in range(0, len(package_list) - 1):
- package1 = package_list[p1]
- for p2 in range(p1 + 1, len(package_list)):
- package2 = package_list[p2]
- if package1.name == package2.name:
- return package1, package2
- return None, None
-
-def count_removals(package_list, base_package_name, epoch, ver, rel, arch):
- count = 0
- for package in package_list:
- if package.base_package_name != base_package_name:
- continue
- if package.epoch != epoch or package.ver != ver or package.rel != rel or package.arch != arch:
- continue
- count += 1
- return count
-
-log.write("Checking for duplicates...\n")
-while True:
- package1, package2 = find_duplicates(package_list)
- if package1 is None:
- break
- p1removals = count_removals(package_list,
- package1.base_package_name,
- package1.epoch,
- package1.ver,
- package1.rel,
- package1.arch)
- p2removals = count_removals(package_list,
- package2.base_package_name,
- package2.epoch,
- package2.ver,
- package2.rel,
- package2.arch)
-
- log.write(" - {0}".format(package1.base_package_name))
- if package1.base_package_name != package2.base_package_name:
- log.write(" {0}\n".format(package2.base_package_name))
- else:
- log.write("\n")
- log.write(" - {0}:{1}-{2}.{3} ({4} dependent packages)\n".format(package1.epoch,
- package1.ver,
- package1.rel,
- package1.arch,
- p1removals))
- log.write(" - {0}:{1}-{2}.{3} ({4} dependent packages)\n".format(package2.epoch,
- package2.ver,
- package2.rel,
- package2.arch,
- p2removals))
-
- removal_candidate = package1
- if p1removals == p2removals:
- # Remove older if we can choose
- if package1.returnEVR().compare(package2.returnEVR()) > 0:
- removal_candidate = package2
- log.write(" - decided to remove {0}:{1}-{2}.{3} because it's older\n".format(removal_candidate.epoch,
- removal_candidate.ver,
- removal_candidate.rel,
- removal_candidate.arch))
- else:
- if p1removals > p2removals:
- removal_candidate = package2
- log.write(" - decided to remove {0}:{1}-{2}.{3} because has fewer dependencies\n".format(removal_candidate.epoch,
- removal_candidate.ver,
- removal_candidate.rel,
- removal_candidate.arch))
- # Remove the removal_candidate packages from the package list
- for package in package_list[:]:
- if package.base_package_name == removal_candidate.base_package_name and \
- 0 == package.returnEVR().compare(removal_candidate.returnEVR()):
- package_list.remove(package)
-
-# Clean coredump_package_list:
-for coredump_package in coredump_package_list[:]:
- found = False
- for package in package_list:
- if str(package) == coredump_package or package.base_package_name == coredump_package:
- found = True
- break
- if not found:
- coredump_package_list.remove(coredump_package)
-
-#
-# Print names of found packages first, then a newline separator, and
-# then objects for which the packages were not found.
-#
-if len(coredump_package_list) == 1:
- print coredump_package_list[0]
-else:
- print "-"
-print
-for package in sorted(package_list):
- print str(package)
-print
-for path, build_id in missing_buildid_list:
- print "{0} {1}".format(path, build_id)
diff --git a/src/retrace/create.wsgi b/src/retrace/create.wsgi
deleted file mode 100644
index 7c5f81b4..00000000
--- a/src/retrace/create.wsgi
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/python
-
-from retrace import *
-from tempfile import *
-
-def application(environ, start_response):
- request = Request(environ)
-
- if request.scheme != "https":
- return response(start_response, "403 Forbidden",
- "You must use HTTPS")
-
- if len(get_active_tasks()) >= CONFIG["MaxParallelTasks"]:
- return response(start_response, "503 Service Unavailable",
- "Retrace server is fully loaded at the moment")
-
- if request.method != "POST":
- return response(start_response, "405 Method Not Allowed",
- "You must use POST method")
-
- if not request.content_type in HANDLE_ARCHIVE.keys():
- return response(start_response, "415 Unsupported Media Type",
- "Specified archive format is not supported")
-
- if not request.content_length:
- return response(start_response, "411 Length Required",
- "You need to set Content-Length header properly")
-
- if request.content_length > CONFIG["MaxPackedSize"] * 1048576:
- return response(start_response, "413 Request Entity Too Large",
- "Specified archive is too large")
-
- if CONFIG["UseWorkDir"]:
- workdir = CONFIG["WorkDir"]
- else:
- workdir = CONFIG["SaveDir"]
-
- if not os.path.isdir(workdir):
- try:
- os.makedirs(workdir)
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to create working directory")
-
- space = free_space(workdir)
-
- if not space:
- return response(start_response, "500 Internal Server Error",
- "Unable to obtain disk free space")
-
- if space - request.content_length < CONFIG["MinStorageLeft"] * 1048576:
- return response(start_response, "507 Insufficient Storage",
- "There is not enough storage space on the server")
-
- try:
- archive = NamedTemporaryFile(mode="wb", delete=False, suffix=".tar.xz")
- archive.write(request.body)
- archive.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to save archive")
-
- size = unpacked_size(archive.name, request.content_type)
- if not size:
- os.unlink(archive.name)
- return response(start_response, "500 Internal Server Error",
- "Unable to obtain unpacked size")
-
- if size > CONFIG["MaxUnpackedSize"] * 1048576:
- os.unlink(archive.name)
- return response(start_response, "413 Request Entity Too Large",
- "Specified archive's content is too large")
-
- if space - size < CONFIG["MinStorageLeft"] * 1048576:
- os.unlink(archive.name)
- return response(start_response, "507 Insufficient Storage",
- "There is not enough storage space on the server")
-
- taskid, taskpass, taskdir = new_task()
- if not taskid or not taskpass or not taskdir:
- return response(start_response, "500 Internal Server Error",
- "Unable to create new task")
-
- try:
- os.mkdir("%s/crash/" % taskdir)
- os.chdir("%s/crash/" % taskdir)
- unpack_retcode = unpack(archive.name, request.content_type)
- os.unlink(archive.name)
-
- if unpack_retcode != 0:
- raise Exception
- except:
- os.chdir("/")
- Popen(["rm", "-rf", taskdir])
- return response(start_response, "500 Internal Server Error",
- "Unable to unpack archive")
-
- files = os.listdir(".")
-
- for required_file in REQUIRED_FILES:
- if not required_file in files:
- os.chdir("/")
- Popen(["rm", "-rf", taskdir])
- return response(start_response, "403 Forbidden",
- "Required file \"%s\" is missing" % required_file)
-
- call(["/usr/bin/abrt-retrace-worker", "%d" % taskid])
-
- return response(start_response, "201 Created", "",
- [("X-Task-Id", "%d" % taskid),
- ("X-Task-Password", taskpass)])
diff --git a/src/retrace/install.sh b/src/retrace/install.sh
deleted file mode 100755
index d73a0b58..00000000
--- a/src/retrace/install.sh
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/bin/bash
-
-ABRTDIR="/etc/abrt"
-LOGDIR="/var/log/abrt-retrace"
-REPODIR="/var/cache/abrt-retrace"
-SCRIPTDIR="/usr/share/abrt-retrace"
-SRCDIR="."
-WORKDIR="/var/spool/abrt-retrace"
-
-FILES="$SRCDIR/create.wsgi $SRCDIR/status.wsgi \
- $SRCDIR/log.wsgi $SRCDIR/backtrace.wsgi \
- $SRCDIR/retrace.py $SRCDIR/abrt-retrace-reposync \
- $SRCDIR/worker.py $SRCDIR/coredump2packages.py \
- $SRCDIR/abrt-retrace-cleanup.py"
-
-if [ ! $EUID = "0" ]
-then
- echo "You must run '$0' with root permissions."
- exit 1
-fi
-
-if ! rpm -q httpd > /dev/null 2>&1
-then
- echo "httpd package is required to install Retrace Server."
- exit 2
-fi
-
-if ! rpm -q mod_wsgi > /dev/null 2>&1
-then
- echo "mod_wsgi package is required to install Retrace Server"
- exit 3
-fi
-
-if ! rpm -q mod_ssl > /dev/null 2>&1
-then
- echo "mod_ssl package is required to install Retrace Server"
- exit 4
-fi
-
-if ! rpm -q python-webob > /dev/null 2>&1
-then
- echo "python-webob package is required to install Retrace Server"
- exit 5
-fi
-
-if ! rpm -q elfutils > /dev/null 2>&1
-then
- echo "elfutils package is required to install Retrace Server"
- exit 6
-fi
-
-if ! rpm -q createrepo > /dev/null 2>&1
-then
- echo "createrepo package is required to install Retrace Server"
- exit 7
-fi
-
-if ! rpm -q mock > /dev/null 2>&1
-then
- echo "mock package is required to install Retrace Server"
- exit 8
-fi
-
-if ! rpm -q xz > /dev/null 2>&1
-then
- echo "xz package is required to install Retrace Server"
- exit 9
-fi
-
-if ! rpm -q gcc > /dev/null 2>&1
-then
- echo "gcc package is required to install Retrace Server"
- exit 10
-fi
-
-if usermod -G mock root
-then
- echo "User 'root' added to 'mock' group"
-else
- echo "Unable to add user 'root' to group 'mock'"
- exit 11
-fi
-
-if [ ! -d "$ABRTDIR" ]
-then
- if mkdir "$ABRTDIR"
- then
- echo "Created directory '$ABRTDIR'"
- else
- echo "Error creating directory '$ABRTDIR'"
- exit 12
- fi
-fi
-
-if [ ! -d "$SCRIPTDIR" ]
-then
- if mkdir "$SCRIPTDIR"
- then
- echo "Created directory '$SCRIPTDIR'"
- else
- echo "Error creating directory '$SCRIPTDIR'"
- exit 13
- fi
-fi
-
-if [ ! -d "$WORKDIR" ]
-then
- if mkdir "$WORKDIR"
- then
- echo "Created directory '$WORKDIR'"
- if chown apache "$WORKDIR" && chgrp apache "$WORKDIR"
- then
- echo "$WORKDIR owner and group changed to 'apache'"
- else
- echo "$WORKDIR unable to change owner or group"
- exit 14
- fi
- else
- echo "Error creating directory '$WORKDIR'"
- exit 15
- fi
-fi
-
-if [ ! -d "$REPODIR" ]
-then
- if mkdir "$REPODIR"
- then
- echo "Created directory '$REPODIR'"
- else
- echo "Error creating directory '$REPODIR'"
- exit 16
- fi
-fi
-
-if [ ! -d "$LOGDIR" ]
-then
- if mkdir "$LOGDIR"
- then
- echo "Created directory '$LOGDIR'"
- else
- echo "Error creating directory '$LOGDIR'"
- exit 17
- fi
-fi
-
-if ! gcc -pedantic -Wall -Wextra -Werror -o "/usr/sbin/abrt-retrace-worker" "$SRCDIR/worker.c" \
- || ! chmod u+s "/usr/sbin/abrt-retrace-worker"
-then
- echo "Error compiling abrt-retrace-worker"
- exit 18
-fi
-
-echo "abrt-retrace-worker compiled"
-
-for FILE in $FILES
-do
- if cp "$FILE" "$SCRIPTDIR"
- then
- echo "Installed '$FILE'"
- else
- echo "Error installing '$FILE'"
- exit 19
- fi
-done
-
-if cp "$SRCDIR/retrace.conf" "/etc/abrt/retrace.conf"
-then
- echo "Copied '$SRCDIR/retrace.conf' to '/etc/abrt/retrace.conf'"
-else
- echo "Error copying '$SRCDIR/retrace.conf'"
- exit 23
-fi
-
-if cp "$SRCDIR/retrace.repo" "/etc/yum.repos.d/retrace.repo" \
- && cp "$SRCDIR/retrace-local.repo" "/etc/yum.repos.d/retrace-local.repo"
-then
- echo "Copied '$SRCDIR/retrace.repo' to '/etc/yum.repos.d/retrace.repo'"
- echo "Copied '$SRCDIR/retrace-local.repo' to '/etc/yum.repos.d/retrace-local.repo'"
- echo "Running initial repository download. This will take some time."
- "$SCRIPTDIR/abrt-retrace-reposync" fedora 14 i686
- createrepo "$REPODIR/fedora-14-i686" > /dev/null
- createrepo "$REPODIR/fedora-14-i686-debuginfo" > /dev/null
- "$SCRIPTDIR/abrt-retrace-reposync" fedora 14 x86_64
- createrepo "$REPODIR/fedora-14-x86_64" > /dev/null
- createrepo "$REPODIR/fedora-14-x86_64-debuginfo" > /dev/null
- "$SCRIPTDIR/abrt-retrace-reposync" fedora 15 i686
-# createrepo "$REPODIR/fedora-15-i686"
-# createrepo "$REPODIR/fedora-15-i686-debuginfo"
- "$SCRIPTDIR/abrt-retrace-reposync" fedora 15 x86_64
-# createrepo "$REPODIR/fedora-15-x86_64"
-# createrepo "$REPODIR/fedora-15-x86_64-debuginfo"
-else
- echo "Error copying '$SRCDIR/retrace.repo' or '$SRCDIR/retrace-local.repo'"
- exit 24
-fi
-
-if cp "$SRCDIR/retrace_httpd.conf" "/etc/httpd/conf.d/retrace.conf"
-then
- echo "Copied '$SRCDIR/retrace_httpd.conf' to '/etc/httpd/conf.d/retrace.conf'"
- service httpd restart
-else
- echo "Error copying '$SRCDIR/retrace_httpd.conf'"
- exit 25
-fi
-
-echo
-echo "Retrace Server setup OK."
-echo "You should set up cron to periodically synchronize local repositories. The recommended configuration is:"
-echo "0 0,8,16 * * * $SCRIPTDIR/abrt-retrace-reposync fedora 14 i686"
-echo "0 2,10,18 * * * $SCRIPTDIR/abrt-retrace-reposync fedora 14 x86_64"
-echo "0 4,12,20 * * * $SCRIPTDIR/abrt-retrace-reposync fedora 15 i686"
-echo "0 6,14,22 * * * $SCRIPTDIR/abrt-retrace-reposync fedora 15 x86_64"
diff --git a/src/retrace/log.wsgi b/src/retrace/log.wsgi
deleted file mode 100644
index 5bdc4ffb..00000000
--- a/src/retrace/log.wsgi
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python
-
-from retrace import *
-
-def application(environ, start_response):
- request = Request(environ)
-
- match = URL_PARSER.match(request.script_name)
- if not match:
- return response(start_response, "404 Not Found",
- "Invalid URL")
-
- taskdir = "%s/%s" % (CONFIG["SaveDir"], match.group(1))
-
- if not os.path.isdir(taskdir):
- return response(start_response, "404 Not Found",
- "There is no such task")
-
- pwdpath = "%s/password" % taskdir
- try:
- pwdfile = open(pwdpath, "r")
- pwd = pwdfile.read()
- pwdfile.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to verify password")
-
- if not "X-Task-Password" in request.headers or \
- request.headers["X-Task-Password"] != pwd:
- return response(start_response, "403 Forbidden",
- "Invalid password")
-
- logpath = "%s/retrace_log" % taskdir
- if not os.path.isfile(logpath):
- return response(start_response, "404 Not Found",
- "There is no log for the specified task")
-
- try:
- logfile = open(logpath, "r")
- output = logfile.read()
- logfile.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to read log file")
-
- return response(start_response, "200 OK", output)
diff --git a/src/retrace/plugins/Makefile.am b/src/retrace/plugins/Makefile.am
deleted file mode 100644
index 251efbff..00000000
--- a/src/retrace/plugins/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-plugins_PYTHON = __init__.py fedora.py
-pluginsdir = $(datadir)/abrt-retrace/plugins
diff --git a/src/retrace/plugins/__init__.py b/src/retrace/plugins/__init__.py
deleted file mode 100644
index 5c041b0c..00000000
--- a/src/retrace/plugins/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-
-import os
-
-PLUGIN_DIR = "/usr/share/abrt-retrace/plugins"
-PLUGINS = []
-
-try:
- files = os.listdir(PLUGIN_DIR)
-except Exception as ex:
- print "Unable to list directory '%s': %s" % (PLUGIN_DIR, ex)
- raise ImportError, ex
-
-for filename in files:
- if not filename.startswith("_") and filename.endswith(".py"):
- pluginname = filename.replace(".py", "")
- try:
- this = __import__("%s.%s" % (__name__, pluginname))
- except:
- continue
-
- plugin = this.__getattribute__(pluginname)
- if plugin.__dict__.has_key("distribution") and plugin.__dict__.has_key("repos"):
- PLUGINS.append(plugin)
diff --git a/src/retrace/plugins/fedora.py b/src/retrace/plugins/fedora.py
deleted file mode 100644
index 6bf2f7b9..00000000
--- a/src/retrace/plugins/fedora.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python
-
-import re
-
-distribution = "fedora"
-abrtparser = re.compile("^Fedora release ([0-9]+) \(([^\)]+)\)$")
-guessparser = re.compile("\.fc([0-9]+)")
-repos = [
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/releases/$VER/Everything/$ARCH/os/Packages/*",
- "rsync://ftp.sh.cvut.cz/fedora/linux/development/$VER/$ARCH/os/Packages/*",
- ],
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/releases/$VER/Everything/$ARCH/debug/*",
- "rsync://ftp.sh.cvut.cz/fedora/linux/development/$VER/$ARCH/debug/*",
- ],
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/updates/$VER/$ARCH/*",
- ],
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/updates/$VER/$ARCH/debug/*",
- ],
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/updates/testing/$VER/$ARCH/*",
- ],
- [
- "rsync://ftp.sh.cvut.cz/fedora/linux/updates/testing/$VER/$ARCH/debug/*",
- ],
-]
diff --git a/src/retrace/retrace.conf b/src/retrace/retrace.conf
deleted file mode 100644
index e97e7cfc..00000000
--- a/src/retrace/retrace.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-[retrace]
-# Maximum tasks running at one moment
-MaxParallelTasks = 5
-
-# Maximum size of archive uploaded by user (MB)
-MaxPackedSize = 50
-
-# Maximum size of archive contents (MB)
-MaxUnpackedSize = 1024
-
-# Minimal storage left on WorkDir FS after unpacking archive (MB)
-MinStorageLeft = 1024
-
-# Delete old tasks after (hours)
-DeleteTaskAfter = 120
-
-# SQLite statistics DB filename
-DBFile = stats.db
-
-# Log directory
-LogDir = /var/log/abrt-retrace
-
-# Local repos directory
-RepoDir = /var/cache/abrt-retrace
-
-# Directory where the crashes and results are saved
-SaveDir = /var/spool/abrt-retrace
-
-# Whether to use explicit working directory, otherwise SaveDir is used
-UseWorkDir = 0
-
-# Working directory
-WorkDir = /tmp/abrt-retrace
diff --git a/src/retrace/retrace.py b/src/retrace/retrace.py
deleted file mode 100644
index 56bfd46e..00000000
--- a/src/retrace/retrace.py
+++ /dev/null
@@ -1,412 +0,0 @@
-#!/usr/bin/python
-
-import os
-import re
-import ConfigParser
-import random
-import sqlite3
-from webob import Request
-from subprocess import *
-
-REQUIRED_FILES = ["coredump", "executable", "package"]
-
-DF_BIN = "/bin/df"
-DU_BIN = "/usr/bin/du"
-GZIP_BIN = "/usr/bin/gzip"
-TAR_BIN = "/bin/tar"
-XZ_BIN = "/usr/bin/xz"
-
-TASKID_PARSER = re.compile("^.*/([0-9]+)/*$")
-PACKAGE_PARSER = re.compile("^(.+)-([0-9]+(\.[0-9]+)*-[0-9]+)\.([^-]+)$")
-DF_OUTPUT_PARSER = re.compile("^([^ ^\t]*)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+%)[ \t]+(.*)$")
-DU_OUTPUT_PARSER = re.compile("^([0-9]+)")
-URL_PARSER = re.compile("^/([0-9]+)/?")
-WORKER_RUNNING_PARSER = re.compile("^[ \t]*([0-9]+)[ \t]+[0-9]+[ \t]+([^ ^\t]+)[ \t]+.*abrt-retrace-worker ([0-9]+)$")
-
-HANDLE_ARCHIVE = {
- "application/x-xz-compressed-tar": {
- "unpack": [TAR_BIN, "xJf"],
- "size": ([XZ_BIN, "--list", "--robot"], re.compile("^totals[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+([0-9]+).*")),
- },
-
- "application/x-gzip": {
- "unpack": [TAR_BIN, "xzf"],
- "size": ([GZIP_BIN, "--list"], re.compile("^[^0-9]*[0-9]+[^0-9]+([0-9]+).*$")),
- },
-
- "application/x-tar": {
- "unpack": [TAR_BIN, "xf"],
- "size": (["ls", "-l"], re.compile("^[ \t]*[^ ^\t]+[ \t]+[^ ^\t]+[ \t]+[^ ^\t]+[ \t]+[^ ^\t]+[ \t]+([0-9]+).*$")),
- },
-}
-
-TASKPASS_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-CONFIG_FILE = "/etc/abrt/retrace.conf"
-CONFIG = {
- "TaskIdLength": 9,
- "TaskPassLength": 32,
- "MaxParallelTasks": 10,
- "MaxPackedSize": 30,
- "MaxUnpackedSize": 600,
- "MinStorageLeft": 10240,
- "DeleteTaskAfter": 120,
- "LogDir": "/var/log/abrt-retrace",
- "RepoDir": "/var/cache/abrt-retrace",
- "SaveDir": "/var/spool/abrt-retrace",
- "WorkDir": "/tmp/abrt-retrace",
- "UseWorkDir": False,
- "DBFile": "stats.db",
-}
-
-STATUS_ANALYZE, STATUS_INIT, STATUS_BACKTRACE, STATUS_CLEANUP, \
-STATUS_STATS, STATUS_FINISHING, STATUS_SUCCESS, STATUS_FAIL = xrange(8)
-
-STATUS = [
- "Analyzing crash data",
- "Initializing virtual root",
- "Generating backtrace",
- "Cleaning up virtual root",
- "Saving crash statistics",
- "Finishing task",
- "Retrace job finished successfully",
- "Retrace job failed",
-]
-
-
-def lock(lockfile):
- try:
- if not os.path.isfile(lockfile):
- open(lockfile, "w").close()
- except:
- return False
-
- return True
-
-def unlock(lockfile):
- try:
- if os.path.getsize(lockfile) == 0:
- os.unlink(lockfile)
- except:
- return False
-
- return True
-
-def read_config():
- parser = ConfigParser.ConfigParser()
- parser.read(CONFIG_FILE)
- for key in CONFIG.keys():
- vartype = type(CONFIG[key])
- if vartype is int:
- get = parser.getint
- elif vartype is bool:
- get = parser.getboolean
- elif vartype is float:
- get = parser.getfloat
- else:
- get = parser.get
-
- try:
- CONFIG[key] = get("retrace", key)
- except:
- pass
-
-def free_space(path):
- pipe = Popen([DF_BIN, path], stdout=PIPE).stdout
- for line in pipe.readlines():
- match = DF_OUTPUT_PARSER.match(line)
- if match:
- pipe.close()
- return 1024 * int(match.group(4))
-
- pipe.close()
- return None
-
-def dir_size(path):
- pipe = Popen([DU_BIN, "-s", path], stdout=PIPE).stdout
- for line in pipe.readlines():
- match = DU_OUTPUT_PARSER.match(line)
- if match:
- pipe.close()
- return 1024 * int(match.group(1))
-
- pipe.close()
- return 0
-
-def unpacked_size(archive, mime):
- command, parser = HANDLE_ARCHIVE[mime]["size"]
- pipe = Popen(command + [archive], stdout=PIPE).stdout
- for line in pipe.readlines():
- match = parser.match(line)
- if match:
- pipe.close()
- return int(match.group(1))
-
- pipe.close()
- return None
-
-def guess_arch(coredump_path):
- pipe = Popen(["file", coredump_path], stdout=PIPE).stdout
- output = pipe.read()
- pipe.close()
-
- if "x86-64" in output:
- return "x86_64"
-
- if "80386" in output:
- return "i386"
-
- return None
-
-def guess_release(package):
- for plugin in PLUGINS:
- match = plugin.guessparser.search(package)
- if match:
- return plugin.distribution, match.group(1)
-
- return None, None
-
-def run_gdb(savedir):
- try:
- exec_file = open("%s/crash/executable" % savedir, "r")
- executable = exec_file.read().replace("'", "").replace("\"", "")
- exec_file.close()
- except:
- return ""
-
- mockr = "../../%s/mock" % savedir
-
- chmod = Popen(["mock", "shell", "-r", mockr, "--",
- "/bin/chmod", "777", executable])
- if chmod.wait() != 0:
- return ""
-
- pipe = Popen(["mock", "shell", "-r", mockr, "--",
- "su", "mockbuild", "-c",
- "\" gdb -batch"
- " -ex 'file %s'"
- " -ex 'core-file /var/spool/abrt/crash/coredump'"
- " -ex 'thread apply all backtrace 2048 full'"
- " -ex 'info sharedlib'"
- " -ex 'print (char*)__abort_msg'"
- " -ex 'print (char*)__glib_assert_msg'"
- " -ex 'info registers'"
- " -ex 'disassemble' \"" % executable,
- # redirect GDB's stderr, ignore mock's stderr
- "2>&1"], stdout=PIPE).stdout
-
- backtrace = pipe.read()
- pipe.close()
-
- return backtrace
-
-def gen_task_password(taskdir):
- generator = random.SystemRandom()
- taskpass = ""
- for j in xrange(CONFIG["TaskPassLength"]):
- taskpass += generator.choice(TASKPASS_ALPHABET)
-
- try:
- passfile = open("%s/password" % taskdir, "w")
- passfile.write(taskpass)
- passfile.close()
- except:
- return None
-
- return taskpass
-
-def get_task_est_time(taskdir):
- return 180
-
-def new_task():
- i = 0
- newdir = CONFIG["SaveDir"]
- while os.path.exists(newdir) and i < 50:
- i += 1
- taskid = random.randint(pow(10, CONFIG["TaskIdLength"] - 1), pow(10, CONFIG["TaskIdLength"]) - 1)
- newdir = "%s/%d" % (CONFIG["SaveDir"], taskid)
-
- try:
- os.mkdir(newdir)
- taskpass = gen_task_password(newdir)
- if not taskpass:
- Popen(["rm", "-rf", newdir])
- raise Exception
-
- return taskid, taskpass, newdir
- except:
- return None, None, None
-
-def unpack(archive, mime):
- pipe = Popen(HANDLE_ARCHIVE[mime]["unpack"] + [archive])
- pipe.wait()
- return pipe.returncode
-
-def response(start_response, status, body="", extra_headers=[]):
- start_response(status, [("Content-Type", "text/plain"), ("Content-Length", "%d" % len(body))] + extra_headers)
- return [body]
-
-def get_active_tasks():
- tasks = []
- if CONFIG["UseWorkDir"]:
- tasksdir = CONFIG["WorkDir"]
- else:
- tasksdir = CONFIG["SaveDir"]
-
- for filename in os.listdir(tasksdir):
- if len(filename) != CONFIG["TaskIdLength"]:
- continue
-
- try:
- taskid = int(filename)
- except:
- continue
-
- path = "%s/%s" % (tasksdir, filename)
- if os.path.isdir(path) and not os.path.isfile("%s/retrace_log" % path):
- tasks.append(taskid)
-
- return tasks
-
-def run_ps():
- pipe = Popen(["ps", "-eo", "pid,ppid,etime,cmd"], stdout=PIPE).stdout
- lines = pipe.readlines()
- pipe.close()
-
- return lines
-
-def get_running_tasks(ps_output=None):
- if not ps_output:
- ps_output = run_ps()
-
- result = []
-
- for line in ps_output:
- match = WORKER_RUNNING_PARSER.match(line)
- if match:
- result.append((int(match.group(1)), int(match.group(3)), match.group(2)))
-
- return result
-
-def get_process_tree(pid, ps_output):
- result = [pid]
-
- parser = re.compile("^([0-9]+)[ \t]+(%d).*$" % pid)
-
- for line in ps_output:
- match = parser.match(line)
- if match:
- pid = int(match.group(1))
- result.extend(get_process_tree(pid, ps_output))
-
- return result
-
-def kill_process_and_childs(process_id, ps_output=None):
- result = True
-
- if not ps_output:
- ps_output = run_ps()
-
- for pid in get_process_tree(process_id, ps_output):
- try:
- os.kill(pid, 9)
- except OSError, ex:
- result = False
-
- return result
-
-def cleanup_task(taskid, gc=True):
- null = open("/dev/null", "w")
-
- savedir = "%s/%d" % (CONFIG["SaveDir"], taskid)
- if os.path.isfile("%s/mock.cfg" % savedir):
- call(["mock", "-r", "../../%s/mock" % savedir, "--scrub=all"],
- stdout=null, stderr=null)
-
- call(["rm", "-rf", "%s/crash" % savedir, "%s/mock.cfg" % savedir],
- stdout=null, stderr=null)
-
- rawlog = "%s/log" % savedir
- newlog = "%s/retrace_log" % savedir
- if os.path.isfile(rawlog):
- try:
- os.rename(rawlog, newlog)
- except:
- pass
-
- if gc:
- try:
- log = open(newlog, "a")
- log.write("Killed by garbage collector\n")
- log.close()
- except:
- pass
-
- null.close()
-
-def init_crashstats_db():
- try:
- con = sqlite3.connect("%s/%s" % (CONFIG["SaveDir"], CONFIG["DBFile"]))
- query = con.cursor()
- query.execute("""
- CREATE TABLE IF NOT EXISTS
- retracestats(
- taskid INT NOT NULL,
- package VARCHAR(255) NOT NULL,
- version VARCHAR(16) NOT NULL,
- release VARCHAR(16) NOT NULL,
- arch VARCHAR(8) NOT NULL,
- starttime INT NOT NULL,
- duration INT NOT NULL,
- prerunning TINYINT NOT NULL,
- postrunning TINYINT NOT NULL,
- chrootsize BIGINT NOT NULL
- )
- """)
- con.commit()
- con.close()
-
- return True
- except:
- return False
-
-def save_crashstats(crashstats):
- try:
- con = sqlite3.connect("%s/%s" % (CONFIG["SaveDir"], CONFIG["DBFile"]))
- query = con.cursor()
- query.execute("""
- INSERT INTO retracestats(taskid, package, version, release, arch,
- starttime, duration, prerunning, postrunning, chrootsize)
- VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (crashstats["taskid"], crashstats["package"], crashstats["version"],
- crashstats["release"], crashstats["arch"], crashstats["starttime"],
- crashstats["duration"], crashstats["prerunning"],
- crashstats["postrunning"], crashstats["chrootsize"])
- )
- con.commit()
- con.close()
-
- return True
- except:
- return False
-
-class logger():
- def __init__(self, taskid):
- "Starts logging into savedir."
- self._logfile = open("%s/%s/log" % (CONFIG["SaveDir"], taskid), "w")
-
- def write(self, msg):
- "Writes msg into log file."
- if not self._logfile.closed:
- self._logfile.write(msg)
- self._logfile.flush()
-
- def close(self):
- "Finishes logging and renames file to retrace_log."
- if not self._logfile.closed:
- self._logfile.close()
- os.rename(self._logfile.name, self._logfile.name.replace("/log", "/retrace_log"))
-
-### read config on import ###
-read_config()
diff --git a/src/retrace/retrace.repo b/src/retrace/retrace.repo
deleted file mode 100644
index ccc224be..00000000
--- a/src/retrace/retrace.repo
+++ /dev/null
@@ -1,23 +0,0 @@
-[retrace-fedora-14-i386]
-name=Fedora 14 - i386
-failovermethod=priority
-baseurl=file:///var/cache/abrt-retrace/fedora-14-i386/
-enabled=0
-
-[retrace-fedora-14-x86_64]
-name=Fedora 14 - x86_64
-failovermethod=priority
-baseurl=file:///var/cache/abrt-retrace/fedora-14-x86_64/
-enabled=0
-
-[retrace-fedora-15-i386]
-name=Fedora 15 - i386
-failovermethod=priority
-baseurl=file:///var/cache/abrt-retrace/fedora-15-i386/
-enabled=0
-
-[retrace-fedora-15-x86_64]
-name=Fedora 15 - x86_64
-failovermethod=priority
-baseurl=file:///var/cache/abrt-retrace/fedora-15-x86_64/
-enabled=0
diff --git a/src/retrace/retrace_httpd.conf b/src/retrace/retrace_httpd.conf
deleted file mode 100644
index bd282471..00000000
--- a/src/retrace/retrace_httpd.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-WSGIScriptAliasMatch ^/settings$ /usr/share/abrt-retrace/settings.wsgi
-WSGIScriptAliasMatch ^/create$ /usr/share/abrt-retrace/create.wsgi
-WSGIScriptAliasMatch ^/[0-9]+/?$ /usr/share/abrt-retrace/status.wsgi
-WSGIScriptAliasMatch ^/[0-9]+/log$ /usr/share/abrt-retrace/log.wsgi
-WSGIScriptAliasMatch ^/[0-9]+/backtrace$ /usr/share/abrt-retrace/backtrace.wsgi
diff --git a/src/retrace/settings.wsgi b/src/retrace/settings.wsgi
deleted file mode 100644
index 9c906c49..00000000
--- a/src/retrace/settings.wsgi
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-
-from retrace import *
-
-def application(environ, start_response):
- formats = ""
- for format in HANDLE_ARCHIVE.keys():
- formats += " %s" % format
-
- output = [
- "running_tasks %d" % len(get_active_tasks()),
- "max_running_tasks %d" % CONFIG["MaxParallelTasks"],
- "max_packed_size %d" % CONFIG["MaxPackedSize"],
- "max_unpacked_size %d" % CONFIG["MaxUnpackedSize"],
- "supported_formats%s" % formats,
- ]
-
- return response(start_response, "200 OK", "\n".join(output))
diff --git a/src/retrace/status.wsgi b/src/retrace/status.wsgi
deleted file mode 100644
index 50334772..00000000
--- a/src/retrace/status.wsgi
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python
-
-from retrace import *
-
-def application(environ, start_response):
- request = Request(environ)
-
- match = URL_PARSER.match(request.script_name)
- if not match:
- return response(start_response, "404 Not Found",
- "Invalid URL")
-
- taskdir = "%s/%s" % (CONFIG["SaveDir"], match.group(1))
-
- if not os.path.isdir(taskdir):
- return response(start_response, "404 Not Found",
- "There is no such task")
-
- pwdpath = "%s/password" % taskdir
- try:
- pwdfile = open(pwdpath, "r")
- pwd = pwdfile.read()
- pwdfile.close()
- except:
- return response(start_response, "500 Internal Server Error",
- "Unable to verify password")
-
- if not "X-Task-Password" in request.headers or \
- request.headers["X-Task-Password"] != pwd:
- return response(start_response, "403 Forbidden",
- "Invalid password")
-
- status = "PENDING"
- if os.path.isfile("%s/retrace_log" % taskdir):
- if os.path.isfile("%s/retrace_backtrace" % taskdir):
- status = "FINISHED_SUCCESS"
- else:
- status = "FINISHED_FAILURE"
-
- statusmsg = status
- try:
- statusfile = open("%s/status" % taskdir, "r")
- statusmsg = statusfile.read()
- statusfile.close()
- except:
- pass
-
- return response(start_response, "200 OK",
- statusmsg, [("X-Task-Status", status)])
diff --git a/src/retrace/worker.c b/src/retrace/worker.c
deleted file mode 100644
index a49f74c3..00000000
--- a/src/retrace/worker.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <stdio.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-/*
- Launches Retrace Server worker (worker.py) with root permissions.
- Binary needs to be owned by root and needs to set SUID bit.
-*/
-
-int main(int argc, char **argv)
-{
- char command[256];
- FILE *pipe;
- int i;
- struct passwd *apache_user;
- const char *apache_username = "apache";
- pid_t pid;
-
- if (argc != 2)
- {
- fprintf(stderr, "Usage: %s task_id\n", argv[0]);
- return 1;
- }
-
- if (setuid(0) != 0)
- {
- fprintf(stderr, "You must run %s with root permissions.\n", argv[0]);
- return 2;
- }
-
- for (i = 0; argv[1][i]; ++i)
- if (!isdigit(argv[1][i]))
- {
- fputs("Task ID may only contain digits.", stderr);
- return 3;
- }
-
- apache_user = getpwnam(apache_username);
- if (!apache_user)
- {
- fprintf(stderr, "User \"%s\" not found.\n", apache_username);
- return 4;
- }
-
- sprintf(command, "%d", apache_user->pw_uid);
-
- setenv("SUDO_USER", apache_username, 1);
- setenv("SUDO_UID", command, 1);
- /* required by mock to be able to write into result directory */
- setenv("SUDO_GID", "0", 1);
-
- /* fork and launch worker.py */
- pid = fork();
-
- if (pid < 0)
- {
- fputs("Unable to fork.", stderr);
- return 6;
- }
-
- /* parent - exit */
- if (pid > 0)
- return 0;
-
- /* child */
- sprintf(command, "/usr/bin/python /usr/share/abrt-retrace/worker.py \"%s\"", argv[1]);
- pipe = popen(command, "r");
- if (pipe == NULL)
- {
- fputs("Unable to run 'worker.py'.", stderr);
- return 5;
- }
-
- return pclose(pipe) >> 8;
-}
diff --git a/src/retrace/worker.py b/src/retrace/worker.py
deleted file mode 100755
index 24defa66..00000000
--- a/src/retrace/worker.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import time
-from retrace import *
-
-sys.path = ["/usr/share/abrt-retrace/"] + sys.path
-from plugins import *
-
-LOG = None
-taskid = None
-
-def set_status(statusid):
- "Sets status for the task"
- if not LOG or not taskid:
- return
-
- filepath = "%s/%s/status" % (CONFIG["SaveDir"], taskid)
- try:
- statusfile = open(filepath, "w")
- statusfile.write(STATUS[statusid])
- statusfile.close()
- except:
- pass
-
- LOG.write("%s " % STATUS[statusid])
-
-def fail(exitcode):
- "Kills script with given exitcode"
- set_status(STATUS_FAIL)
- LOG.close()
- cleanup_task(int(taskid), False)
- sys.exit(exitcode)
-
-def retrace_run(errorcode, cmd):
- "Runs cmd using subprocess.Popen and kills script with errorcode on failure"
- try:
- process = Popen(cmd, stdout=PIPE, stderr=STDOUT)
- process.wait()
- output = process.stdout.read()
- process.stdout.close()
- except Exception as ex:
- process = None
- output = "An unhandled exception occured: %s" % ex
-
- if not process or process.returncode != 0:
- LOG.write("Error %d:\n=== OUTPUT ===\n%s\n" % (errorcode, output))
- fail(errorcode)
-
- return output
-
-if __name__ == "__main__":
- starttime = time.time()
-
- if len(sys.argv) != 2:
- sys.stderr.write("Usage: %s task_id\n" % sys.argv[0])
- sys.exit(11)
-
- taskid = sys.argv[1]
- try:
- taskid_int = int(sys.argv[1])
- except:
- sys.stderr.write("Task ID may only contain digits.\n")
- sys.exit(12)
-
- savedir = workdir = "%s/%s" % (CONFIG["SaveDir"], taskid)
-
- if CONFIG["UseWorkDir"]:
- workdir = "%s/%s" % (CONFIG["WorkDir"], taskid)
-
- if not os.path.isdir(savedir):
- sys.stderr.write("Task '%s' does not exist.\n" % taskid)
- sys.exit(13)
-
- try:
- LOG = logger(taskid)
- except Exception as ex:
- sys.stderr.write("Unable to start logging for task '%s': %s.\n" % (taskid, ex))
- sys.exit(14)
-
- set_status(STATUS_ANALYZE)
-
- # check the crash directory for required files
- for required_file in REQUIRED_FILES:
- if not os.path.isfile("%s/crash/%s" % (savedir, required_file)):
- LOG.write("Crash directory does not contain required file '%s'.\n" % required_file)
- fail(15)
-
- # read architecture from coredump
- arch = guess_arch("%s/crash/coredump" % savedir)
-
- if not arch:
- LOG.write("Unable to read architecture from 'coredump' file.\n")
- fail(16)
-
- # read package file
- try:
- package_file = open("%s/crash/package" % savedir, "r")
- crash_package = package_file.read()
- package_file.close()
- except Exception as ex:
- LOG.write("Unable to read crash package from 'package' file: %s.\n" % ex)
- fail(17)
-
- # read release, distribution and version from release file
- release_path = "%s/crash/os_release" % savedir
- if not os.path.isfile(release_path):
- release_path = "%s/crash/release" % savedir
-
- try:
- release_file = open(release_path, "r")
- release = release_file.read()
- release_file.close()
-
- version = distribution = None
- for plugin in PLUGINS:
- match = plugin.abrtparser.match(release)
- if match:
- version = match.group(1)
- distribution = plugin.distribution
- break
-
- if not version or not distribution:
- raise Exception, "Release '%s' is not supported.\n" % release
-
- except Exception as ex:
- LOG.write("Unable to read distribution and version from 'release' file: %s.\n" % ex)
- LOG.write("Trying to guess distribution and version... ")
- distribution, version = guess_release(crash_package)
- if distribution and version:
- LOG.write("%s-%s\n" % (distribution, version))
- else:
- LOG.write("Failure\n")
- fail(18)
-
- # read package file
- try:
- package_file = open("%s/crash/package" % savedir, "r")
- crash_package = package_file.read()
- package_file.close()
- except Exception as ex:
- LOG.write("Unable to read crash package from 'package' file: %s.\n" % ex)
- fail(19)
-
- packages = crash_package
-
- # read required packages from coredump
- try:
- # ToDo: deal with not found build-ids
- pipe = Popen(["coredump2packages", "%s/crash/coredump" % savedir,
- "--repos=retrace-%s-%s-%s*" % (distribution, version, arch)],
- stdout=PIPE).stdout
- section = 0
- crash_package_or_component = None
- for line in pipe.readlines():
- if line == "\n":
- section += 1
- continue
- elif 0 == section:
- crash_package_or_component = line.strip()
- elif 1 == section:
- packages += " %s" % line.rstrip("\n")
- elif 2 == section:
- # Missing build ids
- pass
- pipe.close()
- except Exception as ex:
- LOG.write("Unable to obtain packages from 'coredump' file: %s.\n" % ex)
- fail(20)
-
- # create mock config file
- try:
- mockcfg = open("%s/mock.cfg" % savedir, "w")
- mockcfg.write("config_opts['root'] = '%s'\n" % taskid)
- mockcfg.write("config_opts['target_arch'] = '%s'\n" % arch)
- mockcfg.write("config_opts['chroot_setup_cmd'] = '--skip-broken install %s shadow-utils gdb rpm'\n" % packages)
- mockcfg.write("config_opts['plugin_conf']['ccache_enable'] = False\n")
- mockcfg.write("config_opts['plugin_conf']['yum_cache_enable'] = False\n")
- mockcfg.write("config_opts['plugin_conf']['root_cache_enable'] = False\n")
- mockcfg.write("\n")
- mockcfg.write("config_opts['yum.conf'] = \"\"\"\n")
- mockcfg.write("[main]\n")
- mockcfg.write("cachedir=/var/cache/yum\n")
- mockcfg.write("debuglevel=1\n")
- mockcfg.write("reposdir=/dev/null\n")
- mockcfg.write("logfile=/var/log/yum.log\n")
- mockcfg.write("retries=20\n")
- mockcfg.write("obsoletes=1\n")
- mockcfg.write("gpgcheck=0\n")
- mockcfg.write("assumeyes=1\n")
- mockcfg.write("syslog_ident=mock\n")
- mockcfg.write("syslog_device=\n")
- mockcfg.write("\n")
- mockcfg.write("#repos\n")
- mockcfg.write("\n")
- mockcfg.write("[%s]\n" % distribution)
- mockcfg.write("name=%s\n" % distribution)
- mockcfg.write("baseurl=file://%s/%s-%s-%s/\n" % (CONFIG["RepoDir"], distribution, version, arch))
- mockcfg.write("failovermethod=priority\n")
- mockcfg.write("\"\"\"\n")
- mockcfg.close()
- except Exception as ex:
- LOG.write("Unable to create mock config file: %s.\n" % ex)
- fail(21)
-
- LOG.write("OK\n")
-
- # get count of tasks running before starting
- prerunning = len(get_active_tasks()) - 1
-
- # run retrace
- mockr = "../../%s/mock" % savedir
-
- set_status(STATUS_INIT)
-
- retrace_run(25, ["mock", "init", "-r", mockr])
- retrace_run(26, ["mock", "-r", mockr, "--copyin", "%s/crash" % savedir, "/var/spool/abrt/crash"])
- retrace_run(27, ["mock", "-r", mockr, "shell", "--", "chgrp", "-R", "mockbuild", "/var/spool/abrt/crash"])
-
- LOG.write("OK\n")
-
- # generate backtrace
- set_status(STATUS_BACKTRACE)
-
- backtrace = run_gdb(savedir)
-
- if not backtrace:
- LOG.write("Error\n")
- fail(29)
-
- try:
- bt_file = open("%s/backtrace" % savedir, "w")
- bt_file.write(backtrace)
- bt_file.close()
- except Exception as ex:
- LOG.write("Error: %s.\n" % ex)
- fail(30)
-
- LOG.write("OK\n")
-
- chroot_size = dir_size("%s/chroot/root" % workdir)
-
- # clean up temporary data
- set_status(STATUS_CLEANUP)
-
- retrace_run(31, ["mock", "-r", mockr, "--scrub=all"])
- retrace_run(32, ["rm", "-rf", "%s/mock.cfg" % savedir, "%s/crash" % savedir])
-
- # ignore error: workdir = savedir => workdir is not empty
- if CONFIG["UseWorkDir"]:
- try:
- os.rmdir(workdir)
- except:
- pass
-
- LOG.write("OK\n")
-
- # save crash statistics
- set_status(STATUS_STATS)
-
- duration = int(time.time() - starttime)
-
- package_match = PACKAGE_PARSER.match(crash_package)
- if not package_match:
- package = crash_package
- version = "unknown"
- release = "unknown"
- else:
- package = package_match.group(1)
- version = package_match.group(2)
- release = package_match.group(4)
-
- crashstats = {
- "taskid": taskid_int,
- "package": package,
- "version": version,
- "release": release,
- "arch": arch,
- "starttime": int(starttime),
- "duration": duration,
- "prerunning": prerunning,
- "postrunning": len(get_active_tasks()) - 1,
- "chrootsize": chroot_size
- }
-
- if not init_crashstats_db() or not save_crashstats(crashstats):
- LOG.write("Error: %s\n" % crashstats)
- else:
- LOG.write("OK\n")
-
- # publish backtrace and log
- set_status(STATUS_FINISHING)
-
- try:
- os.rename("%s/backtrace" % savedir, "%s/retrace_backtrace" % savedir)
- except Exception as ex:
- LOG.write("Error: %s\n" % ex)
- fail(35)
-
- LOG.write("OK\n")
- LOG.write("Retrace took %d seconds.\n" % duration)
-
- set_status(STATUS_SUCCESS)
- LOG.write("\n")
- LOG.close()