1616
1717import datetime
1818
19- from airflow .decorators import task
2019from airflow import models
20+ from airflow .decorators import task
2121from airflow .utils .trigger_rule import TriggerRule
2222from airflow .utils .task_group import TaskGroup
2323
24- from dags . common . vm_resource import Region , Zone
24+ from dags import composer_env
2525from dags .tpu_observability .utils import jobset_util as jobset
2626from dags .tpu_observability .utils import node_pool_util as node_pool
2727from dags .tpu_observability .utils .jobset_util import JobSet , Workload
28- from dags .tpu_observability .configs .common import MachineConfigMap
29- from dags import composer_env
30-
31- # Can be moved to jobset_util.py
32- @task .sensor (poke_interval = 30 , timeout = 900 , mode = "reschedule" )
33- def validate_replica_number (
34- node_pool : node_pool .Info ,
35- jobset_config : JobSet ,
36- replica_type : str ,
37- replica_num : int
38- ):
39- found_replia_num = jobset .get_replica_num (
40- replica_type = replica_type ,
41- job_name = jobset_config .replicated_job_name ,
42- node_pool = node_pool
43- )
44-
45- return (found_replia_num == replica_num )
28+ from dags .tpu_observability .configs .common import MachineConfigMap , GCS_CONFIG_PATH
4629
4730
4831# Keyword arguments are generated dynamically at runtime (pylint does not
4932# know this signature).
5033with models .DAG ( # pylint: disable=unexpected-keyword-arg
5134 dag_id = "jobset_healthiness_ready" ,
5235 start_date = datetime .datetime (2025 , 8 , 10 ),
53- schedule = "00 03 * * *" ,
36+ schedule = "30 19 * * *" if composer_env . is_prod_env () else None ,
5437 catchup = False ,
5538 tags = [
5639 "cloud-ml-auto-solutions" ,
@@ -85,54 +68,15 @@ def validate_replica_number(
8568 match the DAG is a success.
8669 """ ,
8770) as dag :
88- cluster_name = "tpu-observability-automation"
89- cluster_name += "-prod" if composer_env .is_prod_env () else "-dev"
90-
9171 for machine in MachineConfigMap :
9272 config = machine .value
93- cluster_info = node_pool .Info (
94- project_id = models .Variable .get ("PROJECT_ID" , default_var = "cienet-cmcs" ),
95- cluster_name = models .Variable .get (
96- "CLUSTER_NAME" , default_var = cluster_name
97- ),
98- node_pool_name = models .Variable .get (
99- "NODE_POOL_NAME" , default_var = "jobset-healthiness-ready-v6e"
100- ),
101- region = models .Variable .get (
102- "REGION" , default_var = Region .US_CENTRAL1 .value
103- ),
104- location = models .Variable .get (
105- "LOCATION" , default_var = Region .US_CENTRAL1 .value
106- ),
107- node_locations = models .Variable .get (
108- "LOCATIONS" , default_var = Zone .US_CENTRAL1_B .value
109- ),
110- num_nodes = models .Variable .get ("NUM_NODES" , default_var = 4 ),
111- machine_type = config .machine_version .value ,
112- tpu_topology = config .tpu_topology ,
113- )
11473
115- cluster_info_2 = node_pool .Info (
116- project_id = models .Variable .get ("PROJECT_ID" , default_var = "cienet-cmcs" ),
117- cluster_name = models .Variable .get (
118- "CLUSTER_NAME" , default_var = cluster_name
119- ),
120- node_pool_name = models .Variable .get (
121- "NODE_POOL_NAME" , default_var = "jobset-healthiness-ready-v6e-2"
122- ),
123- region = models .Variable .get (
124- "REGION" , default_var = Region .US_CENTRAL1 .value
125- ),
126- location = models .Variable .get (
127- "LOCATION" , default_var = Region .US_CENTRAL1 .value
128- ),
129- node_locations = models .Variable .get (
130- "LOCATIONS" , default_var = Zone .US_CENTRAL1_B .value
131- ),
132- num_nodes = models .Variable .get ("NUM_NODES" , default_var = 4 ),
133- machine_type = config .machine_version .value ,
134- tpu_topology = config .tpu_topology ,
135- )
74+ @task
75+ def generate_second_node_pool_name (
76+ node_pool_info : node_pool .Info ,
77+ ) -> str :
78+ """Generates a second node pool name."""
79+ return f"{ node_pool_info .node_pool_name } -2"
13680
13781 jobset_config = JobSet (
13882 jobset_name = "jobset-healthiness-ready" ,
@@ -155,36 +99,60 @@ def validate_replica_number(
15599 with TaskGroup ( # pylint: disable=unexpected-keyword-arg
156100 group_id = f"v{ config .tpu_version .value } "
157101 ):
158- create_node_pool = node_pool .create (
159- node_pool = cluster_info ,
160- reservation = "cloudtpu-20251107233000-1246578561" ,
102+ cluster_info = node_pool .build_node_pool_info_from_gcs_yaml .override (
103+ task_id = "build_node_pool_info_from_gcs_yaml"
104+ )(
105+ gcs_path = GCS_CONFIG_PATH ,
106+ dag_name = "jobset_healthiness_ready" ,
107+ is_prod = composer_env .is_prod_env (),
108+ machine_type = config .machine_version .value ,
109+ tpu_topology = config .tpu_topology ,
161110 )
162111
163- create_node_pool_2 = node_pool .create (
164- node_pool = cluster_info_2 ,
165- reservation = "cloudtpu-20251107233000-1246578561" ,
112+ cluster_info_2 = node_pool .copy_node_pool_info_with_override (
113+ info = cluster_info ,
114+ node_pool_name = generate_second_node_pool_name ( cluster_info ) ,
166115 )
167116
168- validate_zero_replicas = validate_replica_number (
117+ # Keyword arguments are generated dynamically at runtime (pylint does not
118+ # know this signature).
119+ with TaskGroup ( # pylint: disable=unexpected-keyword-arg
120+ group_id = "create_node_pool"
121+ ) as create_node_pool :
122+ create_first_node_pool = node_pool .create .override (
123+ task_id = "node_pool_1" ,
124+ retries = 2 ,
125+ )(
126+ node_pool = cluster_info ,
127+ )
128+
129+ create_second_node_pool = node_pool .create .override (
130+ task_id = "node_pool_2" ,
131+ retries = 2 ,
132+ )(
133+ node_pool = cluster_info_2 ,
134+ )
135+
136+ validate_zero_replicas = jobset .validate_jobset_replica_number (
169137 node_pool = cluster_info ,
170138 jobset_config = jobset_config ,
171139 replica_type = "ready" ,
172- replica_num = 0
140+ correct_replica_num = 0 ,
173141 )
174142
175143 start_workload = jobset .run_workload (
176144 node_pool = cluster_info ,
177145 yaml_config = jobset_config .generate_yaml (
178- workload_script = Workload .READY_TPU
146+ workload_script = Workload .IDLE_READY_TPU_20M
179147 ),
180148 namespace = jobset_config .namespace ,
181149 )
182150
183- validate_ready_replicas = validate_replica_number (
151+ validate_ready_replicas = jobset . validate_jobset_replica_number (
184152 node_pool = cluster_info ,
185153 jobset_config = jobset_config ,
186154 replica_type = "ready" ,
187- replica_num = jobset_config .replicas
155+ correct_replica_num = jobset_config .replicas ,
188156 )
189157
190158 cleanup_workload = jobset .end_workload .override (
@@ -197,29 +165,38 @@ def validate_replica_number(
197165 setups = start_workload
198166 )
199167
200- cleanup_node_pool = node_pool .delete .override (
201- task_id = "cleanup_node_pool" , trigger_rule = TriggerRule .ALL_DONE
202- )(node_pool = cluster_info ).as_teardown (
203- setups = create_node_pool ,
204- )
205-
206- cleanup_node_pool_2 = node_pool .delete .override (
207- task_id = "cleanup_node_pool" , trigger_rule = TriggerRule .ALL_DONE
208- )(node_pool = cluster_info_2 ).as_teardown (
209- setups = create_node_pool_2 ,
210- )
168+ # Keyword arguments are generated dynamically at runtime (pylint does not
169+ # know this signature).
170+ with TaskGroup ( # pylint: disable=unexpected-keyword-arg
171+ group_id = "cleanup_node_pool"
172+ ) as cleanup_node_pool :
173+ cleanup_first_node_pool = node_pool .delete .override (
174+ task_id = "cleanup_node_pool_1" ,
175+ trigger_rule = TriggerRule .ALL_DONE ,
176+ retries = 2 ,
177+ )(node_pool = cluster_info ).as_teardown (
178+ setups = create_node_pool ,
179+ )
180+
181+ cleanup_second_node_pool = node_pool .delete .override (
182+ task_id = "cleanup_node_pool_2" ,
183+ trigger_rule = TriggerRule .ALL_DONE ,
184+ retries = 2 ,
185+ )(node_pool = cluster_info_2 ).as_teardown (
186+ setups = create_node_pool ,
187+ )
211188
212189 # Airflow uses >> for task chaining, which is pointless for pylint.
213190 # pylint: disable=pointless-statement
214191 (
215- create_node_pool
216- >> create_node_pool_2
192+ cluster_info
193+ >> cluster_info_2
194+ >> create_node_pool
217195 >> validate_zero_replicas
218196 >> start_workload
219197 >> validate_ready_replicas
220198 >> cleanup_workload
221199 >> cleanup_node_pool
222- >> cleanup_node_pool_2
223200
224201 )
225202 # pylint: enable=pointless-statement
0 commit comments