private List<Node> provisionUntilNoDeficit(NodeList nodeList) {
        List<ClusterCapacity> preprovisionCapacity = preprovisionCapacityFlag.value();
        ApplicationId application = ApplicationId.defaultId();

        // Worst-case each ClusterCapacity in preprovisionCapacity will require an allocation.
        int maxProvisions = preprovisionCapacity.size();

        var nodesPlusProvisioned = new ArrayList<>(nodeList.asList());
        for (int numProvisions = 0;; ++numProvisions) {
            var nodesPlusProvisionedPlusAllocated = new ArrayList<>(nodesPlusProvisioned);
            Optional<ClusterCapacity> deficit = allocatePreprovisionCapacity(application, preprovisionCapacity, nodesPlusProvisionedPlusAllocated);
            if (deficit.isEmpty()) {
                return nodesPlusProvisionedPlusAllocated;
            }

            if (numProvisions >= maxProvisions) {
                throw new IllegalStateException("Have provisioned " + numProvisions + " times but there's still deficit: aborting");
            }

            ClusterCapacity clusterCapacityDeficit = deficit.get();
            nodesPlusProvisioned.addAll(provisionHosts(clusterCapacityDeficit.count(),
                                                       toNodeResources(clusterCapacityDeficit),
                                                       Optional.ofNullable(clusterCapacityDeficit.clusterType()),
                                                       nodeList));
        }
    }
@return the nodes in {@code nodeList} plus all hosts provisioned, plus all preprovision capacity
        nodes that were allocated.
@throws NodeAllocationException if there were problems provisioning hosts, and in case message
        should be sufficient (avoid no stack trace)
@throws IllegalStateException if there was an algorithmic problem, and in case message
        should be sufficient (avoid no stack trace).
node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java