diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d81f8e12e..68ba1a5c9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG **CHANGES** - Ubuntu 20.04 is no longer supported. +- Support prioritized and capacity-optimized-prioritized Allocation Strategy **BUG FIXES** - Fix an issue where Security Group validation failed when a rule contained both IPv4 ranges (IpRanges) and security group references (UserIdGroupPairs). diff --git a/cli/src/pcluster/config/cluster_config.py b/cli/src/pcluster/config/cluster_config.py index 96a747ebd7..7f4c7165d5 100644 --- a/cli/src/pcluster/config/cluster_config.py +++ b/cli/src/pcluster/config/cluster_config.py @@ -25,6 +25,7 @@ from pcluster.aws.common import AWSClientError, get_region from pcluster.config.common import ( AdditionalIamPolicy, + AllocationStrategy, BaseDeploymentSettings, BaseDevSettings, BaseTag, @@ -185,6 +186,7 @@ from pcluster.validators.monitoring_validators import DetailedMonitoringValidator, LogRotationValidator from pcluster.validators.networking_validators import ( ElasticIpValidator, + EnableSingleAvailabilityZoneValidator, MultiAzPlacementGroupValidator, QueueSubnetsValidator, SecurityGroupsValidator, @@ -813,10 +815,17 @@ def __init__(self, subnet_ids: List[str], assign_public_ip: str = None, **kwargs class SlurmQueueNetworking(_QueueNetworking): """Represent the networking configuration for the slurm Queue.""" - def __init__(self, placement_group: PlacementGroup = None, proxy: Proxy = None, **kwargs): + def __init__( + self, + placement_group: PlacementGroup = None, + proxy: Proxy = None, + enable_single_availability_zone: bool = None, + **kwargs, + ): super().__init__(**kwargs) self.placement_group = placement_group or PlacementGroup(implied=True) self.proxy = proxy + self.enable_single_availability_zone = enable_single_availability_zone class AwsBatchQueueNetworking(_QueueNetworking): @@ -2565,14 +2574,6 @@ def _register_validators(self, context: ValidatorContext = None): ) -class AllocationStrategy(Enum): - """Define supported allocation strategies.""" - - LOWEST_PRICE = "lowest-price" - CAPACITY_OPTIMIZED = "capacity-optimized" - PRICE_CAPACITY_OPTIMIZED = "price-capacity-optimized" - - class SlurmQueue(_CommonQueue): """Represents a Slurm Queue that has Compute Resources with both Single and Multiple Instance Types.""" @@ -2633,6 +2634,14 @@ def _register_validators(self, context: ValidatorContext = None): max_length=MAX_COMPUTE_RESOURCES_PER_QUEUE, resource_name="ComputeResources per Queue", ) + if any( + isinstance(compute_resource, SlurmFlexibleComputeResource) for compute_resource in self.compute_resources + ): + self._register_validator( + EnableSingleAvailabilityZoneValidator, + allocation_strategy=self.allocation_strategy, + enable_single_availability_zone=self.networking.enable_single_availability_zone, + ) self._register_validator( QueueSubnetsValidator, queue_name=self.name, diff --git a/cli/src/pcluster/config/common.py b/cli/src/pcluster/config/common.py index cf7f54323c..ddb7c4e65b 100644 --- a/cli/src/pcluster/config/common.py +++ b/cli/src/pcluster/config/common.py @@ -28,6 +28,16 @@ LOGGER = logging.getLogger(__name__) +class AllocationStrategy(Enum): + """Define supported allocation strategies.""" + + LOWEST_PRICE = "lowest-price" + CAPACITY_OPTIMIZED = "capacity-optimized" + PRICE_CAPACITY_OPTIMIZED = "price-capacity-optimized" + PRIORITIZED = "prioritized" + CAPACITY_OPTIMIZED_PRIORITIZED = "capacity-optimized-prioritized" + + class CapacityType(Enum): """Enum to identify the type compute supported by the queues.""" diff --git a/cli/src/pcluster/schemas/cluster_schema.py b/cli/src/pcluster/schemas/cluster_schema.py index e14e345767..0d21c8f927 100644 --- a/cli/src/pcluster/schemas/cluster_schema.py +++ b/cli/src/pcluster/schemas/cluster_schema.py @@ -24,7 +24,6 @@ from pcluster.config.cluster_config import ( AdditionalPackages, Alarms, - AllocationStrategy, AmiSearchFilters, AwsBatchClusterConfig, AwsBatchComputeResource, @@ -95,7 +94,7 @@ SlurmSettings, Timeouts, ) -from pcluster.config.common import BaseTag, CapacityType, DefaultUserHomeType +from pcluster.config.common import AllocationStrategy, BaseTag, CapacityType, DefaultUserHomeType from pcluster.config.update_policy import UpdatePolicy from pcluster.constants import ( DELETION_POLICIES, @@ -752,6 +751,7 @@ class SlurmQueueNetworkingSchema(QueueNetworkingSchema): PlacementGroupSchema, metadata={"update_policy": UpdatePolicy.MANAGED_PLACEMENT_GROUP} ) proxy = fields.Nested(QueueProxySchema, metadata={"update_policy": UpdatePolicy.QUEUE_UPDATE_STRATEGY}) + enable_single_availability_zone = fields.Bool(metadata={"update_policy": UpdatePolicy.QUEUE_UPDATE_STRATEGY}) @post_load def make_resource(self, data, **kwargs): diff --git a/cli/src/pcluster/validators/instances_validators.py b/cli/src/pcluster/validators/instances_validators.py index 80215aa3d2..4bcc8fe45f 100644 --- a/cli/src/pcluster/validators/instances_validators.py +++ b/cli/src/pcluster/validators/instances_validators.py @@ -12,7 +12,7 @@ from typing import Callable, Dict from pcluster.aws.aws_resources import InstanceTypeInfo -from pcluster.config import cluster_config +from pcluster.config import cluster_config, common from pcluster.constants import MIN_MEMORY_ABSOLUTE_DIFFERENCE, MIN_MEMORY_PRECENTAGE_DIFFERENCE from pcluster.validators.common import FailureLevel, Validator @@ -221,17 +221,19 @@ class InstancesAllocationStrategyValidator(Validator, _FlexibleInstanceTypesVali """Confirm Allocation Strategy matches with the Capacity Type.""" def _validate(self, compute_resource_name: str, capacity_type: Enum, allocation_strategy: Enum, **kwargs): - """On-demand Capacity type only supports "lowest-price" allocation strategy.""" + """On-demand Capacity type only supports "lowest-price" and "prioritized" allocation strategy.""" if ( capacity_type == cluster_config.CapacityType.ONDEMAND and allocation_strategy - and allocation_strategy != cluster_config.AllocationStrategy.LOWEST_PRICE + and allocation_strategy != common.AllocationStrategy.LOWEST_PRICE + and allocation_strategy != common.AllocationStrategy.PRIORITIZED ): alloc_strategy_msg = allocation_strategy.value if allocation_strategy else "not set" self._add_failure( - f"Compute Resource {compute_resource_name} is using an OnDemand CapacityType but the Allocation " - f"Strategy specified is {alloc_strategy_msg}. OnDemand CapacityType can only use '" - f"{cluster_config.AllocationStrategy.LOWEST_PRICE.value}' allocation strategy.", + f"Compute Resource {compute_resource_name} is using an OnDemand CapacityType but " + f"the Allocation Strategy specified is {alloc_strategy_msg}. OnDemand CapacityType can only use '" + f"{common.AllocationStrategy.LOWEST_PRICE.value}' or '{common.AllocationStrategy.PRIORITIZED.value}' " + "allocation strategy.", FailureLevel.ERROR, ) if capacity_type == cluster_config.CapacityType.CAPACITY_BLOCK and allocation_strategy: @@ -241,6 +243,19 @@ def _validate(self, compute_resource_name: str, capacity_type: Enum, allocation_ "When using CAPACITY_BLOCK CapacityType, allocation strategy should not be set.", FailureLevel.ERROR, ) + if ( + capacity_type == cluster_config.CapacityType.SPOT + and allocation_strategy == common.AllocationStrategy.PRIORITIZED + ): + self._add_failure( + f"Compute Resource {compute_resource_name} is using a SPOT CapacityType but the " + f"Allocation Strategy specified is {allocation_strategy.value}. SPOT CapacityType can only use " + f"'{common.AllocationStrategy.LOWEST_PRICE.value}', " + f"'{common.AllocationStrategy.CAPACITY_OPTIMIZED.value}', " + f"'{common.AllocationStrategy.PRICE_CAPACITY_OPTIMIZED.value}' " + f"or '{common.AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED.value}' allocation strategy.", + FailureLevel.ERROR, + ) class InstancesMemorySchedulingWarningValidator(Validator): diff --git a/cli/src/pcluster/validators/networking_validators.py b/cli/src/pcluster/validators/networking_validators.py index d5c9b59b45..39b4cf5221 100644 --- a/cli/src/pcluster/validators/networking_validators.py +++ b/cli/src/pcluster/validators/networking_validators.py @@ -9,10 +9,12 @@ # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and # limitations under the License. from collections import Counter +from enum import Enum from typing import List, Union from pcluster.aws.aws_api import AWSApi from pcluster.aws.common import AWSClientError +from pcluster.config import common from pcluster.validators.common import FailureLevel, Validator @@ -64,6 +66,29 @@ def _validate(self, subnet_ids: List[str]): self._add_failure(str(e), FailureLevel.ERROR) +class EnableSingleAvailabilityZoneValidator(Validator): + """ + Single Availability Zone validator. + + Check that enable_single_availability_zone should be used with prioritized + or capacity-optimized-prioritized Allocation Strategy + """ + + def _validate(self, allocation_strategy: Enum, enable_single_availability_zone: bool): + prioritized_allocation_strategies = ( + common.AllocationStrategy.PRIORITIZED, + common.AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, + ) + if enable_single_availability_zone and allocation_strategy not in prioritized_allocation_strategies: + self._add_failure( + "Enable_single_availability_zone is specified as " + f"'{enable_single_availability_zone}' while allocation_strategy is specified as " + f"'{allocation_strategy.value}'. Enable_single_availability_zone should only be used with " + "prioritized or capacity-optimized-prioritized Allocation Strategy.", + FailureLevel.ERROR, + ) + + class QueueSubnetsValidator(Validator): """ Queue Subnets validator. diff --git a/cli/tests/pcluster/templates/test_cluster_stack/test_cluster_config_limits/slurm.full_config.snapshot.yaml b/cli/tests/pcluster/templates/test_cluster_stack/test_cluster_config_limits/slurm.full_config.snapshot.yaml index eddb82b155..d6580bef26 100644 --- a/cli/tests/pcluster/templates/test_cluster_stack/test_cluster_config_limits/slurm.full_config.snapshot.yaml +++ b/cli/tests/pcluster/templates/test_cluster_stack/test_cluster_config_limits/slurm.full_config.snapshot.yaml @@ -219,6 +219,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -297,6 +298,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -375,6 +377,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -453,6 +456,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -531,6 +535,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -609,6 +614,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -687,6 +693,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -765,6 +772,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -843,6 +851,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -921,6 +930,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -999,6 +1009,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1077,6 +1088,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1155,6 +1167,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1233,6 +1246,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1311,6 +1325,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1389,6 +1404,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1467,6 +1483,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1545,6 +1562,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1623,6 +1641,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1701,6 +1720,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1779,6 +1799,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1857,6 +1878,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -1935,6 +1957,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -2013,6 +2036,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -2091,6 +2115,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: null + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: null Id: null @@ -2158,6 +2183,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2226,6 +2252,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2294,6 +2321,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2362,6 +2390,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2430,6 +2459,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2498,6 +2528,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2566,6 +2597,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2634,6 +2666,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2702,6 +2735,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2770,6 +2804,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2838,6 +2873,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2906,6 +2942,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -2974,6 +3011,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3042,6 +3080,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3110,6 +3149,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3178,6 +3218,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3246,6 +3287,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3314,6 +3356,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3382,6 +3425,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3450,6 +3494,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3518,6 +3563,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3586,6 +3632,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3654,6 +3701,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3722,6 +3770,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String @@ -3790,6 +3839,7 @@ Scheduling: Networking: AdditionalSecurityGroups: null AssignPublicIp: true + EnableSingleAvailabilityZone: null PlacementGroup: Enabled: true Id: String diff --git a/cli/tests/pcluster/validators/test_all_validators.py b/cli/tests/pcluster/validators/test_all_validators.py index 9e5c413bab..10f0f68a1b 100644 --- a/cli/tests/pcluster/validators/test_all_validators.py +++ b/cli/tests/pcluster/validators/test_all_validators.py @@ -13,7 +13,7 @@ from assertpy import assert_that from pcluster.aws.aws_resources import ImageInfo -from pcluster.config.common import CapacityType +from pcluster.config.common import AllocationStrategy, CapacityType from pcluster.schemas.cluster_schema import ClusterSchema from pcluster.utils import load_yaml_dict from pcluster.validators import ( @@ -224,6 +224,9 @@ def test_slurm_validators_are_called_with_correct_argument(test_datadir, mocker) single_instance_type_subnet_validator = mocker.patch( networking_validators + ".SingleInstanceTypeSubnetValidator._validate", return_value=[] ) + enable_single_availability_zone_validator = mocker.patch( + networking_validators + ".EnableSingleAvailabilityZoneValidator._validate", return_value=[] + ) fsx_validators = validators_path + ".fsx_validators" fsx_s3_validator = mocker.patch(fsx_validators + ".FsxS3Validator._validate", return_value=[]) @@ -334,6 +337,13 @@ def test_slurm_validators_are_called_with_correct_argument(test_datadir, mocker) any_order=True, ) subnets_validator.assert_has_calls([call(subnet_ids=["subnet-12345678", "subnet-23456789", "subnet-12345678"])]) + enable_single_availability_zone_validator.assert_has_calls( + [ + call(allocation_strategy=AllocationStrategy.PRIORITIZED, enable_single_availability_zone=True), + call(allocation_strategy=None, enable_single_availability_zone=False), + ], + any_order=True, + ) single_instance_type_subnet_validator.assert_has_calls( [ call(queue_name="queue1", subnet_ids=["subnet-23456789"]), diff --git a/cli/tests/pcluster/validators/test_all_validators/test_slurm_validators_are_called_with_correct_argument/slurm.yaml b/cli/tests/pcluster/validators/test_all_validators/test_slurm_validators_are_called_with_correct_argument/slurm.yaml index 2f70a826d2..3a552d7fe0 100644 --- a/cli/tests/pcluster/validators/test_all_validators/test_slurm_validators_are_called_with_correct_argument/slurm.yaml +++ b/cli/tests/pcluster/validators/test_all_validators/test_slurm_validators_are_called_with_correct_argument/slurm.yaml @@ -39,9 +39,11 @@ Scheduling: - Name: compute_resource2 InstanceType: c4.2xlarge - Name: queue2 + AllocationStrategy: "prioritized" Networking: SubnetIds: - subnet-23456789 + EnableSingleAvailabilityZone: true ComputeResources: - Name: compute_resource1 InstanceType: c5.4xlarge @@ -68,6 +70,7 @@ Scheduling: Networking: SubnetIds: - subnet-23456789 + EnableSingleAvailabilityZone: false ComputeResources: - Name: compute_resource1 Instances: diff --git a/cli/tests/pcluster/validators/test_instances_validators.py b/cli/tests/pcluster/validators/test_instances_validators.py index e35d571fa6..3ffaa0adb5 100644 --- a/cli/tests/pcluster/validators/test_instances_validators.py +++ b/cli/tests/pcluster/validators/test_instances_validators.py @@ -14,7 +14,8 @@ import pytest from pcluster.aws.aws_resources import InstanceTypeInfo -from pcluster.config.cluster_config import AllocationStrategy, CapacityType +from pcluster.config.cluster_config import CapacityType +from pcluster.config.common import AllocationStrategy from pcluster.validators.instances_validators import ( InstancesAcceleratorsValidator, InstancesAllocationStrategyValidator, @@ -591,31 +592,49 @@ def test_instances_networking_validator( CapacityType.ONDEMAND, AllocationStrategy.CAPACITY_OPTIMIZED, "Compute Resource TestComputeResource is using an OnDemand CapacityType but the Allocation Strategy " - "specified is capacity-optimized. OnDemand CapacityType can only use 'lowest-price' allocation strategy.", + "specified is capacity-optimized. " + "OnDemand CapacityType can only use 'lowest-price' or 'prioritized' allocation strategy.", ), ( CapacityType.ONDEMAND, AllocationStrategy.PRICE_CAPACITY_OPTIMIZED, "Compute Resource TestComputeResource is using an OnDemand CapacityType but the Allocation Strategy " "specified is price-capacity-optimized. " - "OnDemand CapacityType can only use 'lowest-price' allocation strategy.", + "OnDemand CapacityType can only use 'lowest-price' or 'prioritized' allocation strategy.", ), + ( + CapacityType.ONDEMAND, + AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, + "Compute Resource TestComputeResource is using an OnDemand CapacityType but the Allocation " + "Strategy specified is capacity-optimized-prioritized. " + "OnDemand CapacityType can only use 'lowest-price' or 'prioritized' allocation strategy.", + ), + (CapacityType.ONDEMAND, AllocationStrategy.PRIORITIZED, ""), (CapacityType.ONDEMAND, AllocationStrategy.LOWEST_PRICE, ""), (CapacityType.ONDEMAND, None, ""), # Spot Capacity type supports both "lowest-price" and "capacity-optimized" allocation strategy (CapacityType.SPOT, AllocationStrategy.LOWEST_PRICE, ""), (CapacityType.SPOT, AllocationStrategy.CAPACITY_OPTIMIZED, ""), (CapacityType.SPOT, AllocationStrategy.PRICE_CAPACITY_OPTIMIZED, ""), + (CapacityType.SPOT, AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, ""), (CapacityType.SPOT, None, ""), + ( + CapacityType.SPOT, + AllocationStrategy.PRIORITIZED, + "Compute Resource TestComputeResource is using a SPOT CapacityType but the " + "Allocation Strategy specified is prioritized. SPOT CapacityType can only use " + "'lowest-price', " + "'capacity-optimized', " + "'price-capacity-optimized' " + "or 'capacity-optimized-prioritized' allocation strategy.", + ), # Capacity Block type supports does not support any allocation strategy ( CapacityType.CAPACITY_BLOCK, AllocationStrategy.CAPACITY_OPTIMIZED, - ( - "Compute Resource TestComputeResource is using a CAPACITY_BLOCK CapacityType but the Allocation " - "Strategy specified is capacity-optimized. When using CAPACITY_BLOCK CapacityType, " - "allocation strategy should not be set." - ), + "Compute Resource TestComputeResource is using a CAPACITY_BLOCK CapacityType but the Allocation " + "Strategy specified is capacity-optimized. When using CAPACITY_BLOCK CapacityType, " + "allocation strategy should not be set.", ), ( CapacityType.CAPACITY_BLOCK, @@ -632,6 +651,19 @@ def test_instances_networking_validator( "Compute Resource TestComputeResource is using a CAPACITY_BLOCK CapacityType but the Allocation Strategy " "specified is lowest-price. When using CAPACITY_BLOCK CapacityType, allocation strategy should not be set.", ), + ( + CapacityType.CAPACITY_BLOCK, + AllocationStrategy.PRIORITIZED, + "Compute Resource TestComputeResource is using a CAPACITY_BLOCK CapacityType but the Allocation Strategy " + "specified is prioritized. When using CAPACITY_BLOCK CapacityType, allocation strategy should not be set.", + ), + ( + CapacityType.CAPACITY_BLOCK, + AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, + "Compute Resource TestComputeResource is using a CAPACITY_BLOCK CapacityType but the Allocation Strategy " + "specified is capacity-optimized-prioritized. When using CAPACITY_BLOCK CapacityType, " + "allocation strategy should not be set.", + ), (CapacityType.CAPACITY_BLOCK, None, ""), ], ) diff --git a/cli/tests/pcluster/validators/test_networking_validators.py b/cli/tests/pcluster/validators/test_networking_validators.py index ce3f7624c3..624737a286 100644 --- a/cli/tests/pcluster/validators/test_networking_validators.py +++ b/cli/tests/pcluster/validators/test_networking_validators.py @@ -14,8 +14,10 @@ import pytest from pcluster.aws.common import AWSClientError +from pcluster.config.common import AllocationStrategy from pcluster.validators.networking_validators import ( ElasticIpValidator, + EnableSingleAvailabilityZoneValidator, LambdaFunctionsVpcConfigValidator, MultiAzPlacementGroupValidator, QueueSubnetsValidator, @@ -65,6 +67,51 @@ def test_ec2_subnet_id_validator(mocker): assert_failure_messages(actual_failures, None) +@pytest.mark.parametrize( + "allocation_strategy, enable_single_availability_zone, failure_message", + [ + (AllocationStrategy.LOWEST_PRICE, False, None), + ( + AllocationStrategy.LOWEST_PRICE, + True, + "Enable_single_availability_zone is specified as " + "'True' while allocation_strategy is specified as " + "'lowest-price'. Enable_single_availability_zone should only be used with " + "prioritized or capacity-optimized-prioritized Allocation Strategy.", + ), + (AllocationStrategy.CAPACITY_OPTIMIZED, False, None), + ( + AllocationStrategy.CAPACITY_OPTIMIZED, + True, + "Enable_single_availability_zone is specified as " + "'True' while allocation_strategy is specified as " + "'capacity-optimized'. Enable_single_availability_zone should only be used with " + "prioritized or capacity-optimized-prioritized Allocation Strategy.", + ), + (AllocationStrategy.PRICE_CAPACITY_OPTIMIZED, False, None), + ( + AllocationStrategy.PRICE_CAPACITY_OPTIMIZED, + True, + "Enable_single_availability_zone is specified as " + "'True' while allocation_strategy is specified as " + "'price-capacity-optimized'. Enable_single_availability_zone should only be used with " + "prioritized or capacity-optimized-prioritized Allocation Strategy.", + ), + (AllocationStrategy.PRIORITIZED, False, None), + (AllocationStrategy.PRIORITIZED, True, None), + (AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, False, None), + (AllocationStrategy.CAPACITY_OPTIMIZED_PRIORITIZED, True, None), + ], +) +def test_enable_single_availability_zone_validator( + allocation_strategy, enable_single_availability_zone, failure_message +): + actual_failures = EnableSingleAvailabilityZoneValidator().execute( + allocation_strategy, enable_single_availability_zone + ) + assert_failure_messages(actual_failures, failure_message) + + @pytest.mark.parametrize( "queue_name, queue_subnets, subnet_id_az_mapping, failure_message", [