Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OFE: Add support for Shared VPCs. #2598

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -254,22 +254,36 @@ def get_region_zone_info(cloud_provider, credentials):

def _get_gcp_subnets(credentials):
(project, client) = _get_gcp_client(credentials)

entries = []
req = client.subnetworks().listUsable(project=project)
results = req.execute()
entries = results["items"]
if "items" in results:
entries = results["items"]
subnets = []
req = client.projects().getXpnHost(project=project)
results = req.execute()
if "name" in results:
host_project = results['name']
logger.debug("Found host project %s looking for additional subnets.", host_project)
req = client.subnetworks().listUsable(project=host_project)
results = req.execute()
entries_from_host_project = results["items"]
entries = entries + entries_from_host_project

for entry in entries:
# subnet in the form of https://www.googleapis.com/compute/v1/projects/<project>/regions/<region>/subnetworks/<name>
tokens = entry["subnetwork"].split("/")
region = tokens[8]
subnet = tokens[10]
subnet_self_link = entry["subnetwork"]
# vpc in the form of https://www.googleapis.com/compute/v1/projects/<project>/global/networks/<name>
tokens = entry["network"].split("/")
vpc = tokens[9]
vpc_self_link = entry["network"]
# cidr in standard form xxx.xxx.xxx.xxx/yy
cidr = entry["ipCidrRange"]
subnets.append([vpc, region, subnet, cidr])
subnets.append([vpc, region, subnet, cidr, vpc_self_link, subnet_self_link])

return subnets


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,37 @@ def _create_ssh_key(self, target_dir):
def indent_text(self, text, indent_level):
indent = ' ' * indent_level # 2 spaces per indent level, adjust as needed
return '\n'.join(indent + line if line else line for line in text.split('\n'))

def _prepare_subnetwork(self):
network_yaml = []
refs = []
if self.cluster.subnet.cloud_id.startswith("https://www.googleapis.com/compute/v1/projects"):
split_helper = self.cluster.subnet.vpc.cloud_id.split("/")
host_project = split_helper[len(split_helper)-4]
network_name = split_helper[len(split_helper)-1]
region = 'null'
subnetwork_name = 'null'
subnetwork_self_link = self.cluster.subnet.cloud_id
else:
subnetwork_name = self.cluster.subnet.cloud_id
region = self.cluster.subnet.cloud_region
host_project = self.cluster.project_id
subnetwork_self_link = 'null'

template = self.env.get_template('blueprint/network_config.yaml.j2')
context = {
'subnetwork_name': subnetwork_name,
'region': region,
'host_project': host_project,
'subnetwork_self_link': subnetwork_self_link

}
rendered_yaml = template.render(context)
indented_yaml = self.indent_text(rendered_yaml, 1) # Indent as necessary...
network_yaml.append(indented_yaml)

return ("\n\n".join(network_yaml), refs)


