From b839ad32b9bf4541583ecbe68a0bd5dd9f12345a Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 10 Mar 2016 12:32:46 -0500 Subject: dmi data: fix failure of reading dmi data for unset dmi values it is not uncommon to find dmi data in /sys full of 'ff'. utf-8 decoding of those would fail, causing warning and stacktrace. Return '.' instead of \xff. This maps to what dmidecode would return $ dmidecode --string system-product-name ................................. --- cloudinit/util.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'cloudinit/util.py') diff --git a/cloudinit/util.py b/cloudinit/util.py index e7407ea4..1d50edc9 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2140,13 +2140,20 @@ def _read_dmi_syspath(key): LOG.debug("did not find %s", dmi_key_path) return None - key_data = load_file(dmi_key_path) + key_data = load_file(dmi_key_path, decode=False) if not key_data: LOG.debug("%s did not return any data", dmi_key_path) return None - LOG.debug("dmi data %s returned %s", dmi_key_path, key_data) - return key_data.strip() + # in the event that this is all \xff and a carriage return + # then return '.' in its place. + if key_data == b'\xff' * (len(key_data) - 1) + b'\n': + key_data = b'.' * (len(key_data) - 1) + b'\n' + + str_data = key_data.decode('utf8').strip() + + LOG.debug("dmi data %s returned %s", dmi_key_path, str_data) + return str_data except Exception: logexc(LOG, "failed read of %s", dmi_key_path) -- cgit v1.2.3 From be38478cd8e11b0e29c70bb881a676628e9f74d5 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 10 Mar 2016 12:47:55 -0500 Subject: improve comment --- cloudinit/util.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'cloudinit/util.py') diff --git a/cloudinit/util.py b/cloudinit/util.py index 1d50edc9..1a517c79 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2145,13 +2145,12 @@ def _read_dmi_syspath(key): LOG.debug("%s did not return any data", dmi_key_path) return None - # in the event that this is all \xff and a carriage return - # then return '.' in its place. + # uninitialized dmi values show as all \xff and /sys appends a '\n'. + # in that event, return a string of '.' in the same length. if key_data == b'\xff' * (len(key_data) - 1) + b'\n': key_data = b'.' * (len(key_data) - 1) + b'\n' str_data = key_data.decode('utf8').strip() - LOG.debug("dmi data %s returned %s", dmi_key_path, str_data) return str_data -- cgit v1.2.3 From 03f80fa62eb85270a7a96850c5e689a1c4bc0049 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 14 Mar 2016 09:21:02 -0400 Subject: change return value for dmi data of all \xff to be "" Previously we returned a string of "." the same length as the dmi field. That seems confusing to the user as "." would seem like a valid response when in fact this value should not be considered valid. So now, in this case, return empty string. --- cloudinit/util.py | 7 +++++-- tests/unittests/test_util.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'cloudinit/util.py') diff --git a/cloudinit/util.py b/cloudinit/util.py index 1a517c79..caae17ce 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2148,7 +2148,7 @@ def _read_dmi_syspath(key): # uninitialized dmi values show as all \xff and /sys appends a '\n'. # in that event, return a string of '.' in the same length. if key_data == b'\xff' * (len(key_data) - 1) + b'\n': - key_data = b'.' * (len(key_data) - 1) + b'\n' + key_data = b"" str_data = key_data.decode('utf8').strip() LOG.debug("dmi data %s returned %s", dmi_key_path, str_data) @@ -2193,7 +2193,10 @@ def read_dmi_data(key): dmidecode_path = which('dmidecode') if dmidecode_path: - return _call_dmidecode(key, dmidecode_path) + ret = _call_dmidecode(key, dmidecode_path) + if ret is not None and ret.replace(".", "") == "": + return "" + return ret LOG.warn("did not find either path %s or dmidecode command", DMI_SYS_PATH) diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index 542e4075..bdee9719 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -388,7 +388,7 @@ class TestReadDMIData(helpers.FilesystemMockingTestCase): def test_dots_returned_instead_of_foxfox(self): my_len = 32 dmi_value = b'\xff' * my_len + b'\n' - expected = '.' * my_len + expected = "" dmi_key = 'system-product-name' sysfs_key = 'product_name' self._create_sysfs_file(sysfs_key, dmi_value) -- cgit v1.2.3 From f8fe3182ac5e6b7b3b4a81e034e87bfd1327f82b Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 14 Mar 2016 09:25:50 -0400 Subject: change where we handle the translation --- cloudinit/util.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'cloudinit/util.py') diff --git a/cloudinit/util.py b/cloudinit/util.py index caae17ce..f84f120e 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2168,6 +2168,8 @@ def _call_dmidecode(key, dmidecode_path): cmd = [dmidecode_path, "--string", key] (result, _err) = subp(cmd) LOG.debug("dmidecode returned '%s' for '%s'", result, key) + if result.replace(".", "") == "": + return "" return result except (IOError, OSError) as _err: LOG.debug('failed dmidecode cmd: %s\n%s', cmd, _err.message) @@ -2193,10 +2195,7 @@ def read_dmi_data(key): dmidecode_path = which('dmidecode') if dmidecode_path: - ret = _call_dmidecode(key, dmidecode_path) - if ret is not None and ret.replace(".", "") == "": - return "" - return ret + return _call_dmidecode(key, dmidecode_path) LOG.warn("did not find either path %s or dmidecode command", DMI_SYS_PATH) -- cgit v1.2.3 From 001057f01e698c3ca0c078d9535f05fdebec2d80 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 14 Mar 2016 09:34:46 -0400 Subject: strip return of dmidecode and do so before checking for all "." --- cloudinit/util.py | 1 + 1 file changed, 1 insertion(+) (limited to 'cloudinit/util.py') diff --git a/cloudinit/util.py b/cloudinit/util.py index f84f120e..f9e37a79 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2168,6 +2168,7 @@ def _call_dmidecode(key, dmidecode_path): cmd = [dmidecode_path, "--string", key] (result, _err) = subp(cmd) LOG.debug("dmidecode returned '%s' for '%s'", result, key) + result = result.strip() if result.replace(".", "") == "": return "" return result -- cgit v1.2.3