77It creates the necessary access pod, downloads the files, and cleans up automatically.
88
99Usage:
10- python3 download_pvc_results.py --namespace <namespace> --output-dir <local_directory>
10+ python3 download_pvc_results.py --namespace <namespace> --output-dir <local_directory> [--no-config]
1111
1212Examples:
1313 # Download to ./results directory
1414 python3 download_pvc_results.py --namespace <namespace> --output-dir ./results
1515
1616 # Download to specific directory
1717 python3 download_pvc_results.py --namespace <namespace> --output-dir /home/user/profiling_data
18+
19+ # Download without configuration files
20+ python3 download_pvc_results.py --namespace <namespace> --output-dir ./results --no-config
1821"""
1922
2023import argparse
@@ -57,7 +60,7 @@ def deploy_access_pod(namespace: str) -> str:
5760
5861 # Check if pod already exists and is running
5962 try :
60- result = run_command (
63+ result = subprocess . run (
6164 [
6265 "kubectl" ,
6366 "get" ,
@@ -69,12 +72,14 @@ def deploy_access_pod(namespace: str) -> str:
6972 "jsonpath={.status.phase}" ,
7073 ],
7174 capture_output = True ,
75+ text = True ,
76+ check = False ,
7277 )
7378
74- if result .stdout .strip () == "Running" :
79+ if result .returncode == 0 and result . stdout .strip () == "Running" :
7580 print (f"✓ Access pod '{ pod_name } ' already running" )
7681 return pod_name
77- except subprocess . CalledProcessError :
82+ except Exception :
7883 # Pod doesn't exist or isn't running
7984 pass
8085
@@ -99,7 +104,7 @@ def deploy_access_pod(namespace: str) -> str:
99104 # Wait for pod to be ready (up to 60 seconds)
100105 for i in range (60 ):
101106 try :
102- result = run_command (
107+ result = subprocess . run (
103108 [
104109 "kubectl" ,
105110 "get" ,
@@ -111,13 +116,15 @@ def deploy_access_pod(namespace: str) -> str:
111116 "jsonpath={.status.phase}" ,
112117 ],
113118 capture_output = True ,
119+ text = True ,
120+ check = False ,
114121 )
115122
116- if result .stdout .strip () == "Running" :
123+ if result .returncode == 0 and result . stdout .strip () == "Running" :
117124 print ("✓ Access pod is ready" )
118125 return pod_name
119126
120- except subprocess . CalledProcessError :
127+ except Exception :
121128 pass
122129
123130 time .sleep (1 )
@@ -128,40 +135,50 @@ def deploy_access_pod(namespace: str) -> str:
128135 sys .exit (1 )
129136
130137
131- def list_pvc_contents (namespace : str , pod_name : str ) -> List [str ]:
138+ def list_pvc_contents (
139+ namespace : str , pod_name : str , skip_config : bool = False
140+ ) -> List [str ]:
132141 """List contents of the PVC to identify relevant files."""
133142 print ("Scanning PVC contents..." )
134143
135- try :
136- result = run_command (
144+ # Build find command with optional config file exclusion
145+ find_cmd = [
146+ "kubectl" ,
147+ "exec" ,
148+ pod_name ,
149+ "-n" ,
150+ namespace ,
151+ "--" ,
152+ "find" ,
153+ "/profiling_results" ,
154+ "-type" ,
155+ "f" ,
156+ "-name" ,
157+ "*.png" ,
158+ "-o" ,
159+ "-name" ,
160+ "*.npz" ,
161+ ]
162+
163+ # Add config file patterns if not skipping them
164+ if not skip_config :
165+ find_cmd .extend (
137166 [
138- "kubectl" ,
139- "exec" ,
140- pod_name ,
141- "-n" ,
142- namespace ,
143- "--" ,
144- "find" ,
145- "/profiling_results" ,
146- "-type" ,
147- "f" ,
148- "-name" ,
149- "*.png" ,
150- "-o" ,
151- "-name" ,
152- "*.npz" ,
153167 "-o" ,
154168 "-name" ,
155169 "*.yaml" ,
156170 "-o" ,
157171 "-name" ,
158172 "*.yml" ,
159- ],
160- capture_output = True ,
173+ ]
161174 )
162175
176+ try :
177+ result = run_command (find_cmd , capture_output = True )
178+
163179 files = [f .strip () for f in result .stdout .split ("\n " ) if f .strip ()]
164- print (f"Found { len (files )} relevant files to download" )
180+ config_note = " (excluding config files)" if skip_config else ""
181+ print (f"Found { len (files )} relevant files to download{ config_note } " )
165182 return files
166183
167184 except subprocess .CalledProcessError :
@@ -213,20 +230,27 @@ def download_files(
213230 print (f"✓ Download completed: { downloaded } successful, { failed } failed" )
214231
215232
216- def download_summary_files (namespace : str , pod_name : str , output_dir : Path ) -> None :
233+ def download_summary_files (
234+ namespace : str , pod_name : str , output_dir : Path , skip_config : bool = False
235+ ) -> None :
217236 """Download key summary files that might not match the pattern."""
218237 summary_files = [
219238 "/profiling_results/prefill_performance.png" ,
220239 "/profiling_results/decode_performance.png" ,
221- "/profiling_results/disagg.yaml" , # In case it was injected
222240 ]
223241
242+ # Add config files if not skipping them
243+ if not skip_config :
244+ summary_files .append (
245+ "/profiling_results/disagg.yaml"
246+ ) # In case it was injected
247+
224248 print ("Downloading summary files..." )
225249
226250 for file_path in summary_files :
227251 try :
228- # Check if file exists first
229- run_command (
252+ # Check if file exists first using subprocess.run directly
253+ result = subprocess . run (
230254 [
231255 "kubectl" ,
232256 "exec" ,
@@ -239,8 +263,14 @@ def download_summary_files(namespace: str, pod_name: str, output_dir: Path) -> N
239263 file_path ,
240264 ],
241265 capture_output = True ,
266+ text = True ,
267+ check = False ,
242268 )
243269
270+ if result .returncode != 0 :
271+ # File doesn't exist, skip silently
272+ continue
273+
244274 # File exists, download it
245275 rel_path = file_path .replace ("/profiling_results/" , "" )
246276 local_file = output_dir / rel_path
@@ -258,8 +288,9 @@ def download_summary_files(namespace: str, pod_name: str, output_dir: Path) -> N
258288
259289 print (f" ✓ { rel_path } " )
260290
261- except subprocess . CalledProcessError :
291+ except Exception as e :
262292 # File doesn't exist or failed to download, skip silently
293+ print (f" ⚠️ Skipped { file_path .split ('/' )[- 1 ]} : { e } " )
263294 pass
264295
265296
@@ -342,6 +373,12 @@ def main():
342373 help = "Local directory to download results to" ,
343374 )
344375
376+ parser .add_argument (
377+ "--no-config" ,
378+ action = "store_true" ,
379+ help = "Skip downloading configuration files (*.yaml, *.yml)" ,
380+ )
381+
345382 args = parser .parse_args ()
346383
347384 print ("📥 PVC Results Download" )
@@ -354,11 +391,11 @@ def main():
354391 pod_name = deploy_access_pod (args .namespace )
355392
356393 # List and download files
357- files = list_pvc_contents (args .namespace , pod_name )
394+ files = list_pvc_contents (args .namespace , pod_name , args . no_config )
358395 download_files (args .namespace , pod_name , files , args .output_dir )
359396
360397 # Download additional summary files
361- download_summary_files (args .namespace , pod_name , args .output_dir )
398+ download_summary_files (args .namespace , pod_name , args .output_dir , args . no_config )
362399
363400 # Generate README
364401 generate_readme (args .output_dir , len (files ))
0 commit comments