Re-launch a job if the worker fails to run it

If a job is complete with no build result, it has failed to
run to completion.  In this case, discard the previous build
and launch a replacement (in the next run of the queue processor).

Change-Id: Ib8fc245a5becb1e7deb13f1ea0721fdb6ceb9f6f
diff --git a/zuul/model.py b/zuul/model.py
index 5ee0554..4823541 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -162,7 +162,9 @@
         return self.isHoldingFollowingChanges(item.item_ahead)
 
     def setResult(self, item, build):
-        if build.result != 'SUCCESS':
+        if build.retry:
+            item.removeBuild(build)
+        elif build.result != 'SUCCESS':
             # Get a JobTree from a Job so we can find only its dependent jobs
             root = self.getJobTree(item.change.project)
             tree = root.getJobTreeForJob(build.job)
@@ -537,6 +539,7 @@
         self.estimated_time = None
         self.pipeline = None
         self.canceled = False
+        self.retry = False
         self.parameters = {}
 
     def __repr__(self):
@@ -572,6 +575,9 @@
         self.builds[build.job.name] = build
         build.build_set = self
 
+    def removeBuild(self, build):
+        del self.builds[build.job.name]
+
     def getBuild(self, job_name):
         return self.builds.get(job_name)
 
@@ -609,6 +615,9 @@
         self.current_build_set.addBuild(build)
         build.pipeline = self.pipeline
 
+    def removeBuild(self, build):
+        self.current_build_set.removeBuild(build)
+
     def setReportedResult(self, result):
         self.current_build_set.result = result