Merge "Run ansible setup at start of job to verify network" into feature/zuulv3
diff --git a/tests/base.py b/tests/base.py
index df9fbc1..2e3d682 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -1485,7 +1485,10 @@
result = super(RecordingAnsibleJob, self).runAnsible(
cmd, timeout, playbook)
else:
- result = build.run()
+ if playbook.path:
+ result = build.run()
+ else:
+ result = (self.RESULT_NORMAL, 0)
return result
def getHostList(self, args):
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index 27fd85f..af2e7e9 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -346,6 +346,15 @@
self.trusted_projects = []
self.trusted_project_index = {}
+ # Create a JobDirPlaybook for the Ansible setup run. This
+ # doesn't use an actual playbook, but it lets us use the same
+ # methods to write an ansible.cfg as the rest of the Ansible
+ # runs.
+ setup_root = os.path.join(self.ansible_root, 'setup_playbook')
+ os.makedirs(setup_root)
+ self.setup_playbook = JobDirPlaybook(setup_root)
+ self.setup_playbook.trusted = True
+
def addTrustedProject(self, canonical_name, branch):
# Trusted projects are placed in their own directories so that
# we can support using different branches of the same project
@@ -1101,6 +1110,17 @@
def runPlaybooks(self, args):
result = None
+ # Run the Ansible 'setup' module on all hosts in the inventory
+ # at the start of the job with a 60 second timeout. If we
+ # aren't able to connect to all the hosts and gather facts
+ # within that timeout, there is likely a network problem
+ # between here and the hosts in the inventory; return them and
+ # reschedule the job.
+ setup_status, setup_code = self.runAnsibleSetup(
+ self.jobdir.setup_playbook)
+ if setup_status != self.RESULT_NORMAL or setup_code != 0:
+ return result
+
pre_failed = False
success = False
for index, playbook in enumerate(self.jobdir.pre_playbooks):
@@ -1213,6 +1233,8 @@
return None
def preparePlaybooks(self, args):
+ self.writeAnsibleConfig(self.jobdir.setup_playbook)
+
for playbook in args['pre_playbooks']:
jobdir_playbook = self.jobdir.addPrePlaybook()
self.preparePlaybook(jobdir_playbook, playbook,
@@ -1289,7 +1311,7 @@
jobdir_playbook.secrets_content = yaml.safe_dump(
secrets, default_flow_style=False)
- self.writeAnsibleConfig(jobdir_playbook, playbook)
+ self.writeAnsibleConfig(jobdir_playbook)
def checkoutTrustedProject(self, project, branch):
root = self.jobdir.getTrustedProject(project.canonical_name,
@@ -1420,7 +1442,7 @@
job_output_file=self.jobdir.job_output_file)
logging_config.writeJson(self.jobdir.logging_json)
- def writeAnsibleConfig(self, jobdir_playbook, playbook):
+ def writeAnsibleConfig(self, jobdir_playbook):
trusted = jobdir_playbook.trusted
# TODO(mordred) This should likely be extracted into a more generalized
@@ -1467,7 +1489,7 @@
# role. Otherwise, printing the args could be useful for
# debugging.
config.write('display_args_to_stdout = %s\n' %
- str(not playbook['secrets']))
+ str(not jobdir_playbook.secrets_content))
config.write('[ssh_connection]\n')
# NB: when setting pipelining = True, keep_remote_files
@@ -1640,6 +1662,21 @@
return (self.RESULT_NORMAL, ret)
+ def runAnsibleSetup(self, playbook):
+ if self.executor_server.verbose:
+ verbose = '-vvv'
+ else:
+ verbose = '-v'
+
+ cmd = ['ansible', '*', verbose, '-m', 'setup',
+ '-a', 'gather_subset=!all']
+
+ result, code = self.runAnsible(
+ cmd=cmd, timeout=60, playbook=playbook)
+ self.log.debug("Ansible complete, result %s code %s" % (
+ self.RESULT_MAP[result], code))
+ return result, code
+
def runAnsiblePlaybook(self, playbook, timeout, success=None,
phase=None, index=None):
if self.executor_server.verbose: