Merge "Make isJobRegistered for gearman optional"
diff --git a/zuul/ansible/library/zuul_runner.py b/zuul/ansible/library/zuul_runner.py
index f490162..20b5600 100644
--- a/zuul/ansible/library/zuul_runner.py
+++ b/zuul/ansible/library/zuul_runner.py
@@ -18,6 +18,7 @@
 import datetime
 import getpass
 import os
+import re
 import subprocess
 import threading
 
@@ -46,7 +47,12 @@
         if os.path.exists(fn):
             with open(fn) as f:
                 for line in f:
-                    k, v = line.strip().split('=')
+                    line = re.sub('#.*', '', line).strip()
+                    if not line:
+                        continue
+                    if '=' not in line:
+                        continue
+                    k, v = line.split('=')
                     env[k] = v
     return env
 
diff --git a/zuul/cmd/__init__.py b/zuul/cmd/__init__.py
index 2902c50..5ffd431 100644
--- a/zuul/cmd/__init__.py
+++ b/zuul/cmd/__init__.py
@@ -14,8 +14,8 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import six
 from six.moves import configparser as ConfigParser
-import cStringIO
 import extras
 import logging
 import logging.config
@@ -47,7 +47,7 @@
             yappi.start()
         else:
             yappi.stop()
-            yappi_out = cStringIO.StringIO()
+            yappi_out = six.BytesIO()
             yappi.get_func_stats().print_all(out=yappi_out)
             yappi.get_thread_stats().print_all(out=yappi_out)
             log.debug(yappi_out.getvalue())
diff --git a/zuul/launcher/ansiblelaunchserver.py b/zuul/launcher/ansiblelaunchserver.py
index 0b3dc46..f0b695d 100644
--- a/zuul/launcher/ansiblelaunchserver.py
+++ b/zuul/launcher/ansiblelaunchserver.py
@@ -114,10 +114,16 @@
         self.termination_queue = Queue.Queue()
         self.sites = {}
         self.static_nodes = {}
-        if config.has_option('launcher', 'accept-nodes'):
-            self.accept_nodes = config.get('launcher', 'accept-nodes')
+        if config.has_option('launcher', 'accept_nodes'):
+            self.accept_nodes = config.getboolean('launcher',
+                                                  'accept_nodes')
         else:
-            self.accept_nodes = True
+            # TODO(jeblair): remove deprecated form of option
+            if config.has_option('launcher', 'accept-nodes'):
+                self.accept_nodes = config.getboolean('launcher',
+                                                      'accept-nodes')
+            else:
+                self.accept_nodes = True
 
         if self.config.has_option('zuul', 'state_dir'):
             state_dir = os.path.expanduser(
@@ -235,6 +241,8 @@
     def register(self):
         new_functions = set()
         if self.accept_nodes:
+            new_functions.add("node_assign:zuul")
+            # TODO(jeblair): remove deprecated form
             new_functions.add("node-assign:zuul")
         new_functions.add("stop:%s" % self.hostname)
         new_functions.add("set_description:%s" % self.hostname)
@@ -360,7 +368,11 @@
             try:
                 job = self.worker.getJob()
                 try:
-                    if job.name.startswith('node-assign:'):
+                    if job.name.startswith('node_assign:'):
+                        self.log.debug("Got node_assign job: %s" % job.unique)
+                        self.assignNode(job)
+                    elif job.name.startswith('node-assign:'):
+                        # TODO(jeblair): remove deprecated form
                         self.log.debug("Got node-assign job: %s" % job.unique)
                         self.assignNode(job)
                     elif job.name.startswith('stop:'):
@@ -478,7 +490,10 @@
         self._got_job = False
         self._job_complete_event = threading.Event()
         self._running_job = False
+        self._aborted_job = False
         self._sent_complete_event = False
+        self.ansible_job_proc = None
+        self.ansible_post_proc = None
         self.workspace_root = config.get('launcher', 'workspace_root')
         if self.config.has_option('launcher', 'private_key_file'):
             self.private_key_file = config.get('launcher', 'private_key_file')
@@ -639,6 +654,7 @@
         self.registered_functions = new_functions
 
     def abortRunningJob(self):
+        self._aborted_job = True
         return self.abortRunningProc(self.ansible_job_proc)
 
     def abortRunningProc(self, proc):
@@ -675,6 +691,7 @@
         # whether the job actually runs
         result = None
         self._sent_complete_event = False
+        self._aborted_job = False
 
         try:
             self.sendStartEvent(job_name, args)
@@ -773,7 +790,10 @@
             else:
                 status = 'FAILURE'
 
-            result = json.dumps(dict(result=status))
+            if not self._aborted_job:
+                # A Null result will cause zuul to relaunch the job if
+                # it needs to.
+                result = json.dumps(dict(result=status))
 
         return result
 
@@ -934,7 +954,7 @@
         remote_path = os.path.join('/tmp', script_fn)
         copy = dict(src=script_path,
                     dest=remote_path,
-                    mode=0555)
+                    mode=0o555)
         task = dict(copy=copy)
         tasks.append(task)
 
diff --git a/zuul/merger/merger.py b/zuul/merger/merger.py
index c6ae35d..3bc29e6 100644
--- a/zuul/merger/merger.py
+++ b/zuul/merger/merger.py
@@ -210,7 +210,7 @@
         fd.write('#!/bin/bash\n')
         fd.write('ssh -i %s $@\n' % key)
         fd.close()
-        os.chmod(name, 0755)
+        os.chmod(name, 0o755)
 
     def addProject(self, project, url):
         repo = None
diff --git a/zuul/merger/server.py b/zuul/merger/server.py
index 30cd732..d56993c 100644
--- a/zuul/merger/server.py
+++ b/zuul/merger/server.py
@@ -19,7 +19,7 @@
 
 import gear
 
-import merger
+from zuul.merger import merger
 
 
 class MergeServer(object):
diff --git a/zuul/rpclistener.py b/zuul/rpclistener.py
index d54da9f..83d119f 100644
--- a/zuul/rpclistener.py
+++ b/zuul/rpclistener.py
@@ -21,7 +21,7 @@
 import gear
 import six
 
-import model
+from zuul import model
 
 
 class RPCListener(object):
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index beab879..dcc5f88 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -28,10 +28,10 @@
 import time
 import yaml
 
-import layoutvalidator
-import model
-from model import Pipeline, Project, ChangeQueue
-from model import ChangeishFilter, NullChange
+from zuul import layoutvalidator
+from zuul import model
+from zuul.model import Pipeline, Project, ChangeQueue
+from zuul.model import ChangeishFilter, NullChange
 from zuul import change_matcher, exceptions
 from zuul import version as zuul_version