def _prepare_ghpc_filesystems(self):
filesystems_yaml = []
Expand Down Expand Up @@ -260,6 +291,7 @@ def _prepare_ghpc_yaml(self):
try:
yaml_file = self.cluster_dir / "cluster.yaml"
project_id = json.loads(self.cluster.cloud_credential.detail)["project_id"]
network_yaml, network_refs = self._prepare_subnetwork()
filesystems_yaml, filesystems_refs = self._prepare_ghpc_filesystems()
partitions_yaml, partitions_refs = self._prepare_ghpc_partitions(filesystems_refs)
cloudsql_yaml, cloudsql_refs = self._prepare_cloudsql_yaml() # Incorporate CloudSQL YAML
Expand All @@ -270,6 +302,7 @@ def _prepare_ghpc_yaml(self):
context = {
"project_id": project_id,
"site_name": SITE_NAME,
"network_yaml": network_yaml,
"filesystems_yaml": filesystems_yaml,
"partitions_yaml": partitions_yaml,
"cloudsql_yaml": cloudsql_yaml,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import json
import logging
import subprocess
import os
from pathlib import Path

from ..models import GCPFilestoreFilesystem, Filesystem, FilesystemImpl
Expand All @@ -34,7 +35,21 @@ def write_filestore_yaml(fs: GCPFilestoreFilesystem, target_dir: Path) -> None:
project_id = json.loads(fs.cloud_credential.detail)["project_id"]
# Get first (only) export
export_name = fs.exports.first().export_name
private_service_access = False

if fs.vpc.cloud_id.startswith("https://www.googleapis.com/compute/v1/"):
network_id = fs.vpc.cloud_id.replace("https://www.googleapis.com/compute/v1/","")
network_project = network_id.split("/")[-4]
if network_project != project_id:
private_service_access = True
else:
network_id = f"projects/{project_id}/global/networks/{fs.vpc.cloud_id}"

if private_service_access:
connect_mode = "PRIVATE_SERVICE_ACCESS"
else:
connect_mode = "DIRECT_PEERING"

with yaml_file.open("w") as f:
f.write(
f"""
Expand All @@ -56,7 +71,8 @@ def write_filestore_yaml(fs: GCPFilestoreFilesystem, target_dir: Path) -> None:
id: {fs.name}
settings:
filestore_share_name: {export_name[1:]}
network_id: projects/{project_id}/global/networks/{fs.vpc.cloud_id}
network_id: {network_id}
connect_mode: {connect_mode}
zone: {fs.cloud_zone}
size_gb: {fs.capacity}
filestore_tier: {fs.get_performance_tier_display()}
Expand Down Expand Up @@ -89,7 +105,7 @@ def create_filesystem(fs: Filesystem) -> None:
raise NotImplementedError("No support yet for this filesystem")


def _run_ghpc(target_dir: Path) -> None:
def _run_ghpc(target_dir: Path, env: dict) -> None:
ghpc_path = "/opt/gcluster/hpc-toolkit/ghpc"

try:
Expand All @@ -104,6 +120,7 @@ def _run_ghpc(target_dir: Path) -> None:
stdout=log_out,
stderr=log_err,
check=True,
env=env
)
except subprocess.CalledProcessError as cpe:
logger.error("ghpc exec failed", exc_info=cpe)
Expand All @@ -116,10 +133,10 @@ def start_filesystem(fs: Filesystem) -> None:
fs.cloud_state = "cm"
fs.save()
try:
_run_ghpc(_base_dir_for_fs(fs))
extra_env = {
"GOOGLE_APPLICATION_CREDENTIALS": _get_credentials_file(fs)
}
_run_ghpc(_base_dir_for_fs(fs),extra_env)
target_dir = _tf_dir_for_fs(fs)
utils.run_terraform(target_dir, "init")
utils.run_terraform(target_dir, "plan", extra_env=extra_env)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,7 @@ vars:
deployment_groups:
- group: primary
modules:
- source: modules/network/pre-existing-vpc
kind: terraform
settings:
network_name: {{ cluster.subnet.vpc.cloud_id }}
subnetwork_name: {{ cluster.subnet.cloud_id }}
id: hpc_network

- source: community/modules/network/private-service-access
id: ps-connect
use: [ hpc_network ]
{{ network_yaml | safe }}

{{ filesystems_yaml | safe }}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- source: modules/network/pre-existing-subnetwork
kind: terraform
settings:
subnetwork_name: {{ subnetwork_name }}
region: {{ region }}
host_project: {{ host_project_id }}
subnetwork_self_link: {{ subnetwork_self_link }}
id: hpc_network
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
subnets_info[vpc_component.value].forEach(function (item) {
var el = document.createElement("option");
el.text = item[0] + ' [CIDR: ' + item[2] + '] [region: ' + item[1] + ']';
el.setAttribute("value", item[0]);
el.setAttribute("value", item[4]);
subnet_element.appendChild(el);
});
}
Expand Down
41 changes: 27 additions & 14 deletions community/front-end/ofe/website/ghpcfe/views/vpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ def get_context_data(self, **kwargs):
used_in_filesystems = []
used_in_workbenches = []

for c in Cluster.objects.exclude(status="d"):
if vpc == c.subnet.vpc:
for c in Cluster.objects.exclude(status__in=["d","n"]):
if c.subnet is not None and vpc == c.subnet.vpc:
used_in_clusters.append(c)

for fs in Filesystem.objects.exclude(cloud_state__in=["cm", "m", "dm"]):
Expand Down Expand Up @@ -195,10 +195,19 @@ class VPCImportView2(SuperUserRequiredMixin, CreateView):
form_class = VPCImportForm

def get_initial(self):

vpc = []
for vpc_self_link in self.vpc_sub_map.keys():
vpc_split = vpc_self_link.split("/")
vpc_name = vpc_split[-1]
vpc_project = vpc_split[-4]
vpc_friendly_name = f"{vpc_name}@{vpc_project}"
vpc.append((vpc_self_link,vpc_friendly_name))

return {
"cloud_credential": self.cloud_credential,
"subnets": [(x[2], x[2]) for x in self.subnet_info],
"vpc": [(x, x) for x in self.vpc_sub_map.keys()],
"subnets": [(x[5], x[5]) for x in self.subnet_info],
"vpc": vpc,
}

def _setup_data(self, cred_id):
Expand All @@ -207,8 +216,8 @@ def _setup_data(self, cred_id):
"GCP", self.cloud_credential.detail
)
self.vpc_sub_map = defaultdict(list)
for (vpc, region, subnet, cidr) in self.subnet_info:
self.vpc_sub_map[vpc].append((subnet, region, cidr))
for (vpc, region, subnet, cidr, network_self_link, subnet_self_link) in self.subnet_info:
self.vpc_sub_map[network_self_link].append((subnet, region, cidr, network_self_link, subnet_self_link))

def get(self, request, *args, **kwargs):
self._setup_data(kwargs["credential"])
Expand All @@ -226,20 +235,22 @@ def form_valid(self, form):
self.object.save()
form_subnets = form.cleaned_data["subnets"]

def add_subnet(unused_vpc_name, region, subnet, cidr):
def add_subnet(unused_vpc_name, region, subnet, cidr, unused_network_self_link, subnet_self_link):
subnet_split = subnet_self_link.split("/")
subnet_name = subnet_split[-1]
vs = VirtualSubnet(
name=subnet,
name=subnet_name,
vpc=self.object,
cidr=cidr,
cloud_id=subnet,
cloud_id=subnet_self_link,
cloud_region=region,
cloud_state="i",
cloud_credential=self.cloud_credential,
)
vs.save()

for subnet in self.subnet_info:
if subnet[2] in form_subnets:
if subnet[5] in form_subnets:
add_subnet(*subnet)

return HttpResponseRedirect(self.get_success_url())
Expand Down Expand Up @@ -276,7 +287,7 @@ def get_initial(self):
initial["available_subnets"] = [
(x[2], x[2])
for x in subnet_info
if x[0] == self.get_object().cloud_id
if ((x[0] == self.get_object().cloud_id) or (x[4] == self.get_object().cloud_id))
]
initial["subnets"] = [
x.cloud_id for x in self.get_object().subnets.all()
Expand All @@ -289,12 +300,14 @@ def form_valid(self, form):

form_subnets = form.cleaned_data["subnets"]

def add_subnet(unused_vpc_name, region, subnet, cidr):
def add_subnet(unused_vpc_name, region, subnet, cidr, unused_network_self_link, subnet_self_link):
subnet_split = subnet_self_link.split("/")
subnet_name = subnet_split[-1]
vs = VirtualSubnet(
name=subnet,
name=subnet_name,
vpc=self.object,
cidr=cidr,
cloud_id=subnet,
cloud_id=subnet_self_link,
cloud_region=region,
cloud_state="i",
cloud_credential=self.object.cloud_credential,
Expand Down