@@ -110,44 +110,49 @@ def build_ksft(config, tree_path):
110110
111111def deploy_artifacts (_config , machine_ips , reservation_id , nic_info , tree_path ,
112112 kernel_version , filters = None ):
113- """SCP kernel + ksft bundle to test machines .
113+ """SCP kernel + ksft bundle to the DUT .
114114
115- Deploys to /srv/hw-worker/tests/$reservation_id/ on each machine.
115+ Deploys to /srv/hw-worker/tests/$reservation_id/ on the DUT (first
116+ machine in machine_ips). In dual-host setups the remote/peer machine
117+ is not touched — hw_worker configures it via SSH at test time.
116118 Also writes the test runner config file with NIC addressing info.
117119 """
118120 remote_dir = f'/srv/hw-worker/tests/{ reservation_id } '
119121 kernel_image = os .path .join (tree_path , 'arch/x86/boot/bzImage' )
120122 ksft_tarball = os .path .join (tree_path , 'ksft-install.tar.gz' )
121123
122- for ipaddr in machine_ips :
123- print (f"deploy: { ipaddr } -> { remote_dir } " )
124- # Create remote directory
125- _ssh (ipaddr , f'mkdir -p { remote_dir } ' )
126-
127- # Copy kernel
128- _scp (kernel_image , ipaddr , f'{ remote_dir } /bzImage' )
129-
130- # Copy ksft tarball and extract
131- _scp (ksft_tarball , ipaddr , f'{ remote_dir } /ksft-install.tar.gz' )
132- _ssh (ipaddr , f'tar xzf { remote_dir } /ksft-install.tar.gz -C { remote_dir } ' )
133-
134- # Write expected kernel version for hw-worker to verify
135- _ssh (ipaddr ,
136- f"cat > { remote_dir } /.kernel-version << 'HEREDOC'\n { kernel_version } \n HEREDOC" )
137-
138- # Deploy crash filters if available
139- if filters :
140- import tempfile as _tmpfile
141- with _tmpfile .NamedTemporaryFile (mode = 'w' , suffix = '.json' ,
142- delete = False ) as fp :
143- json .dump (filters , fp )
144- tmp_path = fp .name
145- try :
146- _scp (tmp_path , ipaddr , f'{ remote_dir } /filters.json' )
147- finally :
148- os .unlink (tmp_path )
124+ # Only deploy to the DUT (first machine). In dual-host setups the
125+ # remote/peer machine stays on its base kernel and is configured via
126+ # SSH by hw_worker — it does not need the test kernel or selftests.
127+ dut_ip = machine_ips [0 ]
128+ print (f"deploy: { dut_ip } -> { remote_dir } " )
129+ # Create remote directory
130+ _ssh (dut_ip , f'mkdir -p { remote_dir } ' )
131+
132+ # Copy kernel
133+ _scp (kernel_image , dut_ip , f'{ remote_dir } /bzImage' )
134+
135+ # Copy ksft tarball and extract
136+ _scp (ksft_tarball , dut_ip , f'{ remote_dir } /ksft-install.tar.gz' )
137+ _ssh (dut_ip , f'tar xzf { remote_dir } /ksft-install.tar.gz -C { remote_dir } ' )
138+
139+ # Write expected kernel version for hw-worker to verify
140+ _ssh (dut_ip ,
141+ f"cat > { remote_dir } /.kernel-version << 'HEREDOC'\n { kernel_version } \n HEREDOC" )
142+
143+ # Deploy crash filters if available
144+ if filters :
145+ import tempfile as _tmpfile
146+ with _tmpfile .NamedTemporaryFile (mode = 'w' , suffix = '.json' ,
147+ delete = False ) as fp :
148+ json .dump (filters , fp )
149+ tmp_path = fp .name
150+ try :
151+ _scp (tmp_path , dut_ip , f'{ remote_dir } /filters.json' )
152+ finally :
153+ os .unlink (tmp_path )
149154
150- # Write test config on the primary machine (first in list)
155+ # Write test config on the DUT
151156 if nic_info and machine_ips :
152157 config_lines = []
153158 config_lines .append (f'NETIF={ nic_info .get ("ifname" , "" )} ' )
@@ -173,51 +178,53 @@ def deploy_artifacts(_config, machine_ips, reservation_id, nic_info, tree_path,
173178 config_lines .append (f'DISRUPTIVE={ nic_info ["disruptive" ]} ' )
174179
175180 config_content = '\n ' .join (config_lines ) + '\n '
176- _ssh (machine_ips [ 0 ] ,
181+ _ssh (dut_ip ,
177182 f"cat > { remote_dir } /nic-test.env << 'HEREDOC'\n { config_content } HEREDOC" )
178183
179184
180185def kexec_machine (config , machine_ips , reservation_id , mc = None ):
181- """SSH to each machine and kexec into the new kernel."""
186+ """SSH to the DUT and kexec into the new kernel."""
182187 remote_dir = f'/srv/hw-worker/tests/{ reservation_id } '
183188 boot_timeout = config .getint ('hw' , 'max_kexec_boot_timeout' , fallback = 300 )
184189
185190 def _refresh ():
186191 if mc :
187192 mc .reservation_refresh (reservation_id )
188193
189- for ipaddr in machine_ips :
190- # Use the existing initramfs so LVM/DM can assemble the root FS.
191- # On the kexec'd test kernel there's no matching initramfs under
192- # /boot, so fall back to the cached path from a previous lookup.
193- initrd = _ssh (ipaddr ,
194- 'ls /boot/initramfs-$(uname -r).img 2>/dev/null || '
195- 'ls /boot/initrd.img-$(uname -r) 2>/dev/null || true' ).strip ()
196- if initrd :
197- _initrd_cache [ipaddr ] = initrd
198- elif ipaddr in _initrd_cache :
199- cached = _initrd_cache [ipaddr ]
200- if _ssh_retcode (ipaddr , f'test -f { cached } ' ) == 0 :
201- initrd = cached
202- print (f"kexec: { ipaddr } using cached initrd { initrd } " )
203-
204- kexec_cmd = f'kexec -l { remote_dir } /bzImage --reuse-cmdline'
205- if initrd :
206- kexec_cmd += f' --initrd={ initrd } '
207- if initrd != _initrd_cache .get (ipaddr , initrd ):
208- print (f"kexec: { ipaddr } using initrd { initrd } " )
209- else :
210- print (f"kexec: { ipaddr } no initrd found, booting without" )
211- _ssh (ipaddr , kexec_cmd )
212- print (f"kexec: { ipaddr } : " , kexec_cmd )
213- # kexec -e will kill the SSH session, so ignore errors
214- _ssh (ipaddr , 'kexec -e' , check = False , timeout = 5 )
215-
216- # Wait for machines to come back
217- for ipaddr in machine_ips :
218- print (f"kexec: waiting for { ipaddr } to come back (timeout { boot_timeout } s)" )
219- _wait_for_ssh (ipaddr , timeout = boot_timeout , keepalive = _refresh )
220- print (f"kexec: { ipaddr } is back" )
194+ # Only kexec the DUT (first machine). In dual-host setups the
195+ # remote/peer machine stays on its base kernel.
196+ dut_ip = machine_ips [0 ]
197+
198+ # Use the existing initramfs so LVM/DM can assemble the root FS.
199+ # On the kexec'd test kernel there's no matching initramfs under
200+ # /boot, so fall back to the cached path from a previous lookup.
201+ initrd = _ssh (dut_ip ,
202+ 'ls /boot/initramfs-$(uname -r).img 2>/dev/null || '
203+ 'ls /boot/initrd.img-$(uname -r) 2>/dev/null || true' ).strip ()
204+ if initrd :
205+ _initrd_cache [dut_ip ] = initrd
206+ elif dut_ip in _initrd_cache :
207+ cached = _initrd_cache [dut_ip ]
208+ if _ssh_retcode (dut_ip , f'test -f { cached } ' ) == 0 :
209+ initrd = cached
210+ print (f"kexec: { dut_ip } using cached initrd { initrd } " )
211+
212+ kexec_cmd = f'kexec -l { remote_dir } /bzImage --reuse-cmdline'
213+ if initrd :
214+ kexec_cmd += f' --initrd={ initrd } '
215+ if initrd != _initrd_cache .get (dut_ip , initrd ):
216+ print (f"kexec: { dut_ip } using initrd { initrd } " )
217+ else :
218+ print (f"kexec: { dut_ip } no initrd found, booting without" )
219+ _ssh (dut_ip , kexec_cmd )
220+ print (f"kexec: { dut_ip } : " , kexec_cmd )
221+ # kexec -e will kill the SSH session, so ignore errors
222+ _ssh (dut_ip , 'kexec -e' , check = False , timeout = 5 )
223+
224+ # Wait for DUT to come back
225+ print (f"kexec: waiting for { dut_ip } to come back (timeout { boot_timeout } s)" )
226+ _wait_for_ssh (dut_ip , timeout = boot_timeout , keepalive = _refresh )
227+ print (f"kexec: { dut_ip } is back" )
221228
222229
223230def grab_hw_worker_journal (ipaddr , results_path , suffix = '' ):
0 commit comments