Skip to content

Commit 1207521

Browse files
feat: TPU *Create / *get / *create_with_script / *delete Samples (#12690)
* Added create /get / delete / create_startup_script TPU Samples with tests and NOX configuration * Update CODEOWNERS and blunderbuss.yml
1 parent 662f8d5 commit 1207521

File tree

10 files changed

+367
-0
lines changed

10 files changed

+367
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
/secretmanager/**/* @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers @GoogleCloudPlatform/cloud-secrets-team
3232
/securitycenter/**/* @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers @GoogleCloudPlatform/gcp-security-command-center
3333
/service_extensions/**/* @GoogleCloudPlatform/service-extensions-samples-reviewers @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
34+
/tpu/**/* @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
3435
/vmwareengine/**/* @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
3536
/webrisk/**/* @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/python-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers
3637

.github/blunderbuss.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ assign_issues_by:
2727
- "api: recaptchaenterprise"
2828
- "api: secretmanager"
2929
- "api: securitycenter"
30+
- "api: tpu"
3031
- "api: vmwareengine"
3132
to:
3233
- GoogleCloudPlatform/dee-infra
@@ -154,6 +155,7 @@ assign_prs_by:
154155
- "api: privateca"
155156
- "api: recaptchaenterprise"
156157
- "api: secretmanager"
158+
- "api: tpu"
157159
- "api: securitycenter"
158160
to:
159161
- GoogleCloudPlatform/dee-infra

tpu/create_tpu.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
16+
from google.cloud.tpu_v2 import Node
17+
18+
19+
def create_cloud_tpu(
20+
project_id: str,
21+
zone: str,
22+
tpu_name: str,
23+
tpu_type: str = "v2-8",
24+
runtime_version: str = "tpu-vm-tf-2.17.0-pjrt",
25+
) -> Node:
26+
"""Creates a Cloud TPU node.
27+
Args:
28+
project_id (str): The ID of the Google Cloud project.
29+
zone (str): The zone where the TPU node will be created.
30+
tpu_name (str): The name of the TPU node.
31+
tpu_type (str, optional): The type of TPU to create.
32+
runtime_version (str, optional): The runtime version for the TPU.
33+
Returns:
34+
Node: The created TPU node.
35+
"""
36+
# [START tpu_vm_create]
37+
from google.cloud import tpu_v2
38+
39+
# TODO(developer): Update and un-comment below lines
40+
# project_id = "your-project-id"
41+
# zone = "us-central1-b"
42+
# tpu_name = "tpu-name"
43+
# tpu_type = "v2-8"
44+
# runtime_version = "tpu-vm-tf-2.17.0-pjrt"
45+
46+
# Create a TPU node
47+
node = tpu_v2.Node()
48+
node.accelerator_type = tpu_type
49+
# To see available runtime version use command:
50+
# gcloud compute tpus versions list --zone={ZONE}
51+
node.runtime_version = runtime_version
52+
53+
request = tpu_v2.CreateNodeRequest(
54+
parent=f"projects/{project_id}/locations/{zone}",
55+
node_id=tpu_name,
56+
node=node,
57+
)
58+
59+
# Create a TPU client
60+
client = tpu_v2.TpuClient()
61+
operation = client.create_node(request=request)
62+
print("Waiting for operation to complete...")
63+
64+
response = operation.result()
65+
print(response)
66+
# Example response:
67+
# name: "projects/[project_id]/locations/[zone]/nodes/my-tpu"
68+
# accelerator_type: "v2-8"
69+
# state: READY
70+
# ...
71+
72+
# [END tpu_vm_create]
73+
return response
74+
75+
76+
if __name__ == "__main__":
77+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
78+
ZONE = "us-central1-b"
79+
create_cloud_tpu(PROJECT_ID, ZONE, "tpu-name")

tpu/create_tpu_with_script.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
16+
from google.cloud.tpu_v2 import Node
17+
18+
19+
def create_cloud_tpu_with_script(
20+
project_id: str,
21+
zone: str,
22+
tpu_name: str,
23+
tpu_type: str = "v2-8",
24+
runtime_version: str = "tpu-vm-tf-2.17.0-pjrt",
25+
) -> Node:
26+
# [START tpu_vm_create_startup_script]
27+
from google.cloud import tpu_v2
28+
29+
# TODO(developer): Update and un-comment below lines
30+
# project_id = "your-project-id"
31+
# zone = "us-central1-b"
32+
# tpu_name = "tpu-name"
33+
# tpu_type = "v2-8"
34+
# runtime_version = "tpu-vm-tf-2.17.0-pjrt"
35+
36+
node = tpu_v2.Node()
37+
node.accelerator_type = tpu_type
38+
node.runtime_version = runtime_version
39+
40+
# This startup script updates numpy to the latest version and logs the output to a file.
41+
metadata = {
42+
"startup-script": """#!/bin/bash
43+
echo "Hello World" > /var/log/hello.log
44+
sudo pip3 install --upgrade numpy >> /var/log/hello.log 2>&1
45+
"""
46+
}
47+
48+
# Adding metadata with startup script to the TPU node.
49+
node.metadata = metadata
50+
# Enabling external IPs for internet access from the TPU node.
51+
node.network_config = tpu_v2.NetworkConfig(enable_external_ips=True)
52+
53+
request = tpu_v2.CreateNodeRequest(
54+
parent=f"projects/{project_id}/locations/{zone}",
55+
node_id=tpu_name,
56+
node=node,
57+
)
58+
59+
client = tpu_v2.TpuClient()
60+
operation = client.create_node(request=request)
61+
print("Waiting for operation to complete...")
62+
63+
response = operation.result()
64+
print(response.metadata)
65+
# Example response:
66+
# {'startup-script': '#!/bin/bash\n echo "Hello World" > /var/log/hello.log\n
67+
# ...
68+
69+
# [END tpu_vm_create_startup_script]
70+
return response
71+
72+
73+
if __name__ == "__main__":
74+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
75+
ZONE = "us-central1-b"
76+
create_cloud_tpu_with_script(PROJECT_ID, ZONE, "tpu-name")

tpu/delete_tpu.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
16+
17+
def delete_cloud_tpu(project_id: str, zone: str, tpu_name: str = "tpu-name") -> None:
18+
"""Deletes a Cloud TPU node.
19+
Args:
20+
project_id (str): The ID of the Google Cloud project.
21+
zone (str): The zone where the TPU node is located.
22+
tpu_name (str, optional): The name of the TPU node.
23+
Returns: None
24+
"""
25+
# [START tpu_vm_delete]
26+
from google.cloud import tpu_v2
27+
28+
# TODO(developer): Update and un-comment below lines
29+
# project_id = "your-project-id"
30+
# zone = "us-central1-b"
31+
# tpu_name = "tpu-name"
32+
33+
client = tpu_v2.TpuClient()
34+
try:
35+
client.delete_node(
36+
name=f"projects/{project_id}/locations/{zone}/nodes/{tpu_name}"
37+
)
38+
print("The TPU node was deleted.")
39+
except Exception as e:
40+
print(e)
41+
42+
# [END tpu_vm_delete]
43+
44+
45+
if __name__ == "__main__":
46+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
47+
ZONE = "us-central1-b"
48+
delete_cloud_tpu(PROJECT_ID, ZONE, "tpu-name12")

tpu/get_tpu.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
16+
from google.cloud.tpu_v2 import Node
17+
18+
19+
def get_cloud_tpu(project_id: str, zone: str, tpu_name: str = "tpu-name") -> Node:
20+
"""Retrieves a Cloud TPU node.
21+
Args:
22+
project_id (str): The ID of the Google Cloud project.
23+
zone (str): The zone where the TPU node is located.
24+
tpu_name (str, optional): The name of the TPU node.
25+
Returns:
26+
Node: The retrieved TPU node.
27+
"""
28+
# [START tpu_vm_get]
29+
from google.cloud import tpu_v2
30+
31+
# TODO(developer): Update and un-comment below lines
32+
# project_id = "your-project-id"
33+
# zone = "us-central1-b"
34+
# tpu_name = "tpu-name"
35+
36+
client = tpu_v2.TpuClient()
37+
node = client.get_node(
38+
name=f"projects/{project_id}/locations/{zone}/nodes/{tpu_name}"
39+
)
40+
41+
print(node)
42+
# Example response:
43+
# name: "projects/[project_id]/locations/[zone]/nodes/tpu-name"
44+
# state: "READY"
45+
# runtime_version: ...
46+
47+
# [END tpu_vm_get]
48+
return node
49+
50+
51+
if __name__ == "__main__":
52+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
53+
ZONE = "us-central1-b"
54+
get_cloud_tpu(PROJECT_ID, ZONE, "tpu-name")

tpu/noxfile_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7", "3.7", "3.9", "3.10", "3.11"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {},
42+
}

