mirror of
https://github.com/linux-system-roles/network.git
synced 2026-01-23 10:25:28 +00:00
ethtool: use GPERMADDR instead the ethtool command line tool
This patch implements the ETHTOOL_GPERMADDR command in order to retrieve the permanent address from ethtool instead using command line tool. Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
This commit is contained in:
parent
024ba709f6
commit
2e5dd50852
6 changed files with 72 additions and 44 deletions
|
|
@ -34,7 +34,7 @@ _network_packages_default_gobject_packages: ["python{{
|
|||
ansible_python['version']['major'] | replace('2', '')}}-gobject-base"]
|
||||
|
||||
network_service_name_default_nm: NetworkManager
|
||||
network_packages_default_nm: "{{ ['ethtool', 'NetworkManager']
|
||||
network_packages_default_nm: "{{['NetworkManager']
|
||||
+ _network_packages_default_gobject_packages|select()|list()
|
||||
+ _network_packages_default_802_1x|select()|list()}}"
|
||||
|
||||
|
|
@ -56,8 +56,8 @@ if ansible_distribution in ['RedHat', 'CentOS', 'OracleLinux'] and
|
|||
# |select() filters the list to include only values that evaluate to true
|
||||
# (the empty string is false)
|
||||
# |list() converts the generator that |select() creates to a list
|
||||
network_packages_default_initscripts: "{{ ['ethtool']
|
||||
+ _network_packages_default_initscripts_bridge|select()|list()
|
||||
network_packages_default_initscripts: "{{
|
||||
_network_packages_default_initscripts_bridge|select()|list()
|
||||
+ _network_packages_default_initscripts_network_scripts|select()|list()
|
||||
}}"
|
||||
|
||||
|
|
|
|||
|
|
@ -13,19 +13,21 @@ import traceback
|
|||
|
||||
# pylint: disable=import-error, no-name-in-module
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.network_lsr import ethtool
|
||||
from ansible.module_utils.network_lsr import MyError
|
||||
|
||||
# pylint: disable=import-error
|
||||
from ansible.module_utils.network_lsr.argument_validator import (
|
||||
ArgUtil,
|
||||
ArgValidator_ListConnections,
|
||||
ValidationError,
|
||||
)
|
||||
|
||||
# pylint: disable=import-error
|
||||
from ansible.module_utils.network_lsr.utils import Util
|
||||
from ansible.module_utils.network_lsr import nm_provider
|
||||
|
||||
# pylint: enable=import-error, no-name-in-module
|
||||
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: network_connections
|
||||
|
|
@ -107,15 +109,7 @@ class SysUtil:
|
|||
|
||||
@staticmethod
|
||||
def _link_read_permaddress(ifname):
|
||||
try:
|
||||
out = Util.check_output(["ethtool", "-P", ifname])
|
||||
except MyError:
|
||||
return None
|
||||
|
||||
m = re.match("^Permanent address: ([0-9A-Fa-f:]*)\n$", out)
|
||||
if not m:
|
||||
return None
|
||||
return Util.mac_norm(m.group(1))
|
||||
return ethtool.get_perm_addr(ifname)
|
||||
|
||||
@staticmethod
|
||||
def _link_infos_fetch():
|
||||
|
|
|
|||
56
module_utils/network_lsr/ethtool.py
Normal file
56
module_utils/network_lsr/ethtool.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import array
|
||||
import struct
|
||||
import fcntl
|
||||
import socket
|
||||
|
||||
from .utils import Util
|
||||
|
||||
ETHTOOL_GPERMADDR = 0x00000020
|
||||
SIOCETHTOOL = 0x8946
|
||||
MAX_ADDR_LEN = 32
|
||||
IFNAMESIZ = 16
|
||||
|
||||
|
||||
def get_perm_addr(ifname):
|
||||
"""
|
||||
Return the Permanent address value for the specified interface using the
|
||||
ETHTOOL_GPERMADDR ioctl command.
|
||||
|
||||
Please for further documentation, see:
|
||||
https://github.com/torvalds/linux/blob/master/include/uapi/linux/ethtool.h#L734
|
||||
https://github.com/torvalds/linux/blob/master/include/uapi/linux/ethtool.h#L1388
|
||||
https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/tree/ethtool.c#n4172
|
||||
"""
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sockfd = sock.fileno()
|
||||
ifname = ifname.encode("utf-8")
|
||||
if len(ifname) > IFNAMESIZ:
|
||||
return None
|
||||
|
||||
ecmd = array.array(
|
||||
"B",
|
||||
struct.pack(
|
||||
"II%is" % MAX_ADDR_LEN,
|
||||
ETHTOOL_GPERMADDR,
|
||||
MAX_ADDR_LEN,
|
||||
b"\x00" * MAX_ADDR_LEN,
|
||||
),
|
||||
)
|
||||
ifreq = struct.pack("%isP" % IFNAMESIZ, ifname, ecmd.buffer_info()[0])
|
||||
|
||||
fcntl.ioctl(sockfd, SIOCETHTOOL, ifreq)
|
||||
try:
|
||||
res = ecmd.tobytes()
|
||||
except AttributeError: # tobytes() is not available in python2
|
||||
res = ecmd.tostring()
|
||||
_, size, perm_addr = struct.unpack("II%is" % MAX_ADDR_LEN, res)
|
||||
perm_addr = Util.mac_ntoa(perm_addr[:size])
|
||||
except IOError:
|
||||
perm_addr = None
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
return perm_addr
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# vim: fileencoding=utf8
|
||||
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
|
|
@ -25,19 +23,6 @@ class Util:
|
|||
return v
|
||||
return default
|
||||
|
||||
@staticmethod
|
||||
def check_output(argv):
|
||||
# subprocess.check_output is python 2.7.
|
||||
with open("/dev/null", "wb") as DEVNULL:
|
||||
env = os.environ.copy()
|
||||
env["LANG"] = "C"
|
||||
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=DEVNULL, env=env)
|
||||
# FIXME: Can we assume this to always be UTF-8?
|
||||
out = p.communicate()[0].decode("UTF-8")
|
||||
if p.returncode != 0:
|
||||
raise MyError("failure calling %s: exit with %s" % (argv, p.returncode))
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def path_to_glib_bytes(path):
|
||||
"""
|
||||
|
|
@ -275,7 +260,8 @@ class Util:
|
|||
def mac_ntoa(mac):
|
||||
if mac is None:
|
||||
return None
|
||||
return ":".join(["%02x" % c for c in mac])
|
||||
# bytearray() is needed for python2 compatibility
|
||||
return ":".join(["%02x" % c for c in bytearray(mac)])
|
||||
|
||||
@staticmethod
|
||||
def mac_norm(mac_str, force_len=None):
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
if [ "${1}" == "-P" ] && [ "${2}" != "" ]
|
||||
then
|
||||
echo "Permanent address: 23:00:00:00:00:00"
|
||||
fi
|
||||
|
|
@ -2503,10 +2503,9 @@ class TestNM(unittest.TestCase):
|
|||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_check_output(self):
|
||||
res = Util.check_output(["echo", "test"])
|
||||
self.assertEqual(res, "test\n")
|
||||
self.assertRaises(n.MyError, Util.check_output, ["false"])
|
||||
def test_mac_ntoa(self):
|
||||
mac_bytes = b"\xaa\xbb\xcc\xdd\xee\xff"
|
||||
self.assertEqual(Util.mac_ntoa(mac_bytes), "aa:bb:cc:dd:ee:ff")
|
||||
|
||||
def test_convert_passwd_flags_nm(self):
|
||||
test_cases = [
|
||||
|
|
@ -2528,10 +2527,9 @@ class TestUtils(unittest.TestCase):
|
|||
|
||||
class TestSysUtils(unittest.TestCase):
|
||||
def test_link_read_permaddress(self):
|
||||
# Manipulate PATH to use ethtool mock script to avoid hard dependency on
|
||||
# ethtool
|
||||
os.environ["PATH"] = TESTS_BASEDIR + "/helpers:" + os.environ["PATH"]
|
||||
self.assertEqual(SysUtil._link_read_permaddress("lo"), "23:00:00:00:00:00")
|
||||
self.assertEqual(SysUtil._link_read_permaddress("lo"), "00:00:00:00:00:00")
|
||||
self.assertEqual(SysUtil._link_read_permaddress("fakeiface"), None)
|
||||
self.assertEqual(SysUtil._link_read_permaddress("morethansixteenchars"), None)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue