class HostedVespaClusterPolicy implements ClusterPolicy {

    @Override
    public SuspensionReasons verifyGroupGoingDownIsFine(ClusterApi clusterApi) throws HostStateChangeDeniedException {
        if (clusterApi.noServicesOutsideGroupIsDown()) {
            return SuspensionReasons.nothingNoteworthy();
        }

        int percentageOfServicesAllowedToBeDown = getConcurrentSuspensionLimit(clusterApi).asPercentage();
        if (clusterApi.percentageOfServicesDownIfGroupIsAllowedToBeDown() <= percentageOfServicesAllowedToBeDown) {
            return SuspensionReasons.nothingNoteworthy();
        }

        Optional<SuspensionReasons> suspensionReasons = clusterApi.reasonsForNoServicesInGroupIsUp();
        if (suspensionReasons.isPresent()) {
            return suspensionReasons.get();
        }

        throw new HostStateChangeDeniedException(
                clusterApi.getNodeGroup(),
                ENOUGH_SERVICES_UP_CONSTRAINT,
                "Suspension for service type " + clusterApi.serviceType()
                        + " would increase from " + clusterApi.percentageOfServicesDown()
                        + "% to " + clusterApi.percentageOfServicesDownIfGroupIsAllowedToBeDown()
                        + "%, over the limit of " + percentageOfServicesAllowedToBeDown + "%."
                        + clusterApi.downDescription());
    }

}