Merge "Re-order executor/job classes" into feature/zuulv3
diff --git a/requirements.txt b/requirements.txt
index b718827..4b8be3c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
 
 # pull from master until https://github.com/sigmavirus24/github3.py/pull/671
 # is in a release
--e git+https://github.com/sigmavirus24/github3.py.git@develop#egg=Github3.py
+git+https://github.com/sigmavirus24/github3.py.git@develop#egg=Github3.py
 PyYAML>=3.1.0
 Paste
 WebOb>=1.2.3
@@ -11,7 +11,7 @@
 # release.
 # https://github.com/gitpython-developers/GitPython/pull/682
 # https://github.com/gitpython-developers/GitPython/pull/686
--e git+https://github.com/jeblair/GitPython.git@zuul#egg=GitPython
+git+https://github.com/jeblair/GitPython.git@zuul#egg=GitPython
 python-daemon>=2.0.4,<2.1.0
 extras
 statsd>=1.0.0,<3.0
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index f356030..e5924f8 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -855,8 +855,12 @@
             try:
                 self.nodepool.holdNodeSet(nodeset, autohold_key)
             except Exception:
-                self.log.exception("Unable to process autohold for %s",
+                self.log.exception("Unable to process autohold for %s:",
                                    autohold_key)
+                if autohold_key in self.autohold_requests:
+                    self.log.debug("Removing autohold %s due to exception",
+                                   autohold_key)
+                    del self.autohold_requests[autohold_key]
 
             self.nodepool.returnNodeSet(nodeset)
         except Exception:
diff --git a/zuul/zk.py b/zuul/zk.py
index 2fca749..ede78be 100644
--- a/zuul/zk.py
+++ b/zuul/zk.py
@@ -269,6 +269,9 @@
         for nodeid in nodes:
             node_path = '%s/%s' % (self.NODE_ROOT, nodeid)
             node_data, node_stat = self.client.get(node_path)
+            if not node_data:
+                self.log.warning("Node ID %s has no data", nodeid)
+                continue
             node_data = self._strToDict(node_data)
             if (node_data['state'] == zuul.model.STATE_HOLD and
                     node_data.get('hold_job') == identifier):