@@ -259,6 +259,162 @@ def read_output():
259259 logger .error (f"Failed to start background process for { server_id } : { str (e )} " )
260260 return False
261261
262+ def _execute_aiperf_command (self , cmd : 'MarkdownCommand' , timeout : int = 120 ) -> bool :
263+ """Execute an AIPerf command inside a Docker container with Python 3.12"""
264+ logger .info (f"Executing AIPerf command in Docker container: { cmd .tag_name } " )
265+ logger .info (f"Location: { cmd .file_path } :{ cmd .start_line } -{ cmd .end_line } " )
266+
267+ # Always show command content
268+ logger .info (f"Original AIPerf command:\n { '-' * 50 } \n { cmd .command } \n { '-' * 50 } " )
269+
270+ # Get the current working directory and find repo root
271+ import os
272+ from pathlib import Path
273+ current_dir = os .getcwd ()
274+
275+ # Find the aiperf repository root (look for pyproject.toml or setup.py)
276+ repo_root = Path (current_dir )
277+ while repo_root != repo_root .parent :
278+ if (repo_root / 'pyproject.toml' ).exists () or (repo_root / 'setup.py' ).exists ():
279+ break
280+ repo_root = repo_root .parent
281+ else :
282+ # Fallback to current directory if not found
283+ repo_root = Path (current_dir )
284+
285+ repo_root_str = str (repo_root )
286+
287+ # Create Docker command that:
288+ # 1. Uses Python 3.12 image
289+ # 2. Mounts both current directory and repo root
290+ # 3. Sets working directory
291+ # 4. Installs python3-venv and required packages
292+ # 5. Creates virtual environment if needed
293+ # 6. Installs AIPerf from local repo/wheel
294+ # 7. Runs the AIPerf command
295+ # 8. Passes all host environment variables
296+ # Get all environment variables from host
297+ env_vars = []
298+ for key , value in os .environ .items ():
299+ # Escape special characters in environment variable values
300+ escaped_value = value .replace ('"' , '\\ "' ).replace ('$' , '\\ $' ).replace ('`' , '\\ `' )
301+ env_vars .append (f'-e { key } ="{ escaped_value } "' )
302+
303+ env_args = ' \\ \n ' .join (env_vars )
304+
305+ docker_command = f"""docker run --rm -i \\
306+ --network host \\
307+ -v "{ current_dir } :/workspace" \\
308+ -v "{ repo_root_str } :/aiperf_repo" \\
309+ -w /workspace \\
310+ { env_args } \\
311+ python:3.12-slim \\
312+ /bin/bash -c "
313+ set -e
314+ echo 'Installing system dependencies...'
315+ apt-get update -qq
316+ apt-get install -y -qq python3-venv curl jq git
317+ echo 'System dependencies installed successfully'
318+
319+ echo 'Setting up Python environment...'
320+ # Create virtual environment if it doesn't exist
321+ if [ ! -d '.venv' ]; then
322+ echo 'Creating virtual environment...'
323+ python3 -m venv .venv
324+ fi
325+
326+ # Ensure .venv/bin/python3 exists and is executable
327+ if [ ! -f '.venv/bin/python3' ]; then
328+ echo 'Recreating virtual environment...'
329+ rm -rf .venv
330+ python3 -m venv .venv
331+ fi
332+
333+ echo 'Virtual environment ready'
334+
335+ echo 'Setting up AIPerf environment...'
336+
337+ # Upgrade pip first to avoid issues
338+ .venv/bin/pip install --upgrade pip
339+
340+ # Install AIPerf from local source with all dependencies
341+ echo 'Installing AIPerf from local repository...'
342+ cd /aiperf_repo
343+
344+ # Check if there's a wheel in the repo
345+ if ls dist/*.whl 1> /dev/null 2>&1; then
346+ echo 'Found wheel file, installing from wheel...'
347+ /workspace/.venv/bin/pip install dist/*.whl
348+ else
349+ echo 'No wheel found, installing from source...'
350+ /workspace/.venv/bin/pip install .
351+ fi
352+
353+ cd /workspace
354+ echo 'AIPerf installation completed from local source'
355+
356+ # Verify aiperf command is available
357+ echo 'Verifying aiperf installation...'
358+ .venv/bin/aiperf --version || echo 'aiperf command verification failed'
359+
360+ # Ensure aiperf is in PATH for the command execution
361+ export PATH="/workspace/.venv/bin:\$PATH"
362+
363+ echo 'Executing AIPerf command:'
364+ { cmd .command .replace ('"' , '\\ "' ).replace ('$' , '\\ $' )}
365+ "
366+ """
367+
368+ logger .info (f"Repository root: { repo_root_str } " )
369+ logger .info (f"Working directory: { current_dir } " )
370+ logger .info (f"Docker command to execute:\n { '-' * 50 } \n { docker_command } \n { '-' * 50 } " )
371+
372+ logger .info ("=" * 60 )
373+ logger .info (f"REAL-TIME OUTPUT FOR: { cmd .tag_name } (Docker)" )
374+ logger .info ("=" * 60 )
375+
376+ try :
377+ # Use Popen for real-time output
378+ process = subprocess .Popen (
379+ docker_command ,
380+ shell = True ,
381+ stdout = subprocess .PIPE ,
382+ stderr = subprocess .STDOUT , # Combine stderr with stdout
383+ text = True ,
384+ bufsize = 1 , # Line buffered
385+ universal_newlines = True
386+ )
387+
388+ output_lines = []
389+
390+ # Read output in real-time
391+ while True :
392+ output = process .stdout .readline ()
393+ if output == '' and process .poll () is not None :
394+ break
395+ if output :
396+ # Print to console immediately
397+ print (output .strip ())
398+ output_lines .append (output )
399+
400+ # Wait for process to complete
401+ return_code = process .wait (timeout = timeout )
402+
403+ if return_code == 0 :
404+ logger .info (f"AIPerf command '{ cmd .tag_name } ' completed successfully in Docker container" )
405+ return True
406+ else :
407+ logger .error (f"AIPerf command '{ cmd .tag_name } ' failed in Docker container with return code: { return_code } " )
408+ return False
409+
410+ except subprocess .TimeoutExpired :
411+ logger .error (f"AIPerf command '{ cmd .tag_name } ' timed out after { timeout } seconds" )
412+ process .kill ()
413+ return False
414+ except Exception as e :
415+ logger .error (f"Error executing AIPerf command '{ cmd .tag_name } ' in Docker container: { e } " )
416+ return False
417+
262418 def _execute_command (self , cmd : 'MarkdownCommand' , timeout : int = 120 ) -> bool :
263419 """Execute a single command with real-time output"""
264420 logger .info (f"Executing command: { cmd .tag_name } " )
0 commit comments