Blame libnmstate/ifaces/ifaces.py

Packit Service 0535c1
#
Packit Service 0535c1
# Copyright (c) 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
import logging
Packit Service 0535c1
Packit Service 0535c1
from libnmstate.error import NmstateKernelIntegerRoundedError
Packit Service 0535c1
from libnmstate.error import NmstateValueError
Packit Service 0535c1
from libnmstate.error import NmstateVerificationError
Packit Service 0535c1
from libnmstate.prettystate import format_desired_current_state_diff
Packit Service 0535c1
from libnmstate.schema import Interface
Packit Service 0535c1
from libnmstate.schema import InterfaceType
Packit Service 0535c1
from libnmstate.schema import InterfaceState
Packit Service 0535c1
Packit Service 0535c1
from .base_iface import BaseIface
Packit Service 0535c1
from .bond import BondIface
Packit Service 0535c1
from .dummy import DummyIface
Packit Service 0535c1
from .ethernet import EthernetIface
Packit Service 0535c1
from .linux_bridge import LinuxBridgeIface
Packit Service 0535c1
from .ovs import OvsBridgeIface
Packit Service 0535c1
from .ovs import OvsInternalIface
Packit Service 0535c1
from .team import TeamIface
Packit Service 0535c1
from .vlan import VlanIface
Packit Service 0535c1
from .vxlan import VxlanIface
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
class Ifaces:
Packit Service 0535c1
    """
Packit Service 0535c1
    The Ifaces class hold both desired state(optional) and current state.
Packit Service 0535c1
    When desire state been provided, will perpare the state for backend plugin
Packit Service 0535c1
    to apply with:
Packit Service 0535c1
        * Validating on original desire state.
Packit Service 0535c1
        * Merging state.
Packit Service 0535c1
        * Generating metadata.
Packit Service 0535c1
    The class itself is focusing on tasks related to inter-interfaces changes:
Packit Service 0535c1
        * Mater/slave interfaces.
Packit Service 0535c1
        * Parent/Child interfaces.
Packit Service 0535c1
    The class is maitnaing a list of BaseIface(or its child classes) which does
Packit Service 0535c1
    not know desire state and current state difference. Hence this class is
Packit Service 0535c1
    also responsible to handle desire vs current state related tasks.
Packit Service 0535c1
    """
Packit Service 0535c1
Packit Service 0535c1
    def __init__(self, des_iface_infos, cur_iface_infos, save_to_disk=True):
Packit Service 0535c1
        self._save_to_disk = save_to_disk
Packit Service 0535c1
        self._des_iface_infos = des_iface_infos
Packit Service 0535c1
        self._cur_ifaces = {}
Packit Service 0535c1
        self._ifaces = {}
Packit Service 0535c1
        if cur_iface_infos:
Packit Service 0535c1
            for iface_info in cur_iface_infos:
Packit Service 0535c1
                cur_iface = _to_specific_iface_obj(iface_info, save_to_disk)
Packit Service 0535c1
                self._ifaces[cur_iface.name] = cur_iface
Packit Service 0535c1
                self._cur_ifaces[cur_iface.name] = cur_iface
Packit Service 0535c1
Packit Service 0535c1
        if des_iface_infos:
Packit Service 0535c1
            for iface_info in des_iface_infos:
Packit Service 0535c1
                iface = BaseIface(iface_info, save_to_disk)
Packit Service 0535c1
                cur_iface = self._ifaces.get(iface.name)
Packit Service 0535c1
                if cur_iface and cur_iface.is_desired:
Packit Service 0535c1
                    raise NmstateValueError(
Packit Service 0535c1
                        f"Duplicate interfaces names detected: {iface.name}"
Packit Service 0535c1
                    )
Packit Service 0535c1
Packit Service 0535c1
                if iface_info.get(Interface.TYPE) is None:
Packit Service 0535c1
                    if cur_iface:
Packit Service 0535c1
                        iface_info[Interface.TYPE] = cur_iface.type
Packit Service 0535c1
                    elif iface.is_up:
Packit Service 0535c1
                        raise NmstateValueError(
Packit Service 0535c1
                            f"Interface {iface.name} has no type defined "
Packit Service 0535c1
                            "neither in desire state nor current state"
Packit Service 0535c1
                        )
Packit Service 0535c1
                iface = _to_specific_iface_obj(iface_info, save_to_disk)
Packit Service 0535c1
                if (
Packit Service 0535c1
                    iface.type == InterfaceType.UNKNOWN
Packit Service 0535c1
                    # Allowing deletion of down profiles
Packit Service 0535c1
                    and not iface.is_absent
Packit Service 0535c1
                ):
Packit Service 0535c1
                    # Ignore interface with unknown type
Packit Service 0535c1
                    continue
Packit Service 0535c1
                if cur_iface:
Packit Service 0535c1
                    iface.merge(cur_iface)
Packit Service 0535c1
                iface.mark_as_desired()
Packit Service 0535c1
                self._ifaces[iface.name] = iface
Packit Service 0535c1
Packit Service 0535c1
            self._create_virtual_slaves()
Packit Service cc849d
            self._create_sriov_vfs_when_changed()
Packit Service 0535c1
            self._validate_unknown_slaves()
Packit Service f44fb0
            self._mark_vf_interface_as_absent_when_sriov_vf_decrease()
Packit Service 0535c1
            self._validate_unknown_parent()
Packit Service b504c8
            self._apply_copy_mac_from()
Packit Service 0535c1
            self._gen_metadata()
Packit Service 0535c1
            for iface in self._ifaces.values():
Packit Service 0535c1
                iface.pre_edit_validation_and_cleanup()
Packit Service 0535c1
Packit Service 0535c1
            self._pre_edit_validation_and_cleanup()
Packit Service 0535c1
Packit Service b504c8
    def _apply_copy_mac_from(self):
Packit Service b504c8
        for iface in self._ifaces.values():
Packit Service b504c8
            if iface.type not in (
Packit Service b504c8
                InterfaceType.LINUX_BRIDGE,
Packit Service b504c8
                InterfaceType.BOND,
Packit Service b504c8
            ):
Packit Service b504c8
                continue
Packit Service b504c8
            if not iface.copy_mac_from:
Packit Service b504c8
                continue
Packit Service b504c8
Packit Service b504c8
            if iface.copy_mac_from not in iface.slaves:
Packit Service b504c8
                raise NmstateValueError(
Packit Service b504c8
                    f"The interface {iface.name} is holding invalid "
Packit Service b504c8
                    f"{Interface.COPY_MAC_FROM} property "
Packit Service b504c8
                    f"as {iface.copy_mac_from} is not in the port "
Packit Service b504c8
                    f"list: {iface.port}"
Packit Service b504c8
                )
Packit Service b504c8
            port_iface = self._ifaces.get(iface.copy_mac_from)
Packit Service b504c8
            # TODO: bridge/bond might refering the mac from new veth in the
Packit Service b504c8
            #       same desire state, it too complex to support that.
Packit Service b504c8
            if not port_iface:
Packit Service b504c8
                raise NmstateValueError(
Packit Service b504c8
                    f"The interface {iface.name} is holding invalid "
Packit Service b504c8
                    f"{Interface.COPY_MAC_FROM} property "
Packit Service b504c8
                    f"as the port {iface.copy_mac_from} does not exists yet"
Packit Service b504c8
                )
Packit Service b504c8
Packit Service b504c8
            iface.apply_copy_mac_from(port_iface.mac)
