@@ -482,4 +482,55 @@ async def get_running_bots_status(user_id: int) -> List[Dict[str, Any]]:
482
482
})
483
483
484
484
return bots_status
485
- # --- END: Get Running Bot Status ---
485
+ # --- END: Get Running Bot Status ---
486
+
487
+ async def verify_container_running (container_id : str ) -> bool :
488
+ """Verify if a container exists and is running via the Docker socket API."""
489
+ session = get_socket_session () # Assumes get_socket_session() is defined in this file
490
+ if not session :
491
+ logger .error (f"[Verify Container] Cannot verify container { container_id } , requests_unixsocket session not available." )
492
+ return False # Or raise an exception, depending on desired error handling
493
+
494
+ # Construct the correct base URL for socket requests
495
+ # This logic should mirror how other Docker API calls are made in this file
496
+ # For example, if DOCKER_HOST is 'unix:///var/run/docker.sock'
497
+ socket_path_relative = DOCKER_HOST .split ('//' , 1 )[1 ]
498
+ socket_path_abs = f"/{ socket_path_relative } "
499
+ socket_path_encoded = socket_path_abs .replace ("/" , "%2F" )
500
+ socket_url_base = f'http+unix://{ socket_path_encoded } '
501
+
502
+ inspect_url = f'{ socket_url_base } /containers/{ container_id } /json'
503
+
504
+ try :
505
+ logger .debug (f"[Verify Container] Inspecting container { container_id } via URL: { inspect_url } " )
506
+ # Make the request asynchronously. Requires session to be an AIOHTTP client or similar.
507
+ # If get_socket_session() returns a synchronous requests.Session, this needs to run in a thread.
508
+ # Assuming for now that session can handle async requests or this will be wrapped.
509
+ # For a synchronous session, it would be:
510
+ # response = await asyncio.to_thread(session.get, inspect_url)
511
+
512
+ # If get_socket_session() returns a regular requests.Session:
513
+ import asyncio
514
+ loop = asyncio .get_event_loop ()
515
+ response = await loop .run_in_executor (None , session .get , inspect_url )
516
+
517
+ if response .status_code == 404 :
518
+ logger .info (f"[Verify Container] Container { container_id } not found (404)." )
519
+ return False
520
+
521
+ response .raise_for_status () # Raise an exception for other bad status codes (500, etc.)
522
+
523
+ container_info = response .json ()
524
+ is_running = container_info .get ('State' , {}).get ('Running' , False )
525
+ logger .info (f"[Verify Container] Container { container_id } found. Running: { is_running } " )
526
+ return is_running
527
+
528
+ except requests .exceptions .RequestException as e : # Catching requests-specific exceptions
529
+ if hasattr (e , 'response' ) and e .response is not None and e .response .status_code == 404 :
530
+ logger .warning (f"[Verify Container] Container { container_id } not found during request (exception check)." )
531
+ return False
532
+ logger .error (f"[Verify Container] HTTP error inspecting container { container_id } : { e } " , exc_info = True )
533
+ return False # Treat HTTP errors (other than 404) as "not verifiable" or "not running"
534
+ except Exception as e :
535
+ logger .error (f"[Verify Container] Unexpected error inspecting container { container_id } : { e } " , exc_info = True )
536
+ return False # Treat other errors as "not verifiable" or "not running"
0 commit comments