66import select
77import shutil
88import subprocess
9+ import tempfile
910import time
11+ from pathlib import Path
1012from threading import Thread
1113
1214from provisioner .context import Context
1618
1719context = Context .get ()
1820logger = context .logger
21+ stdout_copy_folder = Path ("dev_shm" if context .fake_pi else "/dev/shm" )
1922
2023
2124class RpiImager :
@@ -24,7 +27,7 @@ class RpiImager:
2427 stdout : str
2528 ps : subprocess .Popen [str ]
2629
27- def __init__ (self , args : list [str ]) -> None :
30+ def __init__ (self , args : list [str ], copy_stdout_to : Path | None = None ) -> None :
2831 self .args = args
2932
3033 self .started_on : datetime .datetime = datetime .datetime .now (tz = datetime .UTC )
@@ -48,10 +51,11 @@ def __init__(self, args: list[str]) -> None:
4851
4952 self .output_reader = Thread (target = self .consume_pty )
5053
54+ self .stdout_copy : Path | None = copy_stdout_to
55+
5156 def start (
5257 self ,
5358 ):
54-
5559 self .ps = subprocess .Popen (
5660 self .args ,
5761 text = True ,
@@ -73,6 +77,16 @@ def consume_pty(self):
7377 self .read_output ()
7478 self .parse ()
7579
80+ def append_to_copy (self , content : str ):
81+ if not self .stdout_copy :
82+ return
83+ try :
84+ with self .stdout_copy .open ("a" ) as fh :
85+ fh .write (content )
86+ except Exception as exc :
87+ logger .error (f"Unable to append to stdout copy: { exc } " )
88+ raise exc
89+
7690 def read_output (self ):
7791 bufsize = 1024
7892 timeout = 0.5 # seconds
@@ -98,6 +112,7 @@ def read_output(self):
98112 .decode ("UTF-8" )
99113 )
100114 self .stdout += content
115+ self .append_to_copy (content )
101116 except OSError as exc :
102117 if exc .errno != errno .EBADF :
103118 raise exc
@@ -238,7 +253,6 @@ def parse(self):
238253
239254
240255class PiImagerStep (Step ):
241-
242256 ident : str = "imager"
243257 name : str = "Flash image onto target disk"
244258 reports_progress : bool = True
@@ -256,7 +270,6 @@ def progress_text(self) -> str:
256270 return self .imager .step
257271
258272 def run (self , * , verbose : bool = False ) -> StepResult :
259-
260273 mountpoint = mount_to_temp (self .environment .image_device .path )
261274 fpath = mountpoint .joinpath (self .environment .image .relpath )
262275 target = self .environment .target_disk .path
@@ -275,6 +288,9 @@ def run(self, *, verbose: bool = False) -> StepResult:
275288 verbose = True ,
276289 )
277290 else :
291+ stdout_copy = tempfile .NamedTemporaryFile (
292+ delete = False , prefix = "rpi-imager" , dir = str (stdout_copy_folder )
293+ )
278294 self .imager = RpiImager (
279295 args = [
280296 shutil .which ("rpi-imager" ) or "/bin/false" ,
@@ -283,7 +299,8 @@ def run(self, *, verbose: bool = False) -> StepResult:
283299 "--debug" ,
284300 str (fpath ),
285301 str (self .environment .target_disk .path ),
286- ]
302+ ],
303+ copy_stdout_to = Path (stdout_copy .name ),
287304 )
288305 ps = self .imager
289306 self .imager .start ()
0 commit comments