Packit Service b504c8
Packit Service 0535c1
    def _create_virtual_slaves(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Certain master interface could have virtual slaves which does not
Packit Service 0535c1
        defined in desired state. Create it before generating metadata.
Packit Service 0535c1
        For example, OVS bridge could have slave defined as OVS internal
Packit Service 0535c1
        interface which could be created without defining in desire state but
Packit Service 0535c1
        only in slave list of OVS bridge.
Packit Service 0535c1
        """
Packit Service 0535c1
        new_ifaces = []
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.is_up and iface.is_master:
Packit Service 0535c1
                for slave_name in iface.slaves:
Packit Service 0535c1
                    if slave_name not in self._ifaces.keys():
Packit Service 0535c1
                        new_slave = iface.create_virtual_slave(slave_name)
Packit Service 0535c1
                        if new_slave:
Packit Service 0535c1
                            new_ifaces.append(new_slave)
Packit Service 0535c1
        for iface in new_ifaces:
Packit Service 0535c1
            self._ifaces[iface.name] = iface
Packit Service 0535c1
Packit Service cc849d
    def _create_sriov_vfs_when_changed(self):
Packit Service cc849d
        """
Packit Service cc849d
        When plugin set the TOTAL_VFS of PF, it might take 1 seconds or
Packit Service cc849d
        more to have the VFs to be ready.
Packit Service cc849d
        Nmstate should use verification retry to make sure VFs are full ready.
Packit Service cc849d
        To do that, we include VFs into desire state.
Packit Service cc849d
        """
Packit Service cc849d
        new_ifaces = []
Packit Service cc849d
        for iface in self._ifaces.values():
Packit Service cc849d
            if (
Packit Service cc849d
                iface.is_up
Packit Service cc849d
                and (iface.is_desired or iface.is_changed)
Packit Service cc849d
                and iface.type == InterfaceType.ETHERNET
Packit Service cc849d
                and iface.sriov_total_vfs > 0
Packit Service cc849d
            ):
Packit Service cc849d
                for new_iface in iface.create_sriov_vf_ifaces():
Packit Service cc849d
                    if new_iface.name not in self._ifaces:
Packit Service cc849d
                        new_iface.mark_as_desired()
Packit Service 10f5ae
                        new_iface.mark_as_new_sr_iov_vf()
Packit Service cc849d
                        new_ifaces.append(new_iface)
Packit Service 57b08e
                    else:
Packit Service 57b08e
                        # When the VFs are being modified, all VFs link are
Packit Service 57b08e
                        # being removed from kernel and created again. Nmstate
Packit Service 57b08e
                        # must verify they have been created.
Packit Service 57b08e
                        self._ifaces[new_iface.name].mark_as_desired()
Packit Service cc849d
        for new_iface in new_ifaces:
Packit Service cc849d
            self._ifaces[new_iface.name] = new_iface
Packit Service cc849d
Packit Service f44fb0
    def _mark_vf_interface_as_absent_when_sriov_vf_decrease(self):
Packit Service f44fb0
        """
Packit Service f44fb0
        When SRIOV TOTAL_VFS decreased, we should mark certain VF interfaces
Packit Service f44fb0
        as absent and also remove the entry in `Ethernet.SRIOV.VFS_SUBTREE`.
Packit Service f44fb0
        """
Packit Service f44fb0
        for iface_name, iface in self._ifaces.items():
Packit Service f44fb0
            if iface.type != InterfaceType.ETHERNET or not iface.is_up:
Packit Service f44fb0
                continue
Packit Service f44fb0
            if iface_name not in self.current_ifaces:
Packit Service f44fb0
                continue
Packit Service f44fb0
            cur_iface = self.current_ifaces[iface_name]
Packit Service f44fb0
            if (
Packit Service f44fb0
                cur_iface.sriov_total_vfs != 0
Packit Service f44fb0
                and iface.sriov_total_vfs < cur_iface.sriov_total_vfs
Packit Service f44fb0
            ):
Packit Service f44fb0
                iface.remove_vfs_entry_when_total_vfs_decreased()
Packit Service f44fb0
                for vf_name in iface.get_delete_vf_interface_names(
Packit Service f44fb0
                    cur_iface.sriov_total_vfs
Packit Service f44fb0
                ):
Packit Service f44fb0
                    vf_iface = self._ifaces.get(vf_name)
Packit Service f44fb0
                    if vf_iface:
Packit Service f44fb0
                        vf_iface.mark_as_absent_by_desire()
Packit Service f44fb0
Packit Service 0535c1
    def _pre_edit_validation_and_cleanup(self):
Packit Service 0535c1
        self._validate_over_booked_slaves()
Packit Service 0535c1
        self._validate_vlan_mtu()
Packit Service 0535c1
        self._handle_master_slave_list_change()
Packit Service 0535c1
        self._match_child_iface_state_with_parent()
Packit Service 0535c1
        self._mark_orphen_as_absent()
Packit Service 0535c1
        self._bring_slave_up_if_not_in_desire()
Packit Service 0535c1
        self._validate_ovs_patch_peers()
Packit Service 0535c1
        self._remove_unknown_type_interfaces()
Packit Service 0535c1
Packit Service 0535c1
    def _bring_slave_up_if_not_in_desire(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        When slave been included in master, automactially set it as state UP
Packit Service 0535c1
        if not defiend in desire state
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service c66a53
            if iface.is_desired and iface.is_up and iface.is_master:
Packit Service 4c3ded
                cur_iface = self.current_ifaces.get(iface.name)
Packit Service 0535c1
                for slave_name in iface.slaves:
Packit Service 4c3ded
                    if cur_iface and slave_name in cur_iface.slaves:
Packit Service 4c3ded
                        # Nmstate should not touch the port interface which has
Packit Service 4c3ded
                        # already been included in current interface.
Packit Service 4c3ded
                        continue
Packit Service 0535c1
                    slave_iface = self._ifaces[slave_name]
Packit Service 0535c1
                    if not slave_iface.is_desired and not slave_iface.is_up:
Packit Service 0535c1
                        slave_iface.mark_as_up()
Packit Service 0535c1
                        slave_iface.mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    def _validate_ovs_patch_peers(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        When OVS patch peer does not exist or is down, raise an error.
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.type == InterfaceType.OVS_INTERFACE and iface.is_up:
Packit Service 0535c1
                if iface.peer:
Packit Service 0535c1
                    peer_iface = self._ifaces.get(iface.peer)
Packit Service 0535c1
                    if not peer_iface or not peer_iface.is_up:
Packit Service 0535c1
                        raise NmstateValueError(
Packit Service 0535c1
                            f"OVS patch port peer {iface.peer} must exist and "
Packit Service 0535c1
                            "be up"
Packit Service 0535c1
                        )
Packit Service 0535c1
                    elif (
Packit Service 0535c1
                        not peer_iface.type == InterfaceType.OVS_INTERFACE
Packit Service 0535c1
                        or not peer_iface.is_patch_port
Packit Service 0535c1
                    ):
Packit Service 0535c1
                        raise NmstateValueError(
Packit Service 0535c1
                            f"OVS patch port peer {iface.peer} must be an OVS"
Packit Service 0535c1
                            " patch port"
Packit Service 0535c1
                        )
Packit Service 0535c1
Packit Service 0535c1
    def _validate_vlan_mtu(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Validate that mtu of vlan or vxlan is less than
Packit Service 0535c1
        or equal to it's base interface's MTU
Packit Service 0535c1
Packit Service 0535c1
        If base MTU is not present, set same as vlan MTU
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
Packit Service 0535c1
            if (
Packit Service 0535c1
                iface.type in [InterfaceType.VLAN, InterfaceType.VXLAN]
Packit Service 0535c1
                and iface.is_up
Packit Service 0535c1
                and iface.mtu
Packit Service 0535c1
            ):
Packit Service 0535c1
                base_iface = self._ifaces.get(iface.parent)
Packit Service 0535c1
                if not base_iface.mtu:
Packit Service 0535c1
                    base_iface.mtu = iface.mtu
Packit Service 0535c1
                if iface.mtu > base_iface.mtu:
Packit Service 0535c1
                    raise NmstateValueError(
Packit Service 0535c1
                        f"Interface {iface.name} has bigger "
Packit Service 0535c1
                        f"MTU({iface.mtu}) "
Packit Service 0535c1
                        f"than its base interface: {iface.parent} "
Packit Service 0535c1
                        f"MTU({base_iface.mtu})"
Packit Service 0535c1
                    )
Packit Service 0535c1
Packit Service 0535c1
    def _handle_master_slave_list_change(self):
Packit Service 0535c1
        """
Packit Service 0535c1
         * Mark slave interface as changed if master removed.
Packit Service 0535c1
         * Mark slave interface as changed if slave list of master changed.
Packit Service 0535c1
         * Mark slave interface as changed if slave config changed when master
Packit Service 0535c1
           said so.
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if not iface.is_desired or not iface.is_master:
Packit Service 0535c1
                continue
Packit Service 0535c1
            des_slaves = set(iface.slaves)
Packit Service 0535c1
            if iface.is_absent:
Packit Service 0535c1
                des_slaves = set()
Packit Service 0535c1
            cur_iface = self._cur_ifaces.get(iface.name)
Packit Service 0535c1
            cur_slaves = set(cur_iface.slaves) if cur_iface else set()
Packit Service 0535c1
            if des_slaves != cur_slaves:
Packit Service 0535c1
                changed_slaves = (des_slaves | cur_slaves) - (
Packit Service 0535c1
                    des_slaves & cur_slaves
Packit Service 0535c1
                )
Packit Service 0535c1
                for iface_name in changed_slaves:
Packit Service 0535c1
                    self._ifaces[iface_name].mark_as_changed()
Packit Service 0535c1
            if cur_iface:
Packit Service 0535c1
                for slave_name in iface.config_changed_slaves(cur_iface):
Packit Service ff21db
                    if slave_name in self._ifaces:
Packit Service ff21db
                        self._ifaces[slave_name].mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    def _match_child_iface_state_with_parent(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Handles these use cases:
Packit Service 0535c1
            * When changed/desired parent interface is up, child is not
Packit Service 0535c1
              desired to be any state, set child as UP.
Packit Service 0535c1
            * When changed/desired parent interface is marked as down or
Packit Service 0535c1
              absent, child state should sync with parent.
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.parent and self._ifaces.get(iface.parent):
Packit Service 0535c1
                parent_iface = self._ifaces[iface.parent]
Packit Service 0535c1
                if parent_iface.is_desired or parent_iface.is_changed:
Packit Service 0535c1
                    if (
Packit Service 0535c1
                        Interface.STATE not in iface.original_dict
Packit Service 0535c1
                        or parent_iface.is_down
Packit Service 0535c1
                        or parent_iface.is_absent
Packit Service 0535c1
                    ):
Packit Service 0535c1
                        iface.state = parent_iface.state
Packit Service 0535c1
                        iface.mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    def _mark_orphen_as_absent(self):
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service cd157a
            if (
Packit Service cd157a
                iface.need_parent
Packit Service cd157a
                and (not iface.parent or not self._ifaces.get(iface.parent))
Packit Service cd157a
                and (iface.is_desired or iface.is_changed)
Packit Service 0535c1
            ):
Packit Service 0535c1
                iface.mark_as_changed()
Packit Service 0535c1
                iface.state = InterfaceState.ABSENT
Packit Service 0535c1
Packit Service 0535c1
    def get(self, iface_name):
Packit Service 0535c1
        return self._ifaces.get(iface_name)
Packit Service 0535c1
Packit Service 0535c1
    def __getitem__(self, iface_name):
Packit Service 0535c1
        return self._ifaces[iface_name]
Packit Service 0535c1
Packit Service 0535c1
    def __setitem__(self, iface_name, iface):
Packit Service 0535c1
        self._ifaces[iface_name] = iface
Packit Service 0535c1
Packit Service 0535c1
    def _gen_metadata(self):
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            # Generate metadata for all interface in case any of them
Packit Service 0535c1
            # been marked as changed by DNS/Route/RouteRule.
Packit Service 0535c1
            iface.gen_metadata(self)
Packit Service 0535c1
Packit Service 0535c1
    def keys(self):
Packit Service 0535c1
        for iface in self._ifaces.keys():
Packit Service 0535c1
            yield iface
Packit Service 0535c1
Packit Service 0535c1
    def values(self):
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            yield iface
Packit Service 0535c1
Packit Service 0535c1
    @property
Packit Service 0535c1
    def current_ifaces(self):
Packit Service 0535c1
        return self._cur_ifaces
Packit Service 0535c1
Packit Service 0535c1
    @property
Packit Service 05efbf
    def all_ifaces(self):
Packit Service 05efbf
        return self._ifaces
Packit Service 05efbf
Packit Service 05efbf
    @property
Packit Service 0535c1
    def state_to_edit(self):
Packit Service 0535c1
        return [
Packit Service 0535c1
            iface.to_dict()
Packit Service 0535c1
            for iface in self._ifaces.values()
Packit Service 0535c1
            if iface.is_changed or iface.is_desired
Packit Service 0535c1
        ]
Packit Service 0535c1
Packit Service 0535c1
    @property
Packit Service 0535c1
    def cur_ifaces(self):
Packit Service 0535c1
        return self._cur_ifaces
Packit Service 0535c1
Packit Service bf9017
    def _remove_unknown_interface_type_slaves(self):
Packit Service 0535c1
        """
Packit Service c66a53
        When master containing slaves with unknown interface type or down
Packit Service c66a53
        state, they should be removed from master slave list before verifying.
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.is_up and iface.is_master and iface.slaves:
Packit Service 0535c1
                for slave_name in iface.slaves:
Packit Service 0535c1
                    slave_iface = self._ifaces[slave_name]
Packit Service c66a53
                    if (
Packit Service c66a53
                        slave_iface.type == InterfaceType.UNKNOWN
Packit Service c66a53
                        or slave_iface.state != InterfaceState.UP
Packit Service c66a53
                    ):
Packit Service 0535c1
                        iface.remove_slave(slave_name)
Packit Service 0535c1
Packit Service 0535c1
    def verify(self, cur_iface_infos):
Packit Service 0535c1
        cur_ifaces = Ifaces(
Packit Service 0535c1
            des_iface_infos=None,
Packit Service 0535c1
            cur_iface_infos=cur_iface_infos,
Packit Service 0535c1
            save_to_disk=self._save_to_disk,
Packit Service 0535c1
        )
Packit Service bf9017
        cur_ifaces._remove_unknown_interface_type_slaves()
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.is_desired:
Packit Service 0535c1
                if iface.is_virtual and iface.original_dict.get(
Packit Service 0535c1
                    Interface.STATE
Packit Service 0535c1
                ) in (InterfaceState.DOWN, InterfaceState.ABSENT):
Packit Service 0535c1
                    cur_iface = cur_ifaces.get(iface.name)
Packit Service 0535c1
                    if cur_iface:
Packit Service 0535c1
                        raise NmstateVerificationError(
Packit Service 0535c1
                            format_desired_current_state_diff(
Packit Service 0535c1
                                iface.original_dict,
Packit Service 0535c1
                                cur_iface.state_for_verify(),
Packit Service 0535c1
                            )
Packit Service 0535c1
                        )
Packit Service 0535c1
                elif iface.is_up or (iface.is_down and not iface.is_virtual):
Packit Service 0535c1
                    cur_iface = cur_ifaces.get(iface.name)
Packit Service 0535c1
                    if not cur_iface:
Packit Service 0535c1
                        raise NmstateVerificationError(
Packit Service 0535c1
                            format_desired_current_state_diff(
Packit Service 0535c1
                                iface.original_dict, {}
Packit Service 0535c1
                            )
Packit Service 0535c1
                        )
Packit Service 0535c1
                    elif not iface.match(cur_iface):
Packit Service 0535c1
                        if iface.type == InterfaceType.LINUX_BRIDGE:
Packit Service 0535c1
                            (
Packit Service 0535c1
                                key,
Packit Service 0535c1
                                value,
Packit Service 0535c1
                                cur_value,
Packit Service 0535c1
                            ) = LinuxBridgeIface.is_integer_rounded(
Packit Service 0535c1
                                iface, cur_iface
Packit Service 0535c1
                            )
Packit Service 0535c1
                            if key:
Packit Service 0535c1
                                raise NmstateKernelIntegerRoundedError(
Packit Service 0535c1
                                    "Linux kernel configured with 250 HZ "
Packit Service 0535c1
                                    "will round up/down the integer in linux "
Packit Service 0535c1
                                    f"bridge {iface.name} option '{key}' "
Packit Service 0535c1
                                    f"from {value} to {cur_value}."
Packit Service 0535c1
                                )
Packit Service 0535c1
                        raise NmstateVerificationError(
Packit Service 0535c1
                            format_desired_current_state_diff(
Packit Service 0535c1
                                iface.state_for_verify(),
Packit Service 0535c1
                                cur_iface.state_for_verify(),
Packit Service 0535c1
                            )
Packit Service 0535c1
                        )
Packit Service 57b08e
                    elif (
Packit Service 57b08e
                        iface.type == InterfaceType.ETHERNET and iface.is_sriov
Packit Service 57b08e
                    ):
Packit Service 57b08e
                        if not cur_iface.check_total_vfs_matches_vf_list(
Packit Service 57b08e
                            iface.sriov_total_vfs
Packit Service 57b08e
                        ):
Packit Service 57b08e
                            raise NmstateVerificationError(
Packit Service 57b08e
                                "The NIC exceeded the waiting time for "
Packit Service 57b08e
                                "verification and it is failing because "
Packit Service 57b08e
                                "the `total_vfs` does not match the VF "
Packit Service 57b08e
                                "list length."
Packit Service 57b08e
                            )
Packit Service 0535c1
Packit Service 0535c1
    def gen_dns_metadata(self, dns_state, route_state):
Packit Service 0535c1
        iface_metadata = dns_state.gen_metadata(self, route_state)
Packit Service 0535c1
        for iface_name, dns_metadata in iface_metadata.items():
Packit Service 0535c1
            self._ifaces[iface_name].store_dns_metadata(dns_metadata)
Packit Service 0535c1
            if dns_state.config_changed:
Packit Service 0535c1
                self._ifaces[iface_name].mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    def gen_route_metadata(self, route_state):
Packit Service 0535c1
        iface_metadata = route_state.gen_metadata(self)
Packit Service 0535c1
        for iface_name, route_metadata in iface_metadata.items():
Packit Service 0535c1
            self._ifaces[iface_name].store_route_metadata(route_metadata)
Packit Service 0535c1
Packit Service 0535c1
    def gen_route_rule_metadata(self, route_rule_state, route_state):
Packit Service 0535c1
        iface_metadata = route_rule_state.gen_metadata(route_state)
Packit Service 0535c1
        for iface_name, route_rule_metadata in iface_metadata.items():
Packit Service 0535c1
            self._ifaces[iface_name].store_route_rule_metadata(
Packit Service 0535c1
                route_rule_metadata
Packit Service 0535c1
            )
Packit Service 0535c1
            if route_rule_state.config_changed:
Packit Service 0535c1
                self._ifaces[iface_name].mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    def _validate_unknown_slaves(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Check the existance of slave interface
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            for slave_name in iface.slaves:
Packit Service 0535c1
                if not self._ifaces.get(slave_name):
Packit Service 0535c1
                    raise NmstateValueError(
Packit Service 0535c1
                        f"Interface {iface.name} has unknown slave: "
Packit Service 0535c1
                        f"{slave_name}"
Packit Service 0535c1
                    )
Packit Service 0535c1
Packit Service 0535c1
    def _validate_unknown_parent(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Check the existance of parent interface
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 0535c1
            if iface.parent and not self._ifaces.get(iface.parent):
Packit Service 0535c1
                raise NmstateValueError(
Packit Service 0535c1
                    f"Interface {iface.name} has unknown parent: "
Packit Service 0535c1
                    f"{iface.parent}"
Packit Service 0535c1
                )
Packit Service 0535c1
Packit Service 0535c1
    def _remove_unknown_type_interfaces(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Remove unknown type interfaces that are set as up.
Packit Service 0535c1
        """
Packit Service 0535c1
        for iface in list(self._ifaces.values()):
Packit Service 0535c1
            if iface.type == InterfaceType.UNKNOWN and iface.is_up:
Packit Service 0535c1
                self._ifaces.pop(iface.name, None)
Packit Service 0535c1
                logging.debug(
Packit Service 0535c1
                    f"Interface {iface.name} is type {iface.type} and "
Packit Service 0535c1
                    "will be ignored during the activation"
Packit Service 0535c1
                )
Packit Service 0535c1
Packit Service 0535c1
    def _validate_over_booked_slaves(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Check whether any slave is used by more than one master
Packit Service 0535c1
        """
Packit Service 0535c1
        slave_master_map = {}
Packit Service 0535c1
        for iface in self._ifaces.values():
Packit Service 99fff9
            if not (iface.is_changed or iface.is_desired) or not iface.is_up:
Packit Service 99fff9
                continue
Packit Service 0535c1
            for slave_name in iface.slaves:
Packit Service 0535c1
                cur_master = slave_master_map.get(slave_name)
Packit Service 0535c1
                if cur_master:
Packit Service 0535c1
                    cur_master_iface = self._ifaces.get(cur_master)
Packit Service 0535c1
                    if cur_master_iface and not cur_master_iface.is_absent:
Packit Service 0535c1
                        raise NmstateValueError(
Packit Service 0535c1
                            f"Interface {iface.name} slave {slave_name} is "
Packit Service 0535c1
                            f"already enslaved by interface {cur_master}"
Packit Service 0535c1
                        )
Packit Service 0535c1
                else:
Packit Service 0535c1
                    slave_master_map[slave_name] = iface.name
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _to_specific_iface_obj(info, save_to_disk):
Packit Service 0535c1
    iface_type = info.get(Interface.TYPE, InterfaceType.UNKNOWN)
Packit Service 0535c1
    if iface_type == InterfaceType.ETHERNET:
Packit Service 0535c1
        return EthernetIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.BOND:
Packit Service 0535c1
        return BondIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.DUMMY:
Packit Service 0535c1
        return DummyIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.LINUX_BRIDGE:
Packit Service 0535c1
        return LinuxBridgeIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.OVS_BRIDGE:
Packit Service 0535c1
        return OvsBridgeIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.OVS_INTERFACE:
Packit Service 0535c1
        return OvsInternalIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.VLAN:
Packit Service 0535c1
        return VlanIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.VXLAN:
Packit Service 0535c1
        return VxlanIface(info, save_to_disk)
Packit Service 0535c1
    elif iface_type == InterfaceType.TEAM:
Packit Service 0535c1
        return TeamIface(info, save_to_disk)
Packit Service 0535c1
    else:
Packit Service 0535c1
        return BaseIface(info, save_to_disk)