diff --git a/src/dstack/_internal/core/backends/oci/compute.py b/src/dstack/_internal/core/backends/oci/compute.py index ab9be4908b..f5f839771b 100644 --- a/src/dstack/_internal/core/backends/oci/compute.py +++ b/src/dstack/_internal/core/backends/oci/compute.py @@ -35,6 +35,13 @@ from dstack._internal.core.models.resources import Memory, Range from dstack._internal.core.models.runs import JobProvisioningData, Requirements +# Shape families that dstack's x86-64 OCI Marketplace images can run. GPU shapes are limited to +# NVIDIA GPUs on x86-64 hosts because the images ship CUDA drivers only. Other GPU shapes from +# the gpuhunt catalog are deliberately left out: +# - BM.GPU.MI300X.*, BM.GPU.MI355X.* (AMD Instinct): no ROCm image is published, and +# `create_instance` picks the CUDA image for any GPU offer. +# - BM.GPU.GB200.*, BM.GPU.GB300.* (Grace superchips): arm64 hosts, no arm64 image is published. +# See https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm SUPPORTED_SHAPE_FAMILIES = [ "VM.Standard2.", "BM.Standard2.", @@ -48,6 +55,13 @@ "BM.GPU4.", "VM.GPU.A10.", "BM.GPU.A10.", + "BM.GPU.A100-v2.", + "BM.GPU.L40S.", + "BM.GPU.H100.", + "BM.GPU.H200.", + "BM.GPU.B200.", + "BM.GPU.B300.", + "BM.GPU.RTXPRO.", ] CONFIGURABLE_DISK_SIZE = Range[Memory](min=Memory.parse("50GB"), max=Memory.parse("32TB")) diff --git a/src/dstack/_internal/core/backends/oci/configurator.py b/src/dstack/_internal/core/backends/oci/configurator.py index 95696330e7..8fc6aa57c3 100644 --- a/src/dstack/_internal/core/backends/oci/configurator.py +++ b/src/dstack/_internal/core/backends/oci/configurator.py @@ -28,7 +28,9 @@ ) from dstack._internal.core.models.common import validate_extra_ignore, validate_json_extra_ignore -# where dstack images are published +# Regions where dstack publishes its VM images as OCI Marketplace community listings +# (see scripts/oci_image_tools.py). Listings are regional, so instances can only be launched +# in regions that have the images. Extend this set only together with publishing the images. SUPPORTED_REGIONS = frozenset( [ "eu-frankfurt-1", diff --git a/src/tests/_internal/core/backends/oci/test_compute.py b/src/tests/_internal/core/backends/oci/test_compute.py new file mode 100644 index 0000000000..51644c7c3b --- /dev/null +++ b/src/tests/_internal/core/backends/oci/test_compute.py @@ -0,0 +1,66 @@ +import pytest + +from dstack._internal.core.backends.oci.compute import _supported_instances +from dstack._internal.core.models.backends.base import BackendType +from dstack._internal.core.models.instances import ( + InstanceOffer, + InstanceType, + Resources, +) + + +def make_offer(shape_name: str) -> InstanceOffer: + return InstanceOffer( + backend=BackendType.OCI, + instance=InstanceType( + name=shape_name, + resources=Resources(cpus=8, memory_mib=64 * 1024, gpus=[], spot=False), + ), + region="us-chicago-1", + price=1.0, + ) + + +class TestSupportedInstances: + @pytest.mark.parametrize( + "shape_name", + [ + "VM.Standard2.1", + "BM.Standard.E5.192", + "VM.GPU3.1", + "BM.GPU4.8", + "VM.GPU.A10.1", + "BM.GPU.A10.4", + "BM.GPU.A100-v2.8", + "BM.GPU.L40S.4", + "BM.GPU.H100.8", + "BM.GPU.H200.8", + "BM.GPU.B200.8", + "BM.GPU.B300.8", + "BM.GPU.RTXPRO.8", + ], + ) + def test_supported(self, shape_name: str): + assert _supported_instances(make_offer(shape_name)) + + @pytest.mark.parametrize( + "shape_name", + [ + # Flex shapes need OCPU/memory configuration + "VM.Standard.E4.Flex", + "VM.Optimized3.Flex", + # Ampere A1 Arm CPUs and Grace superchips: no arm64 image + "VM.Standard.A1.Flex", + "BM.Standard.A1.160", + "BM.GPU.GB200.4", + "BM.GPU.GB300.4", + # AMD Instinct: no ROCm image + "BM.GPU.MI300X.8", + "BM.GPU.MI355X.8", + # Deprecated families + "BM.GPU2.2", + "VM.GPU2.1", + ], + ) + def test_unsupported(self, shape_name: str): + assert not _supported_instances(make_offer(shape_name))