diff --git a/module_build_service/scheduler/handlers/modules.py b/module_build_service/scheduler/handlers/modules.py index fedb7fea..a480559b 100644 --- a/module_build_service/scheduler/handlers/modules.py +++ b/module_build_service/scheduler/handlers/modules.py @@ -48,6 +48,7 @@ import six.moves.xmlrpc_client as xmlrpclib import logging import os import time +from datetime import datetime logging.basicConfig(level=logging.DEBUG) @@ -137,7 +138,12 @@ def done(config, session, msg): if not build.scratch: if greenwave is None or greenwave.check_gating(build): build.transition(config, state="ready") - session.commit() + else: + build.state_reason = "Gating failed" + if greenwave.error_occurred: + build.state_reason += " (Error occured while querying Greenwave)" + build.time_modified = datetime.utcnow() + session.commit() build_logs.stop(build) module_build_service.builder.GenericBuilder.clear_cache(build) diff --git a/module_build_service/scheduler/producer.py b/module_build_service/scheduler/producer.py index 0be87dca..82a8df0f 100644 --- a/module_build_service/scheduler/producer.py +++ b/module_build_service/scheduler/producer.py @@ -488,4 +488,11 @@ class MBSProducer(PollingProducer): for build in module_builds: if greenwave.check_gating(build): build.transition(config, state=models.BUILD_STATES["ready"]) - session.commit() + else: + build.state_reason = "Gating failed (MBS will retry in {0} seconds)".format( + conf.polling_interval + ) + if greenwave.error_occurred: + build.state_reason += " (Error occured while querying Greenwave)" + build.time_modified = datetime.utcnow() + session.commit() diff --git a/module_build_service/utils/greenwave.py b/module_build_service/utils/greenwave.py index e5dd2901..8ecd1a6d 100644 --- a/module_build_service/utils/greenwave.py +++ b/module_build_service/utils/greenwave.py @@ -37,9 +37,10 @@ class Greenwave(object): self.url = conf.greenwave_url self._decision_context = conf.greenwave_decision_context if not self.decision_context: - raise GreenwaveError("No Greenwave decision context set") + raise RuntimeError("No Greenwave decision context set") self._subj_type = conf.greenwave_subject_type self._gw_timeout = conf.greenwave_timeout + self.error_occurred = False def _greenwave_query(self, query_type, payload=None): """ @@ -63,7 +64,7 @@ class Greenwave(object): except requests.exceptions.Timeout: raise GreenwaveError("Greenwave request timed out") except Exception as exc: - error_message = "Unspecified greenwave request error" \ + error_message = "Unspecified greenwave request error " \ '(original exception was: "{0}")'.format(str(exc)) log.exception(error_message) raise GreenwaveError(error_message) @@ -156,10 +157,12 @@ class Greenwave(object): :return: True if at least one GW response contains policies_satisfied set to true :rtype: bool """ + self.error_occurred = False try: versions = self.get_product_versions() except GreenwaveError: log.warning('An error occured while getting a product versions') + self.error_occurred = True return False for ver in versions: @@ -168,6 +171,7 @@ class Greenwave(object): # at least one positive result is enough return True except (KeyError, GreenwaveError) as exc: + self.error_occurred = True log.warning('Incorrect greenwave result "%s", ignoring', str(exc)) return False @@ -180,7 +184,7 @@ class Greenwave(object): def url(self, value): value = value.rstrip("/") if not value: - raise GreenwaveError("No Greenwave URL set") + raise RuntimeError("No Greenwave URL set") self._url = value @property @@ -202,6 +206,6 @@ class Greenwave(object): try: greenwave = Greenwave() -except GreenwaveError: +except RuntimeError: log.warning('Greenwave is not configured or configured improperly') greenwave = None diff --git a/tests/test_build/test_build.py b/tests/test_build/test_build.py index 4df321a5..8682745d 100644 --- a/tests/test_build/test_build.py +++ b/tests/test_build/test_build.py @@ -528,6 +528,7 @@ class TestBuild: assert module_build.state == models.BUILD_STATES["ready"] else: assert module_build.state == models.BUILD_STATES["done"] + assert module_build.state_reason == "Gating failed" @patch( "module_build_service.config.Config.check_for_eol", diff --git a/tests/test_scheduler/test_poller.py b/tests/test_scheduler/test_poller.py index 5469a2c8..fae0f7b6 100644 --- a/tests/test_scheduler/test_poller.py +++ b/tests/test_scheduler/test_poller.py @@ -18,6 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import re import pytest from mock import patch from module_build_service import models, conf @@ -666,4 +667,8 @@ class TestPoller: assert set([m.id for m in module]) == {1, 2} else: assert len(module) == 1 - assert set([m.id for m in module]) == {1} + assert module[0].id == 1 + module = models.ModuleBuild.query.filter_by(state=models.BUILD_STATES["done"]).all() + assert len(module) == 1 + assert module[0].id == 2 + assert re.match("Gating failed.*", module[0].state_reason)