We limit the number of concurrent blob downloads per node and per recovery, but if a user configures too many concurrent recoveries they may run out of per-node download permits which yields the following message:

> Unable to acquire permit to use snapshot files during recovery, this recovery will recover index files from the source node. Ensure snapshot files can be used during recovery by setting [indices.recovery.max_concurrent_snapshot_file_downloads] to be no greater than [25]

The `[25]` here is wrong, the 25 permits are shared across all inbound recoveries so we should divide the suggested value by `cluster.routing.allocation.node_concurrent_incoming_recoveries`. In extreme cases the user may have configured so many concurrent recoveries that the only reasonable limit is zero, and in that case we should suggest setting `indices.recovery.use_snapshots: false` instead.


server/src/test/java/org/elasticsearch/indices/recovery/RecoverySettingsTests.java
} else if (setting.getKey().equals(NODE_BANDWIDTH_RECOVERY_DISK_WRITE_SETTING.getKey())) {
                recoverySettings.withDiskWriteBandwidth(randomNonZeroByteSizeValue());
            } else {
                throw new AssertionError();
            }
        }
        final IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, recoverySettings::build);
        assertThat(
            exception.getMessage(),
            containsString(
                "Settings "
                    + NODE_BANDWIDTH_RECOVERY_SETTINGS.stream().map(Setting::getKey).toList()
                    + " must all be defined or all be undefined; but only settings "
                    + NODE_BANDWIDTH_RECOVERY_SETTINGS.stream().filter(randomSettings::contains).map(Setting::getKey).toList()
                    + " are configured."
            )
        );
    }
    public void testNodeBandwidthSettingsExist() {
        final NodeRecoverySettings recoverySettings = nodeRecoverySettings();
        recoverySettings.withRandomIndicesRecoveryMaxBytesPerSec();
        recoverySettings.withRoles(randomDataNodeRoles());
        recoverySettings.withRandomMemory();
        if (randomBoolean()) {
            recoverySettings.withNetworkBandwidth(randomNonZeroByteSizeValue());
            recoverySettings.withDiskReadBandwidth(randomNonZeroByteSizeValue());
            recoverySettings.withDiskWriteBandwidth(randomNonZeroByteSizeValue());
            assertTrue(recoverySettings.build().nodeBandwidthSettingsExist());
        } else {
            assertFalse(recoverySettings.build().nodeBandwidthSettingsExist());