Python Multi-Host Failure Handling
A loop over an inventory has one host that is down, one whose name does not resolve and one where the command itself fails - and the obvious `for` loop stops at the first of them, having done a third of the work and reported nothing. This guide collects a result per host, distinguishes failures that are worth retrying from those that are not, runs them concurrently for a measured 4.1x, and exits with a code that says whether some or all of it worked.
Remote Hosts and CI/CD Guide 34 of 39 Advanced
- Python3.14.4
- Control nodeUbuntu 26.04 LTS
- Managed hostsRHEL 10.0
- requests2.34.2
- paramiko5.0.0
- pytest9.1.1
- PyYAML6.0.3
- boto3 / botocore1.43.78
- TimeAbout 22 min
- Reviewed24 August 2026
Written against the versions above. `concurrent.futures.ThreadPoolExecutor` is standard library and unchanged in the relevant respects. Threads are right here because every worker is blocked on a socket - the GIL is not in the way.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| RUNNER01 | 192.168.0.27 | Ubuntu 26.04 LTS | Control node - every script in this path runs here | 2 Core | 4 GB | 50 GB |
| RHCSA-A01 | 192.168.0.31 | RHEL 10.0 | Managed host - reached over SSH from the control node | 2 Core | 4 GB | 50 GB |
| RHCSA-B01 | 192.168.0.33 | RHEL 10.0 | Second managed host - so an inventory has more than one row | 2 Core | 4 GB | 50 GB |
Before you start
- guide 32 - the inventory this loops over.
- guide 5 - the codes at the end.
- guide 28 - which failures are worth retrying.
-
The loop that stops at the first problem
-
So catch per host, and keep a result for each
-
The three failures are not the same failure
-
Sequentially, then in parallel
-
And the worker count that matters
-
An exception inside a worker, and where it surfaces
-
What the script should exit with