From d8320383db7ae5abe6597bc6c32a9a18f3464313 Mon Sep 17 00:00:00 2001 From: Chenlizhong Date: Thu, 1 Dec 2022 10:44:53 +0800 Subject: [PATCH] fix: fix errors in ethtool (#3605) * fix: fix 'invalid literal for int() with base 10: n/a' error and 'bad line' parse exception in ethtool Signed-off-by: Chen lizhong * test: fix flake8 error in test file Signed-off-by: Chen lizhong * test: Remove print in test file Signed-off-by: Chen lizhong * test: update test for n/a checking Signed-off-by: Chen lizhong * fix: use isnumeric() method instead of 'n/a in value' Signed-off-by: Chen lizhong * fix: support python3 and python2 both for isnumeric() Signed-off-by: Chen lizhong * fix: fix flake8 Signed-off-by: Chen lizhong * fix: fix error in python2.6 Signed-off-by: Chen lizhong (cherry picked from commit 9ed8f4a81851dd613d90fa223b17b8e38faae56f) --- insights/parsers/ethtool.py | 20 ++++++++++---- insights/tests/parsers/test_ethtool.py | 37 +++++++++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/insights/parsers/ethtool.py b/insights/parsers/ethtool.py index 832742d06d..9f9dece654 100644 --- a/insights/parsers/ethtool.py +++ b/insights/parsers/ethtool.py @@ -42,11 +42,16 @@ import os import re +import sys from collections import namedtuple from ..parsers import ParseException from .. import parser, LegacyItemAccess, CommandParser from insights.specs import Specs +if sys.version_info[0] == 3: + # Python 3 + unicode = str + def extract_iface_name_from_path(path, name): """ @@ -501,9 +506,10 @@ def parse_content(self, content): for line in content[2:]: if line.strip(): (key, value) = [s.strip() for s in line.split(":", 1)] - value = int(value) - self.data[key] = value - setattr(self, key.replace("-", "_"), value) + if unicode(value).isnumeric(): + value = int(value) + self.data[key] = value + setattr(self, key.replace("-", "_"), value) @parser(Specs.ethtool_g) @@ -600,7 +606,8 @@ def set_section(section, data): elif ':' in line: # key: value, store in section data for now key, value = (s.strip() for s in line.split(":", 1)) - section_data[key.replace(" ", "_").lower()] = int(value) + if unicode(value).isnumeric(): + section_data[key.replace(" ", "_").lower()] = int(value) # Handle last found section, if any set_section(section, section_data) @@ -756,6 +763,7 @@ class TimeStamp(CommandParser): >>> eno1.data['Hardware Receive Filter Modes']['all'] 'HWTSTAMP_FILTER_ALL' """ + @property def ifname(self): """(str): the interface name""" @@ -767,6 +775,7 @@ def parse_content(self, content): group = None for line in content[1:]: + line = line.strip() if ":" in line: key, val = [i.strip() for i in line.split(':', 1)] group = {} @@ -775,7 +784,7 @@ def parse_content(self, content): key, val = [i.strip() for i in line.split(None, 1)] group[key] = val.strip('()') elif line: - raise ParseException('bad line: {0}'.format(line)) + group[line] = None @parser(Specs.ethtool) @@ -853,6 +862,7 @@ class Ethtool(CommandParser): >>> ethinfo.supported_ports # This is converted to a list of strings ['TP', 'MII'] """ + @property def ifname(self): """str: Return the name of network interface in content.""" diff --git a/insights/tests/parsers/test_ethtool.py b/insights/tests/parsers/test_ethtool.py index bdf2f873dc..64fd105ba0 100644 --- a/insights/tests/parsers/test_ethtool.py +++ b/insights/tests/parsers/test_ethtool.py @@ -7,7 +7,6 @@ import doctest - TEST_ETHTOOL_A_DOCS = ''' Pause parameters for eth0: Autonegotiate: on @@ -67,6 +66,16 @@ TX negotiated: off """.strip() +ETHTOOL_T_NO_CAP_VALUE = """ +Time stamping parameters for ens192: +Capabilities: + software-receive + software-system-clock +PTP Hardware Clock: none +Hardware Transmit Timestamp Modes: none +Hardware Receive Filter Modes: none +""" + def test_ethtool_a(): context = context_wrap(SUCCESS_ETHTOOL_A, path=SUCCESS_ETHTOOL_A_PATH) @@ -142,7 +151,7 @@ def test_ethtool_a_blank_line(): tx-frame-low: 25 tx-usecs-high: 0 -tx-frame-high: 0 +tx-frame-high: n/a """.strip() @@ -168,7 +177,7 @@ def test_get_ethtool_c(): context.path = TEST_ETHTOOL_C_PATH result = ethtool.CoalescingInfo(context) assert keys_in(["adaptive-rx", "adaptive-tx", "pkt-rate-high", - "tx-usecs-irq", "tx-frame-low", "tx-usecs-high", "tx-frame-high"], result.data) + "tx-usecs-irq", "tx-frame-low", "tx-usecs-high"], result.data) assert result.ifname == "eth2" assert not result.adaptive_rx assert not result.adaptive_tx @@ -176,7 +185,7 @@ def test_get_ethtool_c(): assert result.tx_usecs_irq == 0 assert result.tx_frame_low == 25 assert result.tx_usecs_high == 0 - assert result.tx_frame_high == 0 + assert 'tx_frame_high' not in result.data def test_get_ethtool_c_cannot_get(): @@ -657,6 +666,16 @@ def test_ethtool_S_f(): all (HWTSTAMP_FILTER_ALL) ''' +ETHTOOL_T_NO_CAP_VALUE = """ +Time stamping parameters for ens192: +Capabilities: + software-receive + software-system-clock +PTP Hardware Clock: none +Hardware Transmit Timestamp Modes: none +Hardware Receive Filter Modes: none +""" + def test_ethtool_timestamp(): timestamp = ethtool.TimeStamp(context_wrap(TEST_ETHTOOL_TIMESTAMP, path="sbin/ethtool_-T_eno1")) @@ -666,9 +685,13 @@ def test_ethtool_timestamp(): assert timestamp.data['PTP Hardware Clock'] == '0' assert timestamp.data['Hardware Transmit Timestamp Modes']['off'] == 'HWTSTAMP_TX_OFF' assert timestamp.data['Hardware Receive Filter Modes']['all'] == 'HWTSTAMP_FILTER_ALL' - with pytest.raises(ParseException) as pe: - ethtool.TimeStamp(context_wrap(TEST_ETHTOOL_TIMESTAMP_AB, path="sbin/ethtool_-T_eno1")) - assert 'bad line:' in str(pe) + + +def test_ethtool_timestamp_no_cap_value(): + timestamp = ethtool.TimeStamp(context_wrap(ETHTOOL_T_NO_CAP_VALUE, path="sbin/ethtool_-T_ens192")) + assert timestamp.ifname == 'ens192' + assert timestamp.data['Capabilities']['software-receive'] is None + assert timestamp.data['Hardware Transmit Timestamp Modes'] == 'none' TEST_EXTRACT_FROM_PATH_1 = """