package com.sequenceiq.cloudbreak.controller.validation.template; import java.util.Collection; import java.util.Map; import javax.inject.Inject; import org.springframework.stereotype.Component; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.sequenceiq.cloudbreak.cloud.model.DiskType; import com.sequenceiq.cloudbreak.cloud.model.Platform; import com.sequenceiq.cloudbreak.cloud.model.VmType; import com.sequenceiq.cloudbreak.cloud.model.VmTypeMeta; import com.sequenceiq.cloudbreak.cloud.model.VolumeParameterConfig; import com.sequenceiq.cloudbreak.cloud.model.VolumeParameterType; import com.sequenceiq.cloudbreak.controller.BadRequestException; import com.sequenceiq.cloudbreak.domain.Template; import com.sequenceiq.cloudbreak.service.stack.CloudParameterService; @Component public class TemplateValidator { @Inject private CloudParameterService cloudParameterService; private Supplier<Map<Platform, Collection<VmType>>> virtualMachines = Suppliers.memoize(() -> cloudParameterService.getVmtypes(true).getVirtualMachines()); private Supplier<Map<Platform, Map<String, VolumeParameterType>>> diskMappings = Suppliers.memoize(() -> cloudParameterService.getDiskTypes().getDiskMappings()); public void validateTemplateRequest(Template value) { VmType vmType = null; VolumeParameterType volumeParameterType = null; Platform platform = Platform.platform(value.cloudPlatform()); Map<Platform, Collection<VmType>> machines = virtualMachines.get(); if (machines.containsKey(platform) && !machines.get(platform).isEmpty()) { for (VmType type : machines.get(platform)) { if (type.value().equals(value.getInstanceType())) { vmType = type; } } if (vmType == null) { throw new BadRequestException( String.format("The '%s' instance type isn't supported by '%s' platform", value.getInstanceType(), platform.value())); } } Map<Platform, Map<String, VolumeParameterType>> disks = diskMappings.get(); if (disks.containsKey(platform) && !disks.get(platform).isEmpty()) { Map<String, VolumeParameterType> map = disks.get(platform); volumeParameterType = map.get(value.getVolumeType()); if (volumeParameterType == null) { throw new BadRequestException( String.format("The '%s' volume type isn't supported by '%s' platform", value.getVolumeType(), platform.value())); } } validateVolume(value, vmType, platform, volumeParameterType); } private void validateVolume(Template value, VmType vmType, Platform platform, VolumeParameterType volumeParameterType) { validateVolumeType(value, platform); validateVolumeCount(value, vmType, volumeParameterType); validateVolumeSize(value, vmType, volumeParameterType); validateMaximumVolumeSize(value, vmType); } private void validateMaximumVolumeSize(Template value, VmType vmType) { if (vmType != null) { String maxSize = vmType.getMetaDataValue(VmTypeMeta.MAXIMUM_PERSISTENT_DISKS_SIZE_GB); if (maxSize != null) { int fullSize = value.getVolumeSize() * value.getVolumeCount(); if (Integer.valueOf(maxSize) < fullSize) { throw new BadRequestException( String.format("The %s platform does not support %s Gb full volume size. The maximum size of disks could be %s Gb.", value.cloudPlatform(), fullSize, maxSize)); } } } } private void validateVolumeType(Template value, Platform platform) { DiskType diskType = DiskType.diskType(value.getVolumeType()); Map<Platform, Collection<DiskType>> diskTypes = cloudParameterService.getDiskTypes().getDiskTypes(); if (diskTypes.containsKey(platform) && !diskTypes.get(platform).isEmpty()) { if (!diskTypes.get(platform).contains(diskType)) { throw new BadRequestException(String.format("The '%s' platform does not support '%s' volume type", platform.value(), diskType.value())); } } } private void validateVolumeCount(Template value, VmType vmType, VolumeParameterType volumeParameterType) { if (vmType != null && needToCheckVolume(volumeParameterType, value.getVolumeCount())) { VolumeParameterConfig config = vmType.getVolumeParameterbyVolumeParameterType(volumeParameterType); if (config != null) { if (value.getVolumeCount() > config.maximumNumber()) { throw new BadRequestException(String.format("Max allowed volume count for '%s': %s", vmType.value(), config.maximumNumber())); } else if (value.getVolumeCount() < config.minimumNumber()) { throw new BadRequestException(String.format("Min allowed volume count for '%s': %s", vmType.value(), config.minimumNumber())); } } else { throw new BadRequestException(String.format("The '%s' instance type does not support 'Ephemeral' volume type", vmType.value())); } } } private void validateVolumeSize(Template value, VmType vmType, VolumeParameterType volumeParameterType) { if (vmType != null && needToCheckVolume(volumeParameterType, value.getVolumeCount())) { VolumeParameterConfig config = vmType.getVolumeParameterbyVolumeParameterType(volumeParameterType); if (config != null) { if (value.getVolumeSize() > config.maximumSize()) { throw new BadRequestException(String.format("Max allowed volume size for '%s': %s", vmType.value(), config.maximumSize())); } else if (value.getVolumeSize() < config.minimumSize()) { throw new BadRequestException(String.format("Min allowed volume size for '%s': %s", vmType.value(), config.minimumSize())); } } else { throw new BadRequestException(String.format("The '%s' instance type does not support 'Ephemeral' volume type", vmType.value())); } } } private boolean needToCheckVolume(VolumeParameterType volumeParameterType, Object value) { return volumeParameterType != VolumeParameterType.EPHEMERAL || value != null; } }