Blame libnmstate/nm/wired.py

Packit Service 0535c1
#
Packit Service 0535c1
# Copyright (c) 2018-2020 Red Hat, Inc.
Packit Service 0535c1
#
Packit Service 0535c1
# This file is part of nmstate
Packit Service 0535c1
#
Packit Service 0535c1
# This program is free software: you can redistribute it and/or modify
Packit Service 0535c1
# it under the terms of the GNU Lesser General Public License as published by
Packit Service 0535c1
# the Free Software Foundation, either version 2.1 of the License, or
Packit Service 0535c1
# (at your option) any later version.
Packit Service 0535c1
#
Packit Service 0535c1
# This program is distributed in the hope that it will be useful,
Packit Service 0535c1
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 0535c1
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 0535c1
# GNU Lesser General Public License for more details.
Packit Service 0535c1
#
Packit Service 0535c1
# You should have received a copy of the GNU Lesser General Public License
Packit Service 0535c1
# along with this program. If not, see <https://www.gnu.org/licenses/>.
Packit Service 0535c1
#
Packit Service 0535c1
Packit Service 0535c1
from libnmstate.ethtool import minimal_ethtool
Packit Service 0535c1
from libnmstate.nm import sriov
Packit Service 0535c1
from libnmstate.schema import Ethernet
Packit Service 0535c1
from libnmstate.schema import Interface
Packit Service 0535c1
from .common import NM
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
ZEROED_MAC = "00:00:00:00:00:00"
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
class WiredSetting:
Packit Service 0535c1
    def __init__(self, state):
Packit Service 0535c1
        self.mtu = state.get(Interface.MTU)
Packit Service 0535c1
        self.mac = state.get(Interface.MAC)
Packit Service 0535c1
Packit Service 0535c1
        ethernet = state.get(Ethernet.CONFIG_SUBTREE, {})
Packit Service 0535c1
        self.speed = ethernet.get(Ethernet.SPEED)
Packit Service 0535c1
        self.duplex = ethernet.get(Ethernet.DUPLEX)
Packit Service 0535c1
        self.auto_negotiation = ethernet.get(Ethernet.AUTO_NEGOTIATION)
Packit Service 0535c1
Packit Service 0535c1
    def __hash__(self):
Packit Service 0535c1
        return hash(self.__key())
Packit Service 0535c1
Packit Service 0535c1
    def __eq__(self, other):
Packit Service 0535c1
        return self is other or self.__key() == other.__key()
Packit Service 0535c1
Packit Service 0535c1
    def __ne__(self, other):
Packit Service 0535c1
        return not self.__eq__(other)
Packit Service 0535c1
Packit Service 0535c1
    def __bool__(self):
Packit Service 0535c1
        return bool(
Packit Service 0535c1
            self.mac
Packit Service 0535c1
            or self.mtu
Packit Service 0535c1
            or self.speed
Packit Service 0535c1
            or self.duplex
Packit Service 0535c1
            or (self.auto_negotiation is not None)
Packit Service 0535c1
        )
Packit Service 0535c1
Packit Service 0535c1
    def __key(self):
Packit Service 0535c1
        return (
Packit Service 0535c1
            self.mtu,
Packit Service 0535c1
            self.mac,
Packit Service 0535c1
            self.speed,
Packit Service 0535c1
            self.duplex,
Packit Service 0535c1
            self.auto_negotiation,
Packit Service 0535c1
        )
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def create_setting(iface_state, base_con_profile):
Packit Service 0535c1
    setting = WiredSetting(iface_state)
Packit Service 0535c1
Packit Service 0535c1
    nm_wired_setting = None
Packit Service 0535c1
    if base_con_profile:
Packit Service 0535c1
        nm_wired_setting = base_con_profile.get_setting_wired()
Packit Service 0535c1
        if nm_wired_setting:
Packit Service 0535c1
            nm_wired_setting = nm_wired_setting.duplicate()
Packit Service 0535c1
Packit Service 0535c1
    if not setting:
Packit Service 0535c1
        return nm_wired_setting
Packit Service 0535c1
Packit Service 0535c1
    if not nm_wired_setting:
Packit Service 0535c1
        nm_wired_setting = NM.SettingWired.new()
Packit Service 0535c1
Packit Service 0535c1
    if setting.mac:
Packit Service 0535c1
        nm_wired_setting.props.cloned_mac_address = setting.mac
Packit Service 0535c1
Packit Service 0535c1
    if setting.mtu:
Packit Service 0535c1
        nm_wired_setting.props.mtu = setting.mtu
Packit Service 0535c1
Packit Service 0535c1
    if setting.auto_negotiation:
Packit Service 0535c1
        nm_wired_setting.props.auto_negotiate = True
Packit Service 0535c1
        if not setting.speed and not setting.duplex:
Packit Service 0535c1
            nm_wired_setting.props.speed = 0
Packit Service 0535c1
            nm_wired_setting.props.duplex = None
Packit Service 0535c1
Packit Service 0535c1
        elif not setting.speed:
Packit Service 0535c1
            ethtool_results = minimal_ethtool(str(iface_state[Interface.NAME]))
Packit Service 0535c1
            setting.speed = ethtool_results[Ethernet.SPEED]
Packit Service 0535c1
        elif not setting.duplex:
Packit Service 0535c1
            ethtool_results = minimal_ethtool(str(iface_state[Interface.NAME]))
