import re import subprocess from shutil import which # Originally from https://github.com/opencoff/useful-scripts/blob/master/linktest.py # mapping fields from ethtool output to simple names field_map = { "Supported ports": "ports", "Supported link modes": "sup_link_modes", "Supports auto-negotiation": "sup_autoneg", "Advertised link modes": "adv_link_modes", "Advertised auto-negotiation": "adv_autoneg", "Speed": "speed", "Duplex": "duplex", "Port": "port", "Auto-negotiation": "autoneg", "Link detected": "link", } def merge_two_dicts(x, y): z = x.copy() z.update(y) return z class Ethtool: """ This class aims to parse ethtool output There is several bindings to have something proper, but it requires compilation and other requirements. """ def __init__(self, interface, *args, **kwargs): self.interface = interface def _parse_ethtool_output(self): """ parse ethtool output """ output = subprocess.getoutput("ethtool {}".format(self.interface)) fields = {} field = "" fields["speed"] = "-" fields["link"] = "-" fields["duplex"] = "-" for line in output.split("\n")[1:]: line = line.rstrip() r = line.find(":") if r > 0: field = line[:r].strip() if field not in field_map: continue field = field_map[field] output = line[r + 1 :].strip() fields[field] = output else: if len(field) > 0 and field in field_map: fields[field] += " " + line.strip() return fields def _parse_ethtool_module_output(self): status, output = subprocess.getstatusoutput( "ethtool -m {}".format(self.interface) ) if status == 0: r = re.search(r"Identifier.*\((\w+)\)", output) if r and len(r.groups()) > 0: return {"form_factor": r.groups()[0]} return {} def parse(self): if which("ethtool") is None: return None output = self._parse_ethtool_output() output.update(self._parse_ethtool_module_output()) return output