Skip to content

Commit 47c8007

Browse files
committed
driver/usbloader: support synchronizing extra files used by uuu scripts
When using a non-builtin ``uuu`` script as image for the ``UUUDriver``, that script can reference files relative to script file itself. To support that case, the ``UUUDriver`` is expandend to take a list of files to synchronize to the remote exporter before invoking ``uuu``. However, the ``ManagedFile`` helper places the files in a per-file directory based on the hash of the file being synchronized (when using ``rsync`` instead of ``nfs``). This breaks the files-relative-to-uuu- script use case, so use a combined hash of all the configured files instead. Signed-off-by: Martin Hundebøll <[email protected]>
1 parent 2ce9e24 commit 47c8007

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

doc/configuration.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,6 +2541,8 @@ Implements:
25412541
UUUDriver:
25422542
image: 'mybootloaderkey'
25432543
script: 'spl'
2544+
extra_files:
2545+
- 'fitImage'
25442546
25452547
images:
25462548
mybootloaderkey: 'path/to/mybootloader.img'
@@ -2549,6 +2551,7 @@ Arguments:
25492551
- image (str): optional, key in :ref:`images <labgrid-device-config-images>` containing the path
25502552
of an image to bootstrap onto the target
25512553
- script (str): optional, run built-in script with ``uuu -b``, called with image as arg0
2554+
- extra_files (list): optional, paths to synchronize to exporter before invoking ``uuu``
25522555

25532556
USBStorageDriver
25542557
~~~~~~~~~~~~~~~~

labgrid/driver/usbloader.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import subprocess
23
import attr
34

@@ -158,6 +159,7 @@ class UUUDriver(Driver, BootstrapProtocol):
158159

159160
image = attr.ib(default=None)
160161
script = attr.ib(default='', validator=attr.validators.instance_of(str))
162+
extra_files = attr.ib(default=[], validator=attr.validators.instance_of(list))
161163

162164
def __attrs_post_init__(self):
163165
super().__attrs_post_init__()
@@ -167,6 +169,8 @@ def __attrs_post_init__(self):
167169
else:
168170
self.tool = 'uuu-loader'
169171

172+
self.hash = None
173+
170174
def on_activate(self):
171175
pass
172176

@@ -178,16 +182,46 @@ def on_deactivate(self):
178182
def load(self, filename=None):
179183
if filename is None and self.image is not None:
180184
filename = self.target.env.config.get_image_path(self.image)
185+
181186
mf = ManagedFile(filename, self.loader)
187+
mf.hash = self.get_hash(filename)
182188
mf.sync_to_resource()
183189

190+
for file in self.extra_files or []:
191+
file_mf = ManagedFile(file, self.loader)
192+
file_mf.hash = self.get_hash(filename)
193+
file_mf.sync_to_resource()
194+
184195
cmd = ['-b', self.script] if self.script else []
185196

186197
processwrapper.check_output(
187198
self.loader.command_prefix + [self.tool] + cmd + [mf.get_remote_path()],
188199
print_on_silent_log=True
189200
)
190201

202+
def get_hash(self, image):
203+
"""Create a hash of all input files combined to use when synchronizing managed files."""
204+
if self.hash is not None:
205+
return self.hash
206+
207+
hasher = hashlib.sha256()
208+
209+
# Inspired by the implementation of hashlib.file_digest() from CPython, but adapted to read
210+
# multiple files instead of a single one.
211+
buf = bytearray(2**18) # Reusable buffer to reduce allocations.
212+
view = memoryview(buf)
213+
214+
for file in [image] + self.extra_files:
215+
with open(file, 'rb') as fileobj:
216+
while True:
217+
size = fileobj.readinto(buf)
218+
if size == 0:
219+
break # EOF
220+
hasher.update(view[:size])
221+
222+
self.hash = hasher.hexdigest()
223+
return self.hash
224+
191225

192226
@target_factory.reg_driver
193227
@attr.s(eq=False)

0 commit comments

Comments
 (0)