From dbcc33edaec8eb6e5590e7eb29390fc58acbf6c6 Mon Sep 17 00:00:00 2001 From: Lubos Kocman Date: Mon, 17 Oct 2016 13:21:37 +0200 Subject: [PATCH 1/4] remove log.debug for unrelated messages (too spammy) Signed-off-by: Lubos Kocman Signed-off-by: Nils Philippsen --- rida/messaging.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/rida/messaging.py b/rida/messaging.py index 44b2a859..51e16175 100644 --- a/rida/messaging.py +++ b/rida/messaging.py @@ -111,8 +111,6 @@ class BaseMessage(object): if msg_obj: return msg_obj - log.debug('Skipping unrecognized message with the topic "{0}"' - .format(topic)) return None From 614100163ddb5e800567cc75f29bfde76239d8f0 Mon Sep 17 00:00:00 2001 From: Lubos Kocman Date: Mon, 17 Oct 2016 13:21:55 +0200 Subject: [PATCH 2/4] Transition module build to failed if PDC wasn't updated This allows resume... otherwise we're stuck in building. Signed-off-by: Lubos Kocman Signed-off-by: Nils Philippsen --- rida/scheduler/handlers/modules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rida/scheduler/handlers/modules.py b/rida/scheduler/handlers/modules.py index f7917a22..41e073a7 100644 --- a/rida/scheduler/handlers/modules.py +++ b/rida/scheduler/handlers/modules.py @@ -106,7 +106,7 @@ def wait(config, session, msg): dependencies, tag = _get_deps_and_tag() except ValueError: log.exception("Failed to get module info from PDC. Max retries reached.") - build.transition(config, state="build") # Wait for the buildroot to be ready.a + build.transition(config, state="failed") session.commit() raise From c15d8f5889cb09c204489de3907c54a3fc85c6ba Mon Sep 17 00:00:00 2001 From: Lubos Kocman Date: Mon, 17 Oct 2016 13:25:42 +0200 Subject: [PATCH 3/4] Use correct rida.log for logging Improved logging for rida/views.py (helps to debug resubmission). Signed-off-by: Lubos Kocman Signed-off-by: Nils Philippsen --- rida/views.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rida/views.py b/rida/views.py index 076dae82..a8e65e9a 100644 --- a/rida/views.py +++ b/rida/views.py @@ -30,11 +30,9 @@ This is the implementation of the orchestrator's public RESTful API. from flask import request, jsonify from flask.views import MethodView import json -import logging import modulemd import os import rida.auth -import rida.logger import rida.scm import shutil import tempfile @@ -85,18 +83,22 @@ class ModuleBuildAPI(MethodView): try: r = json.loads(request.get_data().decode("utf-8")) except: + log.error('Invalid JSON submitted') raise ValidationError('Invalid JSON submitted') if "scmurl" not in r: + log.error('Missing scmurl') raise ValidationError('Missing scmurl') url = r["scmurl"] if not any(url.startswith(prefix) for prefix in conf.scmurls): + log.error('The submitted scmurl is not allowed') raise Unauthorized("The submitted scmurl is not allowed") yaml = "" td = None try: + log.debug('Verifying modulemd') td = tempfile.mkdtemp() scm = rida.scm.SCM(url, conf.scmurls) cod = scm.checkout(td) @@ -117,6 +119,7 @@ class ModuleBuildAPI(MethodView): try: mmd.loads(yaml) except: + log.error('Invalid modulemd') raise UnprocessableEntity('Invalid modulemd') if models.ModuleBuild.query.filter_by(name=mmd.name, @@ -166,6 +169,7 @@ class ModuleBuildAPI(MethodView): full_url = pkg["repository"] + "?#" + pkg["commit"] full_urls.append((pkgname, full_url)) + log.debug("Checking scm urls") # Checks the availability of SCM urls. pool = ThreadPool(10) err_msgs = pool.map(lambda data: "Cannot checkout {}".format(data[0]) @@ -190,8 +194,8 @@ class ModuleBuildAPI(MethodView): module.transition(conf, models.BUILD_STATES["wait"]) db.session.add(module) db.session.commit() - logging.info("%s submitted build of %s-%s-%s", username, mmd.name, - mmd.version, mmd.release) + log.info("%s submitted build of %s-%s-%s", username, mmd.name, + mmd.version, mmd.release) return jsonify(module.json()), 201 From 744af59189e14b70070cda21581f14c8b2371266 Mon Sep 17 00:00:00 2001 From: Lubos Kocman Date: Mon, 17 Oct 2016 13:28:17 +0200 Subject: [PATCH 4/4] Add functionality to resume failed build Resume only failed module build tasks (this should be configurable in the future). Signed-off-by: Lubos Kocman Signed-off-by: Nils Philippsen --- rida/views.py | 67 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/rida/views.py b/rida/views.py index a8e65e9a..54fcc0ab 100644 --- a/rida/views.py +++ b/rida/views.py @@ -122,21 +122,37 @@ class ModuleBuildAPI(MethodView): log.error('Invalid modulemd') raise UnprocessableEntity('Invalid modulemd') - if models.ModuleBuild.query.filter_by(name=mmd.name, + module = models.ModuleBuild.query.filter_by(name=mmd.name, version=mmd.version, - release=mmd.release).first(): - raise Conflict('Module already exists') - - module = models.ModuleBuild.create( - db.session, - conf, - name=mmd.name, - version=mmd.version, - release=mmd.release, - modulemd=yaml, - scmurl=url, - username=username - ) + release=mmd.release).first() + if module: + log.debug('Checking whether module build already exist.') + # TODO: make this configurable, we might want to allow + # resubmitting any stuck build on DEV no matter the state + if module.state not in (models.BUILD_STATES['failed']): + log.error('Module (state=%s) already exists. ' + 'Only new or failed builds are allowed.' + % module.state) + raise Conflict('Module (state=%s) already exists. ' + 'Only new or failed builds are allowed.' + % module.state) + log.debug('Resuming existing module build %r' % module) + module.username = username + module.transition(conf, models.BUILD_STATES["init"]) + log.info("Resumed existing module build in previous state %s" + % module.state) + else: + log.debug('Creating new module build') + module = models.ModuleBuild.create( + db.session, + conf, + name=mmd.name, + version=mmd.version, + release=mmd.release, + modulemd=yaml, + scmurl=url, + username=username + ) # List of (pkg_name, git_url) tuples to be used to check # the availability of git URLs paralelly later. @@ -182,13 +198,22 @@ class ModuleBuildAPI(MethodView): for pkgname, pkg in mmd.components.rpms.packages.items(): full_url = pkg["repository"] + "?#" + pkg["commit"] - build = models.ComponentBuild( - module_id=module.id, - package=pkgname, - format="rpms", - scmurl=full_url, - ) - db.session.add(build) + existing_build = models.ComponentBuild.query.filter_by( + module_id=module.id, package=pkgname).first() + if (existing_build + and existing_build.state != models.BUILD_STATES['done']): + existing_build.state = models.BUILD_STATES['init'] + db.session.add(existing_build) + else: + # XXX: what about components that were present in previous + # builds but are gone now (component reduction)? + build = models.ComponentBuild( + module_id=module.id, + package=pkgname, + format="rpms", + scmurl=full_url, + ) + db.session.add(build) module.modulemd = mmd.dumps() module.transition(conf, models.BUILD_STATES["wait"])