Current implementation of NodeProvisioner.update() handles an exception from node provisioning and adding a node to Jenkins in the one block where it isn't clear from which step an Exception was thrown - it can create a confusion for ex. Provisioned slave " + f.displayName + " failed to launch in handling ExecutionException is very confusing because the mentioned provisioned slave doesn't exist, it could never exist etc.
I'd propose to split this to two separate try/catch blocks (+ one general try/catch block) and adjust the error messages a bit:
should catch and handle InterruptedException, ExecutionException.
should catch and handle IOException.
Both parts are enclosed with try/catch block for catching of Error and Throwable as the last stand if they occur.
In addition the first block shouldn't log anything here if ExecutionException.getCause() is instance of AbortException. AbortException has the unified meaning through the Jenkins - we need to signalize a situation when a provision process of a new node failed (in Future.call()); during the provision process we know about this failure, we recovered from it and we need to report that situation to NodeProvisioner. In NodeProvisioner we shouldn't make any additional action because handling and recovering is a responsibility of the reported in the place it was thrown.
Proposed change should be fully backward compatible.
TO-DO: When we introduce this change in the core first, we can adjust exception throwing from cloud provider plugins.