|
33 | 33 | merge_tags, |
34 | 34 | ) |
35 | 35 | from dstack._internal.core.backends.base.offers import get_catalog_offers |
36 | | -from dstack._internal.core.errors import ComputeError, NoCapacityError, PlacementGroupInUseError |
| 36 | +from dstack._internal.core.errors import ( |
| 37 | + ComputeError, |
| 38 | + NoCapacityError, |
| 39 | + PlacementGroupInUseError, |
| 40 | + PlacementGroupNotSupportedError, |
| 41 | +) |
37 | 42 | from dstack._internal.core.models.backends.base import BackendType |
38 | 43 | from dstack._internal.core.models.common import CoreModel |
39 | 44 | from dstack._internal.core.models.gateways import ( |
|
46 | 51 | InstanceOffer, |
47 | 52 | InstanceOfferWithAvailability, |
48 | 53 | ) |
49 | | -from dstack._internal.core.models.placement import PlacementGroup, PlacementGroupProvisioningData |
| 54 | +from dstack._internal.core.models.placement import ( |
| 55 | + PlacementGroup, |
| 56 | + PlacementGroupProvisioningData, |
| 57 | + PlacementStrategy, |
| 58 | +) |
50 | 59 | from dstack._internal.core.models.resources import Memory, Range |
51 | 60 | from dstack._internal.core.models.runs import JobProvisioningData, Requirements |
52 | 61 | from dstack._internal.core.models.volumes import ( |
@@ -334,6 +343,8 @@ def create_placement_group( |
334 | 343 | placement_group: PlacementGroup, |
335 | 344 | master_instance_offer: InstanceOffer, |
336 | 345 | ) -> PlacementGroupProvisioningData: |
| 346 | + if not _offer_supports_placement_group(master_instance_offer, placement_group): |
| 347 | + raise PlacementGroupNotSupportedError() |
337 | 348 | ec2_client = self.session.client("ec2", region_name=placement_group.configuration.region) |
338 | 349 | logger.debug("Creating placement group %s...", placement_group.name) |
339 | 350 | ec2_client.create_placement_group( |
@@ -370,6 +381,8 @@ def is_suitable_placement_group( |
370 | 381 | placement_group: PlacementGroup, |
371 | 382 | instance_offer: InstanceOffer, |
372 | 383 | ) -> bool: |
| 384 | + if not _offer_supports_placement_group(instance_offer, placement_group): |
| 385 | + return False |
373 | 386 | return ( |
374 | 387 | placement_group.configuration.backend == BackendType.AWS |
375 | 388 | and placement_group.configuration.region == instance_offer.region |
@@ -1059,6 +1072,15 @@ def _supported_instances(offer: InstanceOffer) -> bool: |
1059 | 1072 | return False |
1060 | 1073 |
|
1061 | 1074 |
|
| 1075 | +def _offer_supports_placement_group(offer: InstanceOffer, placement_group: PlacementGroup) -> bool: |
| 1076 | + if placement_group.configuration.placement_strategy != PlacementStrategy.CLUSTER: |
| 1077 | + return True |
| 1078 | + for family in ["t3.", "t2."]: |
| 1079 | + if offer.instance.name.startswith(family): |
| 1080 | + return False |
| 1081 | + return True |
| 1082 | + |
| 1083 | + |
1062 | 1084 | def _get_maximum_efa_interfaces(ec2_client: botocore.client.BaseClient, instance_type: str) -> int: |
1063 | 1085 | try: |
1064 | 1086 | response = ec2_client.describe_instance_types( |
|
0 commit comments