Packit Service 0535c1
            setting.duplex = ethtool_results[Ethernet.DUPLEX]
Packit Service 0535c1
Packit Service 0535c1
    elif setting.auto_negotiation is False:
Packit Service 0535c1
        nm_wired_setting.props.auto_negotiate = False
Packit Service 0535c1
        ethtool_results = minimal_ethtool(str(iface_state[Interface.NAME]))
Packit Service 0535c1
        if not setting.speed:
Packit Service 0535c1
            setting.speed = ethtool_results[Ethernet.SPEED]
Packit Service 0535c1
        if not setting.duplex:
Packit Service 0535c1
            setting.duplex = ethtool_results[Ethernet.DUPLEX]
Packit Service 0535c1
Packit Service 0535c1
    if setting.speed:
Packit Service 0535c1
        nm_wired_setting.props.speed = setting.speed
Packit Service 0535c1
Packit Service 0535c1
    if setting.duplex in [Ethernet.HALF_DUPLEX, Ethernet.FULL_DUPLEX]:
Packit Service 0535c1
        nm_wired_setting.props.duplex = setting.duplex
Packit Service 0535c1
Packit Service 0535c1
    return nm_wired_setting
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def get_info(device):
Packit Service 0535c1
    """
Packit Service 0535c1
    Provides the current active values for a device
Packit Service 0535c1
    """
Packit Service 0535c1
    info = {}
Packit Service 0535c1
Packit Service 0535c1
    iface = device.get_iface()
Packit Service 0535c1
    try:
Packit Service 6a4bbd
        mtu = int(device.get_mtu())
Packit Service 6a4bbd
        if mtu:
Packit Service 6a4bbd
            info[Interface.MTU] = mtu
Packit Service 0535c1
    except AttributeError:
Packit Service 0535c1
        pass
Packit Service 0535c1
Packit Service 0535c1
    mac = device.get_hw_address()
Packit Service 0535c1
    if not mac:
Packit Service 0535c1
        mac = _get_mac_address_from_sysfs(iface)
Packit Service 0535c1
Packit Service 0535c1
    # A device may not have a MAC or it may not yet be "realized" (zeroed mac).
Packit Service 0535c1
    if mac and mac != ZEROED_MAC:
Packit Service 0535c1
        info[Interface.MAC] = mac
Packit Service 0535c1
Packit Service 0535c1
    if device.get_device_type() == NM.DeviceType.ETHERNET:
Packit Service 0535c1
        ethernet = _get_ethernet_info(device, iface)
Packit Service 0535c1
        if ethernet:
Packit Service 0535c1
            info[Ethernet.CONFIG_SUBTREE] = ethernet
Packit Service 0535c1
Packit Service 0535c1
    return info
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _get_mac_address_from_sysfs(ifname):
Packit Service 0535c1
    """
Packit Service 0535c1
    Fetch the mac address of an interface from sysfs.
Packit Service 0535c1
    This is a workaround for https://bugzilla.redhat.com/1786937.
Packit Service 0535c1
    """
Packit Service 0535c1
    mac = None
Packit Service 0535c1
    sysfs_path = f"/sys/class/net/{ifname}/address"
Packit Service 0535c1
    try:
Packit Service 0535c1
        with open(sysfs_path) as f:
Packit Service 0535c1
            mac = f.read().rstrip("\n").upper()
Packit Service 0535c1
    except FileNotFoundError:
Packit Service 0535c1
        pass
Packit Service 0535c1
    return mac
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _get_ethernet_info(device, iface):
Packit Service 0535c1
    ethernet = {}
Packit Service 0535c1
    try:
Packit Service 0535c1
        speed = int(device.get_speed())
Packit Service 0535c1
        if speed > 0:
Packit Service 0535c1
            ethernet[Ethernet.SPEED] = speed
Packit Service 0535c1
        else:
Packit Service 0535c1
            return None
Packit Service 0535c1
    except AttributeError:
Packit Service 0535c1
        return None
Packit Service 0535c1
Packit Service 0535c1
    ethtool_results = minimal_ethtool(iface)
Packit Service 0535c1
    auto_setting = ethtool_results[Ethernet.AUTO_NEGOTIATION]
Packit Service 0535c1
    if auto_setting is True:
Packit Service 0535c1
        ethernet[Ethernet.AUTO_NEGOTIATION] = True
Packit Service 0535c1
    elif auto_setting is False:
Packit Service 0535c1
        ethernet[Ethernet.AUTO_NEGOTIATION] = False
Packit Service 0535c1
    else:
Packit Service 0535c1
        return None
Packit Service 0535c1
Packit Service 0535c1
    duplex_setting = ethtool_results[Ethernet.DUPLEX]
Packit Service 0535c1
    if duplex_setting in [Ethernet.HALF_DUPLEX, Ethernet.FULL_DUPLEX]:
Packit Service 0535c1
        ethernet[Ethernet.DUPLEX] = duplex_setting
Packit Service 0535c1
    else:
Packit Service 0535c1
        return None
Packit Service 0535c1
Packit Service 0535c1
    sriov_info = sriov.get_info(device)
Packit Service 0535c1
    if sriov_info:
Packit Service 0535c1
        ethernet.update(sriov_info)
Packit Service 0535c1
Packit Service 0535c1
    return ethernet