diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/retrace/Makefile.am | 31 | ||||
-rwxr-xr-x | src/retrace/abrt-retrace-cleanup | 60 | ||||
-rwxr-xr-x | src/retrace/abrt-retrace-reposync | 118 | ||||
-rw-r--r-- | src/retrace/backtrace.wsgi | 46 | ||||
-rwxr-xr-x | src/retrace/coredump2packages | 293 | ||||
-rw-r--r-- | src/retrace/create.wsgi | 111 | ||||
-rwxr-xr-x | src/retrace/install.sh | 212 | ||||
-rw-r--r-- | src/retrace/log.wsgi | 46 | ||||
-rw-r--r-- | src/retrace/plugins/Makefile.am | 2 | ||||
-rw-r--r-- | src/retrace/plugins/__init__.py | 24 | ||||
-rw-r--r-- | src/retrace/plugins/fedora.py | 29 | ||||
-rw-r--r-- | src/retrace/retrace.conf | 33 | ||||
-rw-r--r-- | src/retrace/retrace.py | 412 | ||||
-rw-r--r-- | src/retrace/retrace.repo | 23 | ||||
-rw-r--r-- | src/retrace/retrace_httpd.conf | 5 | ||||
-rw-r--r-- | src/retrace/settings.wsgi | 18 | ||||
-rw-r--r-- | src/retrace/status.wsgi | 49 | ||||
-rw-r--r-- | src/retrace/worker.c | 77 | ||||
-rwxr-xr-x | src/retrace/worker.py | 305 |
20 files changed, 1 insertions, 1895 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 84499069..3154d5c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = include lib hooks btparser daemon applet gui-gtk cli plugins retrace +SUBDIRS = include lib hooks btparser daemon applet gui-gtk cli plugins 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() |