From d0a3e74760f5e7a57365b064602358968800d479 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 04 2024 02:51:42 +0000
Subject: [PATCH 1/5] refuse createrepo tasks if no fs access


---

diff --git a/builder/kojid b/builder/kojid
index fe35e47..780f339 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -5827,7 +5827,14 @@ class CreaterepoTask(BaseTaskHandler):
         toprepodir = self.pathinfo.repo(repo_id, rinfo['tag_name'])
         self.repodir = '%s/%s' % (toprepodir, arch)
         if not os.path.isdir(self.repodir):
-            raise koji.GenericError("Repo directory missing: %s" % self.repodir)
+            top_repos_dir = joinpath(self.options.topdir, "repos")
+            if not os.path.isdir(top_repos_dir):
+                # missing or incorrect mount?
+                # refuse and let another host try
+                self.session.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+            else:
+                # we seem to have fs access, but dir is missing, perhaps a repo_init bug?
+                raise koji.GenericError("Repo directory missing: %s" % self.repodir)
         groupdata = os.path.join(toprepodir, 'groups', 'comps.xml')
         # set up our output dir
         self.outdir = '%s/repo' % self.workdir

From 9bb8753dbb9867f20e49d122dd5e234252331fc2 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 04 2024 02:51:42 +0000
Subject: [PATCH 2/5] in newRepo too


---

diff --git a/builder/kojid b/builder/kojid
index 780f339..a93940c 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -5725,6 +5725,15 @@ class NewRepoTask(BaseTaskHandler):
 
     def handler(self, tag, event=None, src=False, debuginfo=False, separate_src=False):
         tinfo = self.session.getTag(tag, strict=True, event=event)
+
+        # check for fs access before we try calling repoInit
+        top_repos_dir = joinpath(self.options.topdir, "repos")
+        if not os.path.isdir(top_repos_dir):
+            # missing or incorrect mount?
+            # refuse and let another host try
+            self.session.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+
+        # call repoInit
         kwargs = {}
         if event is not None:
             kwargs['event'] = event
@@ -5736,6 +5745,7 @@ class NewRepoTask(BaseTaskHandler):
         if debuginfo or tinfo['extra'].get('with_debuginfo'):
             kwargs['with_debuginfo'] = True
         repo_id, event_id = self.session.host.repoInit(tinfo['id'], task_id=self.id, **kwargs)
+
         path = koji.pathinfo.repo(repo_id, tinfo['name'])
         if not os.path.isdir(path):
             raise koji.GenericError("Repo directory missing: %s" % path)

From 4f68d46915dd5a706ff46bba40624f7f0a9d2f50 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 04 2024 02:51:42 +0000
Subject: [PATCH 3/5] typo


---

diff --git a/builder/kojid b/builder/kojid
index a93940c..a759c12 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -5731,7 +5731,7 @@ class NewRepoTask(BaseTaskHandler):
         if not os.path.isdir(top_repos_dir):
             # missing or incorrect mount?
             # refuse and let another host try
-            self.session.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+            self.session.host.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
 
         # call repoInit
         kwargs = {}
@@ -5841,7 +5841,7 @@ class CreaterepoTask(BaseTaskHandler):
             if not os.path.isdir(top_repos_dir):
                 # missing or incorrect mount?
                 # refuse and let another host try
-                self.session.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+                self.session.host.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
             else:
                 # we seem to have fs access, but dir is missing, perhaps a repo_init bug?
                 raise koji.GenericError("Repo directory missing: %s" % self.repodir)

From f0b2e5a6e987d6f1540f544f17a7f85fa11f8b54 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 04 2024 02:51:42 +0000
Subject: [PATCH 4/5] handle refusal with an exception


---

diff --git a/builder/kojid b/builder/kojid
index a759c12..e1bdb2c 100755
--- a/builder/kojid
+++ b/builder/kojid
@@ -79,7 +79,8 @@ from koji.tasks import (
     BaseTaskHandler,
     MultiPlatformTask,
     ServerExit,
-    ServerRestart
+    ServerRestart,
+    RefuseTask,
 )
 from koji.util import (
     dslice,
@@ -5731,7 +5732,7 @@ class NewRepoTask(BaseTaskHandler):
         if not os.path.isdir(top_repos_dir):
             # missing or incorrect mount?
             # refuse and let another host try
-            self.session.host.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+            raise RefuseTask("No access to repos dir %s" % top_repos_dir)
 
         # call repoInit
         kwargs = {}
@@ -5841,7 +5842,7 @@ class CreaterepoTask(BaseTaskHandler):
             if not os.path.isdir(top_repos_dir):
                 # missing or incorrect mount?
                 # refuse and let another host try
-                self.session.host.refuseTask(self.id, msg="No access to repos dir %s" % top_repos_dir)
+                raise RefuseTask("No access to repos dir %s" % top_repos_dir)
             else:
                 # we seem to have fs access, but dir is missing, perhaps a repo_init bug?
                 raise koji.GenericError("Repo directory missing: %s" % self.repodir)
diff --git a/koji/daemon.py b/koji/daemon.py
index a7a9561..2b8e700 100644
--- a/koji/daemon.py
+++ b/koji/daemon.py
@@ -1504,6 +1504,9 @@ class TaskManager(object):
         except (SystemExit, koji.tasks.ServerExit, KeyboardInterrupt):
             # we do not trap these
             raise
+        except koji.tasks.RefuseTask as refuse:
+            self.session.host.refuseTask(handler.id, msg=str(refuse))
+            return
         except koji.tasks.ServerRestart:
             # freeing this task will allow the pending restart to take effect
             self.session.host.freeTasks([handler.id])
diff --git a/koji/tasks.py b/koji/tasks.py
index ea45a16..cbb279f 100644
--- a/koji/tasks.py
+++ b/koji/tasks.py
@@ -110,6 +110,11 @@ class ServerRestart(Exception):
     pass
 
 
+class RefuseTask(Exception):
+    """Raise to task handler to refuse a task"""
+    pass
+
+
 def parse_task_params(method, params):
     """Parse task params into a dictionary
 

From ec011c3c5b9ce02113ccbe617be9ffb16690cdb8 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 04 2024 02:51:42 +0000
Subject: [PATCH 5/5] log refusal message


---

diff --git a/kojihub/scheduler.py b/kojihub/scheduler.py
index 815b0f1..0c75f8a 100644
--- a/kojihub/scheduler.py
+++ b/kojihub/scheduler.py
@@ -99,7 +99,7 @@ def set_refusal(hostID, taskID, soft=True, by_host=False, msg=''):
     }
     upsert = UpsertProcessor('scheduler_task_refusals', data=data, keys=('task_id', 'host_id'))
     upsert.execute()
-    log_both('Host refused task', task_id=taskID, host_id=hostID)
+    log_both(f'Host refused task: {msg}', task_id=taskID, host_id=hostID)
 
 
 class TaskRefusalsQuery(QueryView):