tpu/requirements-test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==8.2.0

tpu/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
google-cloud-tpu==1.18.5
2+
3+

tpu/test_tpu.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
import uuid
16+
17+
from google.cloud.tpu_v2.types import Node
18+
19+
import pytest
20+
21+
import create_tpu
22+
import create_tpu_with_script
23+
import delete_tpu
24+
import get_tpu
25+
26+
TPU_NAME = "test-tpu-" + uuid.uuid4().hex[:10]
27+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
28+
ZONE = "us-south1-a"
29+
TPU_TYPE = "v5litepod-1"
30+
TPU_VERSION = "tpu-vm-tf-2.17.0-pjrt"
31+
32+
33+
# Instance of TPU
34+
@pytest.fixture(scope="session")
35+
def tpu_instance() -> Node:
36+
yield create_tpu.create_cloud_tpu(PROJECT_ID, ZONE, TPU_NAME, TPU_TYPE, TPU_VERSION)
37+
try:
38+
delete_tpu.delete_cloud_tpu(PROJECT_ID, ZONE, TPU_NAME)
39+
except Exception as e:
40+
print(f"Error during cleanup: {e}")
41+
42+
43+
def test_creating_tpu(tpu_instance: Node) -> None:
44+
assert tpu_instance.state == Node.State.READY
45+
46+
47+
def test_creating_with_startup_script() -> None:
48+
tpu_name_with_script = "script-tpu-" + uuid.uuid4().hex[:5]
49+
try:
50+
tpu_with_script = create_tpu_with_script.create_cloud_tpu_with_script(
51+
PROJECT_ID, ZONE, tpu_name_with_script, TPU_TYPE, TPU_VERSION
52+
)
53+
assert "--upgrade numpy" in tpu_with_script.metadata["startup-script"]
54+
finally:
55+
delete_tpu.delete_cloud_tpu(PROJECT_ID, ZONE, tpu_name_with_script)
56+
57+
58+
def test_get_tpu() -> None:
59+
tpu = get_tpu.get_cloud_tpu(PROJECT_ID, ZONE, TPU_NAME)
60+
assert tpu.state == Node.State.READY
61+
assert tpu.name == f"projects/{PROJECT_ID}/locations/{ZONE}/nodes/{TPU_NAME}"

0 commit comments

Comments
 (0)