From 0723df677956717257b94a8a97de75c7434fb372 Mon Sep 17 00:00:00 2001 From: Victor Skvortsov Date: Thu, 31 Oct 2024 16:36:10 +0500 Subject: [PATCH] Support GCP Shared VPC for some subnets (#1933) --- .../_internal/core/backends/gcp/resources.py | 18 +++++++++++++----- .../services/backends/configurators/gcp.py | 8 ++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/dstack/_internal/core/backends/gcp/resources.py b/src/dstack/_internal/core/backends/gcp/resources.py index e51574948..4d1397fda 100644 --- a/src/dstack/_internal/core/backends/gcp/resources.py +++ b/src/dstack/_internal/core/backends/gcp/resources.py @@ -56,7 +56,7 @@ def get_availability_zones( def check_vpc( - network_client: compute_v1.NetworksClient, + subnetworks_client: compute_v1.SubnetworksClient, routers_client: compute_v1.RoutersClient, project_id: str, regions: List[str], @@ -71,14 +71,21 @@ def check_vpc( if shared_vpc_project_id: vpc_project_id = shared_vpc_project_id try: - network_client.get(project=vpc_project_id, network=vpc_name) + for region in regions: + get_vpc_subnet_or_error( + subnetworks_client=subnetworks_client, + vpc_project_id=vpc_project_id, + vpc_name=vpc_name, + region=region, + ) except google.api_core.exceptions.NotFound: - raise ComputeError(f"Failed to find VPC {vpc_name} in project {vpc_project_id}") + raise ComputeError(f"Failed to find Shared VPC project {vpc_project_id}") if allocate_public_ip: return - if nat_check: + # We may have no permissions to check NAT in a shared VPC + if nat_check and shared_vpc_project_id is None: regions_without_nat = [] for region in regions: if not has_vpc_nat_access(routers_client, vpc_project_id, vpc_name, region): @@ -230,7 +237,8 @@ def get_vpc_subnet_or_error( if network_name == vpc_name and subnet_region == region: return subnet_resource_name raise ComputeError( - f"No usable subnetwork found in region {region} for VPC {vpc_name} in project {vpc_project_id}" + f"No usable subnetwork found in region {region} for VPC {vpc_name} in project {vpc_project_id}." + f" Ensure that VPC {vpc_name} exists and has usable subnetworks." ) diff --git a/src/dstack/_internal/server/services/backends/configurators/gcp.py b/src/dstack/_internal/server/services/backends/configurators/gcp.py index bbca96f66..8c45ae21e 100644 --- a/src/dstack/_internal/server/services/backends/configurators/gcp.py +++ b/src/dstack/_internal/server/services/backends/configurators/gcp.py @@ -221,11 +221,11 @@ def _get_regions_element( return element def _check_config(self, config: GCPConfigInfoWithCredsPartial, credentials: Credentials): - network_client = compute_v1.NetworksClient(credentials=credentials) + subnetworks_client = compute_v1.SubnetworksClient(credentials=credentials) routers_client = compute_v1.RoutersClient(credentials=credentials) self._check_tags_config(config) self._check_vpc_config( - network_client=network_client, + subnetworks_client=subnetworks_client, routers_client=routers_client, config=config, ) @@ -245,14 +245,14 @@ def _check_tags_config(self, config: GCPConfigInfoWithCredsPartial): def _check_vpc_config( self, config: GCPConfigInfoWithCredsPartial, - network_client: compute_v1.NetworksClient, + subnetworks_client: compute_v1.SubnetworksClient, routers_client: compute_v1.RoutersClient, ): allocate_public_ip = config.public_ips if config.public_ips is not None else True nat_check = config.nat_check if config.nat_check is not None else True try: resources.check_vpc( - network_client=network_client, + subnetworks_client=subnetworks_client, routers_client=routers_client, project_id=config.project_id, regions=config.regions or DEFAULT_REGIONS,