Skip to content

Commit aaeb201

Browse files
authored
Support internal IP and cluster placement for jarvislabs (#4247)
1 parent 69c6552 commit aaeb201

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

mkdocs/docs/concepts/backends.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,9 @@ projects:
952952

953953
</div>
954954

955+
??? info "Cluster placement"
956+
Fleets with `placement: cluster` are supported in the `india-chennai-01` and `india-noida-01` regions, where instances join the account's default [VPC](https://docs.jarvislabs.ai/vpc/) and communicate over private IPs. No additional configuration is required.
957+
955958
### CloudRift
956959

957960
Log into your [CloudRift](https://console.cloudrift.ai/) console, click `API Keys` in the sidebar and click the button to create a new API key.

src/dstack/_internal/core/backends/jarvislabs/compute.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import subprocess
33
import tempfile
44
from collections.abc import Iterable
5-
from typing import List, Optional, cast
5+
from typing import Callable, List, Optional, cast
66

77
import gpuhunt
88
from gpuhunt.providers.jarvislabs import JarvisLabsProvider
@@ -13,6 +13,7 @@
1313
ComputeWithAllOffersCached,
1414
ComputeWithCreateInstanceSupport,
1515
ComputeWithInstanceVolumesSupport,
16+
ComputeWithMultinodeSupport,
1617
ComputeWithPrivilegedSupport,
1718
generate_unique_instance_name,
1819
get_shim_commands,
@@ -47,6 +48,11 @@
4748
SSH_CONNECT_TIMEOUT_SECONDS = 10
4849
SSH_SETUP_TIMEOUT_SECONDS = 240
4950
SSH_LAUNCH_TIMEOUT_SECONDS = 60
51+
# VMs in these regions join the account's default VPC and get a private IP that is
52+
# routable between VMs of the same account. Other regions have no VPC, so their
53+
# private IPs cannot be used for inter-node communication.
54+
# See https://docs.jarvislabs.ai/vpc/
55+
VPC_REGIONS = frozenset({"india-chennai-01", "india-noida-01"})
5056

5157

5258
class JarvisLabsOfferBackendData(TypedDict):
@@ -70,6 +76,7 @@ class JarvisLabsCompute(
7076
ComputeWithCreateInstanceSupport,
7177
ComputeWithPrivilegedSupport,
7278
ComputeWithInstanceVolumesSupport,
79+
ComputeWithMultinodeSupport,
7380
Compute,
7481
):
7582
def __init__(self, config: JarvisLabsConfig):
@@ -98,6 +105,13 @@ def get_offers_modifiers(
98105
) -> Iterable[OfferModifier]:
99106
return [get_offers_disk_modifier(CONFIGURABLE_DISK_SIZE, requirements)]
100107

108+
def get_offers_post_filter(
109+
self, requirements: Requirements
110+
) -> Optional[Callable[[InstanceOfferWithAvailability], bool]]:
111+
if not requirements.multinode:
112+
return None
113+
return lambda offer: offer.region in VPC_REGIONS
114+
101115
def create_instance(
102116
self,
103117
instance_offer: InstanceOfferWithAvailability,
@@ -207,6 +221,7 @@ def update_provisioning_data(
207221
return
208222
provisioning_data.hostname = hostname
209223
provisioning_data.username = username
224+
provisioning_data.internal_ip = _get_internal_ip(instance)
210225

211226
def terminate_instance(
212227
self, instance_id: str, region: str, backend_data: Optional[str] = None
@@ -261,6 +276,16 @@ def _raise_failed_status(status: dict) -> None:
261276
raise ProvisioningError(_format_failed_status(status), status)
262277

263278

279+
def _get_internal_ip(instance: dict) -> Optional[str]:
280+
# Private IPs of VMs outside a VPC are not routable between VMs.
281+
if not instance.get("vpc_id"):
282+
return None
283+
private_ip = instance.get("private_ip")
284+
if not isinstance(private_ip, str) or not private_ip:
285+
return None
286+
return private_ip
287+
288+
264289
def _get_ssh_username(instance: dict) -> str:
265290
ssh_command = instance.get("ssh_str") or instance.get("ssh_command")
266291
if not isinstance(ssh_command, str):

0 commit comments

Comments
 (0)