1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2024-10-06 10:51:13 +01:00

Device: Updated to set and retrieve binary data from sysfiles

`set_sysfile_values` now accepts a `^` symbol prefixed to the
file path to indicated that the value should be written as binary data.
To accommodate this an extra `binary` flag has been added to  the `set_sysfile_value`and `get_sysfile_value` methods to write and retrieve the binary data respectively.
This commit is contained in:
Marc Bonnici 2017-04-04 17:32:10 +01:00
parent 35df2fff30
commit 50236b0661
2 changed files with 42 additions and 14 deletions

View File

@ -17,6 +17,7 @@
import os import os
import re import re
import time import time
import base64
import socket import socket
from collections import namedtuple from collections import namedtuple
from subprocess import CalledProcessError from subprocess import CalledProcessError
@ -241,7 +242,7 @@ class BaseLinuxDevice(Device): # pylint: disable=abstract-method
self.logger.debug('Could not pull property file "{}"'.format(propfile)) self.logger.debug('Could not pull property file "{}"'.format(propfile))
return {} return {}
def get_sysfile_value(self, sysfile, kind=None): def get_sysfile_value(self, sysfile, kind=None, binary=False):
""" """
Get the contents of the specified sysfile. Get the contents of the specified sysfile.
@ -251,28 +252,49 @@ class BaseLinuxDevice(Device): # pylint: disable=abstract-method
be any Python callable that takes a single str argument. be any Python callable that takes a single str argument.
If not specified or is None, the contents will be returned If not specified or is None, the contents will be returned
as a string. as a string.
:param binary: Whether the value should be encoded into base64 for reading
to deal with binary format.
""" """
if binary:
output = self.execute('{} base64 {}'.format(self.busybox, sysfile), as_root=self.is_rooted).strip()
output = output.decode('base64')
else:
output = self.execute('cat \'{}\''.format(sysfile), as_root=self.is_rooted).strip() # pylint: disable=E1103 output = self.execute('cat \'{}\''.format(sysfile), as_root=self.is_rooted).strip() # pylint: disable=E1103
if kind: if kind:
return kind(output) return kind(output)
else: else:
return output return output
def set_sysfile_value(self, sysfile, value, verify=True): def set_sysfile_value(self, sysfile, value, verify=True, binary=False):
""" """
Set the value of the specified sysfile. By default, the value will be checked afterwards. Set the value of the specified sysfile. By default, the value will be checked afterwards.
Can be overridden by setting ``verify`` parameter to ``False``. Can be overridden by setting ``verify`` parameter to ``False``. By default binary values
will not be written correctly this can be changed by setting the ``binary`` parameter to
``True``.
""" """
value = str(value) value = str(value)
self.execute('echo {} > \'{}\''.format(value, sysfile), check_exit_code=False, as_root=True) if binary:
# Value is already string encoded, so need to decode before encoding in base64
try:
value = str(value.decode('string_escape'))
except ValueError as e:
msg = 'Can not interpret value "{}" for "{}": {}'
raise ValueError(msg.format(value, sysfile, e.message))
encoded_value = base64.b64encode(value)
cmd = 'echo {} | {} base64 -d > \'{}\''.format(encoded_value, self.busybox, sysfile)
else:
cmd = 'echo {} > \'{}\''.format(value, sysfile)
self.execute(cmd, check_exit_code=False, as_root=True)
if verify: if verify:
output = self.get_sysfile_value(sysfile) output = self.get_sysfile_value(sysfile, binary=binary)
if output.strip() != value: # pylint: disable=E1103 if output.strip() != value: # pylint: disable=E1103
message = 'Could not set the value of {} to {}'.format(sysfile, value) message = 'Could not set the value of {} to {}'.format(sysfile, value)
raise DeviceError(message) raise DeviceError(message)
self._written_sysfiles.append(sysfile) self._written_sysfiles.append((sysfile, binary))
def get_sysfile_values(self): def get_sysfile_values(self):
""" """
@ -281,21 +303,24 @@ class BaseLinuxDevice(Device): # pylint: disable=abstract-method
""" """
values = {} values = {}
for sysfile in self._written_sysfiles: for sysfile, binary in self._written_sysfiles:
values[sysfile] = self.get_sysfile_value(sysfile) values[sysfile] = self.get_sysfile_value(sysfile, binary=binary)
return values return values
def set_sysfile_values(self, params): def set_sysfile_values(self, params):
""" """
The plural version of ``set_sysfile_value``. Takes a single parameter which is a mapping of The plural version of ``set_sysfile_value``. Takes a single parameter which is a mapping of
file paths to values to be set. By default, every value written will be verified. The can file paths to values to be set. By default, every value written will be verified. This can
be disabled for individual paths by appending ``'!'`` to them. be disabled for individual paths by appending ``'!'`` to them. To enable values being
written as binary data, a ``'^'`` can be prefixed to the path.
""" """
for sysfile, value in params.iteritems(): for sysfile, value in params.iteritems():
verify = not sysfile.endswith('!') verify = not sysfile.endswith('!')
sysfile = sysfile.rstrip('!') sysfile = sysfile.rstrip('!')
self.set_sysfile_value(sysfile, value, verify=verify) binary = sysfile.startswith('^')
sysfile = sysfile.lstrip('^')
self.set_sysfile_value(sysfile, value, verify=verify, binary=binary)
def deploy_busybox(self, context, force=False): def deploy_busybox(self, context, force=False):
""" """

View File

@ -394,7 +394,7 @@ class Device(Extension):
""" """
self.execute("sleep {}".format(seconds), timeout=seconds + 10) self.execute("sleep {}".format(seconds), timeout=seconds + 10)
def set_sysfile_value(self, filepath, value, verify=True): def set_sysfile_value(self, filepath, value, verify=True, binary=False):
""" """
Write the specified value to the specified file on the device Write the specified value to the specified file on the device
and verify that the value has actually been written. and verify that the value has actually been written.
@ -403,13 +403,14 @@ class Device(Extension):
:param value: The value to be written to the file. Must be :param value: The value to be written to the file. Must be
an int or a string convertable to an int. an int or a string convertable to an int.
:param verify: Specifies whether the value should be verified, once written. :param verify: Specifies whether the value should be verified, once written.
:param binary: Specifies whether the value should be written as binary data.
Should raise DeviceError if could write value. Should raise DeviceError if could write value.
""" """
raise NotImplementedError() raise NotImplementedError()
def get_sysfile_value(self, sysfile, kind=None): def get_sysfile_value(self, sysfile, kind=None, binary=False):
""" """
Get the contents of the specified sysfile. Get the contents of the specified sysfile.
@ -419,6 +420,8 @@ class Device(Extension):
be any Python callable that takes a single str argument. be any Python callable that takes a single str argument.
If not specified or is None, the contents will be returned If not specified or is None, the contents will be returned
as a string. as a string.
:param binary: Whether the value should be encoded into base64 for reading
to deal with binary format.
""" """
raise NotImplementedError() raise NotImplementedError()