Blame libnmstate/nm/applier.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
import logging
Packit Service 0535c1
import itertools
Packit Service 0535c1
Packit Service 0535c1
from libnmstate.error import NmstateValueError
Packit Service 0535c1
from libnmstate.schema import Interface
Packit Service 0535c1
from libnmstate.schema import InterfaceState
Packit Service 0535c1
from libnmstate.schema import InterfaceType
Packit Service 0535c1
from libnmstate.schema import LinuxBridge as LB
Packit Service 0535c1
from libnmstate.schema import OVSBridge as OvsB
Packit Service 0535c1
from libnmstate.schema import OVSInterface
Packit Service 0535c1
from libnmstate.schema import Team
Packit Service 0535c1
from libnmstate.ifaces.bond import BondIface
Packit Service 0535c1
from libnmstate.ifaces.bridge import BridgeIface
Packit Service 0535c1
Packit Service 0535c1
from . import bond
Packit Service 0535c1
from . import bridge
Packit Service 0535c1
from . import connection
Packit Service 0535c1
from . import device
Packit Service 0535c1
from . import ipv4
Packit Service 0535c1
from . import ipv6
Packit Service 0535c1
from . import lldp
Packit Service 0535c1
from . import ovs
Packit Service 0535c1
from . import sriov
Packit Service 0535c1
from . import team
Packit Service 0535c1
from . import translator
Packit Service 0535c1
from . import user
Packit Service 0535c1
from . import vlan
Packit Service 0535c1
from . import vxlan
Packit Service 0535c1
from . import wired
Packit Service 0535c1
from .common import NM
Packit Service 0535c1
from .dns import get_dns_config_iface_names
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
MAXIMUM_INTERFACE_LENGTH = 15
Packit Service 0535c1
Packit Service 0535c1
MASTER_METADATA = "_master"
Packit Service 0535c1
MASTER_TYPE_METADATA = "_master_type"
Packit Service 0535c1
MASTER_IFACE_TYPES = (
Packit Service 0535c1
    InterfaceType.OVS_BRIDGE,
Packit Service 0535c1
    bond.BOND_TYPE,
Packit Service 0535c1
    LB.TYPE,
Packit Service 0535c1
    Team.TYPE,
Packit Service 0535c1
)
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def apply_changes(context, net_state, save_to_disk):
Packit Service 0535c1
    con_profiles = []
Packit Service 0535c1
Packit Service 0535c1
    _preapply_dns_fix(context, net_state)
Packit Service 0535c1
Packit Service 0535c1
    ifaces_desired_state = net_state.ifaces.state_to_edit
Packit Service 0535c1
    ifaces_desired_state.extend(
Packit Service 0535c1
        _create_proxy_ifaces_desired_state(ifaces_desired_state)
Packit Service 0535c1
    )
Packit Service 0535c1
Packit Service 0535c1
    for iface_desired_state in filter(
Packit Service 0535c1
        lambda s: s.get(Interface.STATE) != InterfaceState.ABSENT,
Packit Service 0535c1
        ifaces_desired_state,
Packit Service 0535c1
    ):
Packit Service 0535c1
        ifname = iface_desired_state[Interface.NAME]
Packit Service 0535c1
        nmdev = context.get_nm_dev(ifname)
Packit Service 0535c1
        cur_con_profile = None
Packit Service 0535c1
        if nmdev:
Packit Service 0535c1
            cur_con_profile = connection.ConnectionProfile(context)
Packit Service 0535c1
            cur_con_profile.import_by_device(nmdev)
Packit Service 0535c1
        else:
Packit Service 0535c1
            # Profile for virtual interface will remove interface when down
Packit Service 0535c1
            # hence search on existing NM.RemoteConnections
Packit Service 0535c1
            con_profile = context.client.get_connection_by_id(ifname)
Packit Service 0535c1
            if con_profile and con_profile.get_interface_name() == ifname:
Packit Service 0535c1
                cur_con_profile = connection.ConnectionProfile(
Packit Service 0535c1
                    context, profile=con_profile
Packit Service 0535c1
                )
Packit Service 0535c1
        original_desired_iface_state = {}
Packit Service 0535c1
        if net_state.ifaces.get(ifname):
Packit Service 0535c1
            iface = net_state.ifaces[ifname]
Packit Service 0535c1
            if iface.is_desired:
Packit Service 0535c1
                original_desired_iface_state = iface.original_dict
Packit Service 0535c1
            if (
Packit Service 0535c1
                set(original_desired_iface_state.keys())
Packit Service 0535c1
                <= set([Interface.STATE, Interface.NAME, Interface.TYPE])
Packit Service 0535c1
                and cur_con_profile
Packit Service 0535c1
                and cur_con_profile.profile
Packit Service 0535c1
                and not net_state.ifaces[ifname].is_changed
Packit Service 0535c1
            ):
Packit Service 0535c1
                # Don't create new profile if original desire does not ask
Packit Service 0535c1
                # anything besides state:up and not been marked as changed.
Packit Service 0535c1
                # We don't need to do this once we support querying on-disk
Packit Service 0535c1
                # configure
Packit Service 0535c1
                con_profiles.append(cur_con_profile)
Packit Service 0535c1
                continue
Packit Service 0535c1
        new_con_profile = _build_connection_profile(
Packit Service 0535c1
            context,
Packit Service 0535c1
            iface_desired_state,
Packit Service 0535c1
            cur_con_profile,
Packit Service 0535c1
            original_desired_iface_state,
Packit Service 0535c1
        )
Packit Service 0535c1
        if not new_con_profile.devname:
Packit Service 0535c1
            set_conn = new_con_profile.profile.get_setting_connection()
Packit Service 0535c1
            set_conn.props.interface_name = iface_desired_state[Interface.NAME]
Packit Service 0535c1
        if cur_con_profile and cur_con_profile.profile:
Packit Service 0535c1
            cur_con_profile.update(new_con_profile, save_to_disk)
Packit Service 0535c1
            con_profiles.append(new_con_profile)
Packit Service 0535c1
        else:
Packit Service 0535c1
            # Missing connection, attempting to create a new one.
Packit Service 44efa8
            connection.delete_iface_inactive_connections(context, ifname)
Packit Service 0535c1
            new_con_profile.add(save_to_disk)
Packit Service 0535c1
            con_profiles.append(new_con_profile)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    _set_ifaces_admin_state(context, ifaces_desired_state, con_profiles)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _set_ifaces_admin_state(context, ifaces_desired_state, con_profiles):
Packit Service 0535c1
    """
Packit Service 0535c1
    Control interface admin state by activating, deactivating and deleting
Packit Service 0535c1
    devices connection profiles.
Packit Service 0535c1
Packit Service 0535c1
    The `absent` state results in deactivating the device and deleting
Packit Service 0535c1
    the connection profile.
Packit Service 0535c1
Packit Service 0535c1
    For new virtual devices, the `up` state is handled by activating the
Packit Service 0535c1
    new connection profile. For existing devices, the device is activated,
Packit Service 0535c1
    leaving it to choose the correct profile.
Packit Service 0535c1
Packit Service 0535c1
    In order to activate correctly the interfaces, the order is significant:
Packit Service 0535c1
    - Master-less master interfaces.
Packit Service 0535c1
    - New interfaces (virtual interfaces, but not OVS ones).
Packit Service 0535c1
    - Master interfaces.
Packit Service 0535c1
    - OVS ports.
Packit Service 0535c1
    - OVS internal.
Packit Service 0535c1
    - All the rest.
Packit Service 0535c1
    """
Packit Service 0535c1
    con_profiles_by_devname = _index_profiles_by_devname(con_profiles)
Packit Service 0535c1
    new_ifaces = _get_new_ifaces(context, con_profiles)
Packit Service 0535c1
    new_ifaces_to_activate = set()
Packit Service 0535c1
    new_vlan_ifaces_to_activate = set()
Packit Service 0535c1
    new_vxlan_ifaces_to_activate = set()
Packit Service 0535c1
    new_ovs_interface_to_activate = set()
Packit Service 0535c1
    new_ovs_port_to_activate = set()
Packit Service 0535c1
    new_master_not_enslaved_ifaces = set()
Packit Service 0535c1
    master_ifaces_to_edit = set()
Packit Service 0535c1
    ifaces_to_edit = set()
Packit Service 0535c1
    devs_to_deactivate = {}
Packit Service 0535c1
    devs_to_delete_profile = {}
Packit Service 0535c1
    devs_to_delete = {}
Packit Service 0535c1
    devs_to_deactivate_beforehand = []
Packit Service 0535c1
    profiles_to_delete = []
Packit Service 0535c1
    devs_to_activate_beforehand = []
Packit Service 0535c1
Packit Service 0535c1
    current_profiles = context.client.get_connections()
Packit Service 0535c1
Packit Service 0535c1
    for iface_desired_state in ifaces_desired_state:
Packit Service 0535c1
        ifname = iface_desired_state[Interface.NAME]
Packit Service 0535c1
        nmdev = context.get_nm_dev(ifname)
Packit Service 0535c1
        if not nmdev:
Packit Service 0535c1
            if (
Packit Service 0535c1
                ifname in new_ifaces
Packit Service 0535c1
                and iface_desired_state[Interface.STATE] == InterfaceState.UP
Packit Service 0535c1
            ):
Packit Service 0535c1
                if _is_master_iface(
Packit Service 0535c1
                    iface_desired_state
Packit Service 0535c1
                ) and not _is_slave_iface(iface_desired_state):
Packit Service 0535c1
                    new_master_not_enslaved_ifaces.add(ifname)
Packit Service 0535c1
                elif (
Packit Service 0535c1
                    iface_desired_state[Interface.TYPE]
Packit Service 0535c1
                    == InterfaceType.OVS_INTERFACE
Packit Service 0535c1
                ):
Packit Service 0535c1
                    new_ovs_interface_to_activate.add(ifname)
Packit Service 0535c1
                elif (
Packit Service 0535c1
                    iface_desired_state[Interface.TYPE]
Packit Service 0535c1
                    == InterfaceType.OVS_PORT
Packit Service 0535c1
                ):
Packit Service 0535c1
                    new_ovs_port_to_activate.add(ifname)
Packit Service 0535c1
                elif iface_desired_state[Interface.TYPE] == InterfaceType.VLAN:
Packit Service 0535c1
                    new_vlan_ifaces_to_activate.add(ifname)
Packit Service 0535c1
                elif (
Packit Service 0535c1
                    iface_desired_state[Interface.TYPE] == InterfaceType.VXLAN
Packit Service 0535c1
                ):
Packit Service 0535c1
                    new_vxlan_ifaces_to_activate.add(ifname)
Packit Service 0535c1
                else:
Packit Service 0535c1
                    new_ifaces_to_activate.add(ifname)
Packit Service 0535c1
            elif iface_desired_state[Interface.STATE] == InterfaceState.ABSENT:
Packit Service 0535c1
                # Delete the down profiles
Packit Service 0535c1
                iface_name = iface_desired_state[Interface.NAME]
Packit Service 0535c1
                for current_profile in current_profiles:
Packit Service 0535c1
                    if current_profile.get_interface_name() == iface_name:
Packit Service 0535c1
                        profile = connection.ConnectionProfile(
Packit Service 0535c1
                            context, current_profile
Packit Service 0535c1
                        )
Packit Service 0535c1
                        profiles_to_delete.append(profile)
Packit Service 0535c1
Packit Service 0535c1
        else:
Packit Service 0535c1
            if not nmdev.get_managed():
Packit Service 0535c1
                nmdev.set_managed(True)
Packit Service 0535c1
                if iface_desired_state[Interface.STATE] == InterfaceState.DOWN:
Packit Service 0535c1
                    devs_to_activate_beforehand.append(nmdev)
Packit Service 0535c1
            if iface_desired_state[Interface.STATE] == InterfaceState.UP:
Packit Service 0535c1
                if (
Packit Service 0535c1
                    iface_desired_state.get(Interface.TYPE)
Packit Service 0535c1
                    == InterfaceType.BOND
Packit Service 0535c1
                ):
Packit Service 0535c1
                    iface = BondIface(iface_desired_state)
Packit Service 0535c1
                    if iface.is_bond_mode_changed:
Packit Service 0535c1
                        # NetworkManager leaves leftover in sysfs for bond
Packit Service 0535c1
                        # options when changing bond mode, bug:
Packit Service 0535c1
                        # https://bugzilla.redhat.com/show_bug.cgi?id=1819137
Packit Service 0535c1
                        # Workaround: delete the bond interface from kernel and
Packit Service 0535c1
                        # create again via full deactivation beforehand.
Packit Service 0535c1
                        logging.debug(
Packit Service 0535c1
                            f"Bond interface {ifname} is changing bond mode, "
Packit Service 0535c1
                            "will do full deactivation before applying changes"
Packit Service 0535c1
                        )
Packit Service 0535c1
                        devs_to_deactivate_beforehand.append(nmdev)
Packit Service 0535c1
Packit Service 0535c1
                if _is_master_iface(iface_desired_state):
Packit Service 0535c1
                    master_ifaces_to_edit.add(
Packit Service 0535c1
                        (nmdev, con_profiles_by_devname[ifname].profile)
Packit Service 0535c1
                    )
Packit Service 0535c1
                else:
Packit Service 0535c1
                    ifaces_to_edit.add(
Packit Service 0535c1
                        (nmdev, con_profiles_by_devname[ifname].profile)
Packit Service 0535c1
                    )
Packit Service 0535c1
            elif iface_desired_state[Interface.STATE] in (
Packit Service 0535c1
                InterfaceState.DOWN,
Packit Service 0535c1
                InterfaceState.ABSENT,
Packit Service 0535c1
            ):
Packit Service 0535c1
                nmdevs = _get_affected_devices(context, iface_desired_state)
Packit Service 0535c1
                is_absent = (
Packit Service 0535c1
                    iface_desired_state[Interface.STATE]
Packit Service 0535c1
                    == InterfaceState.ABSENT
Packit Service 0535c1
                )
Packit Service 0535c1
                for affected_nmdev in nmdevs:
Packit Service 44efa8
                    devs_to_deactivate[
Packit Service 44efa8
                        affected_nmdev.get_iface()
Packit Service 44efa8
                    ] = affected_nmdev
Packit Service 44efa8
                    if is_absent:
Packit Service 44efa8
                        devs_to_delete_profile[
Packit Service 0535c1
                            affected_nmdev.get_iface()
Packit Service 0535c1
                        ] = affected_nmdev
Packit Service 0535c1
                if (
Packit Service 0535c1
                    is_absent
Packit Service 0535c1
                    and nmdev.is_software()
Packit Service 0535c1
                    and nmdev.get_device_type() != NM.DeviceType.VETH
Packit Service 0535c1
                ):
Packit Service 0535c1
                    devs_to_delete[nmdev.get_iface()] = nmdev
Packit Service 0535c1
            else:
Packit Service 0535c1
                raise NmstateValueError(
Packit Service 0535c1
                    "Invalid state {} for interface {}".format(
Packit Service 0535c1
                        iface_desired_state[Interface.STATE],
Packit Service 0535c1
                        iface_desired_state[Interface.NAME],
Packit Service 0535c1
                    )
Packit Service 0535c1
                )
Packit Service 0535c1
Packit Service 0535c1
    for nmdev in devs_to_activate_beforehand:
Packit Service 0535c1
        profile = connection.ConnectionProfile(context)
Packit Service 0535c1
        profile.con_id = nmdev.get_iface()
Packit Service 0535c1
        profile.activate()
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev in devs_to_deactivate_beforehand:
Packit Service 0535c1
        device.deactivate(context, dev)
Packit Service 0535c1
Packit Service 0535c1
    # Do not remove devices that are marked for editing.
Packit Service 0535c1
    for dev, _ in itertools.chain(master_ifaces_to_edit, ifaces_to_edit):
Packit Service 0535c1
        devs_to_deactivate.pop(dev.get_iface(), None)
Packit Service 0535c1
        devs_to_delete_profile.pop(dev.get_iface(), None)
Packit Service 0535c1
        devs_to_delete.pop(dev.get_iface(), None)
Packit Service 0535c1
Packit Service 0535c1
    for profile in profiles_to_delete:
Packit Service 0535c1
        profile.delete()
Packit Service 0535c1
        context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_master_not_enslaved_ifaces:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_ifaces_to_activate:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev, con_profile in master_ifaces_to_edit:
Packit Service 0535c1
        device.modify(context, dev, con_profile)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_ovs_port_to_activate:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_ovs_interface_to_activate:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev, con_profile in ifaces_to_edit:
Packit Service 0535c1
        device.modify(context, dev, con_profile)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_vlan_ifaces_to_activate:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for ifname in new_vxlan_ifaces_to_activate:
Packit Service 0535c1
        device.activate(context, dev=None, connection_id=ifname)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev in devs_to_deactivate.values():
Packit Service 0535c1
        device.deactivate(context, dev)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev in devs_to_delete_profile.values():
Packit Service 0535c1
        device.delete(context, dev)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
    for dev in devs_to_delete.values():
Packit Service 0535c1
        device.delete_device(context, dev)
Packit Service 0535c1
    context.wait_all_finish()
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _index_profiles_by_devname(con_profiles):
Packit Service 0535c1
    return {con_profile.devname: con_profile for con_profile in con_profiles}
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _get_new_ifaces(context, con_profiles):
Packit Service 0535c1
    ifaces_without_device = set()
Packit Service 0535c1
    for con_profile in con_profiles:
Packit Service 0535c1
        ifname = con_profile.devname
Packit Service 0535c1
        nmdev = context.get_nm_dev(ifname)
Packit Service 0535c1
        if not nmdev:
Packit Service 0535c1
            # When the profile id is different from the iface name, use the
Packit Service 0535c1
            # profile id.
Packit Service 0535c1
            if ifname != con_profile.con_id:
Packit Service 0535c1
                ifname = con_profile.con_id
Packit Service 0535c1
            ifaces_without_device.add(ifname)
Packit Service 0535c1
    return ifaces_without_device
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _is_master_iface(iface_state):
Packit Service 0535c1
    return iface_state[Interface.TYPE] in MASTER_IFACE_TYPES
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _is_slave_iface(iface_state):
Packit Service 0535c1
    return iface_state.get(MASTER_METADATA)
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _get_affected_devices(context, iface_state):
Packit Service 0535c1
    nmdev = context.get_nm_dev(iface_state[Interface.NAME])
Packit Service 0535c1
    devs = []
Packit Service 0535c1
    if nmdev:
Packit Service 0535c1
        devs += [nmdev]
Packit Service 0535c1
        iface_type = iface_state[Interface.TYPE]
Packit Service 0535c1
        if iface_type == InterfaceType.OVS_BRIDGE:
Packit Service 0535c1
            port_slaves = ovs.get_slaves(nmdev)
Packit Service 0535c1
            iface_slaves = [
Packit Service 0535c1
                iface for port in port_slaves for iface in ovs.get_slaves(port)
Packit Service 0535c1
            ]
Packit Service 0535c1
            devs += port_slaves + iface_slaves
Packit Service 0535c1
        elif iface_type == LB.TYPE:
Packit Service 0535c1
            devs += bridge.get_slaves(nmdev)
Packit Service 0535c1
        elif iface_type == bond.BOND_TYPE:
Packit Service 0535c1
            devs += bond.get_slaves(nmdev)
Packit Service 0535c1
Packit Service 0535c1
        ovs_port_dev = ovs.get_port_by_slave(nmdev)
Packit Service 0535c1
        if ovs_port_dev:
Packit Service 0535c1
            devs.append(ovs_port_dev)
Packit Service 0535c1
    return devs
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _create_proxy_ifaces_desired_state(ifaces_desired_state):
Packit Service 0535c1
    """
Packit Service 0535c1
    Prepare the state of the "proxy" interfaces. These are interfaces that
Packit Service 0535c1
    exist as NM entities/profiles, but are invisible to the API.
Packit Service 0535c1
    These proxy interfaces state is created as a side effect of other ifaces
Packit Service 0535c1
    definition.
Packit Service 0535c1
    Note: This function modifies the ifaces_desired_state content in addition
Packit Service 0535c1
    to returning a new set of states for the proxy interfaces.
Packit Service 0535c1
Packit Service 0535c1
    In OVS case, the port profile is the proxy, it is not part of the public
Packit Service 0535c1
    state of the system, but internal to the NM provider.
Packit Service 0535c1
    """
Packit Service 0535c1
    new_ifaces_desired_state = []
Packit Service 0535c1
    new_ifaces_names = set()
Packit Service 0535c1
    for iface_desired_state in ifaces_desired_state:
Packit Service 0535c1
        master_type = iface_desired_state.get(MASTER_TYPE_METADATA)
Packit Service 0535c1
        if master_type != InterfaceType.OVS_BRIDGE:
Packit Service 0535c1
            continue
Packit Service 0535c1
        port_opts_metadata = iface_desired_state.get(
Packit Service 0535c1
            BridgeIface.BRPORT_OPTIONS_METADATA
Packit Service 0535c1
        )
Packit Service 0535c1
        if port_opts_metadata is None:
Packit Service 0535c1
            continue
Packit Service 0535c1
        port_iface_desired_state = _create_ovs_port_iface_desired_state(
Packit Service 0535c1
            iface_desired_state, port_opts_metadata
Packit Service 0535c1
        )
Packit Service 0535c1
        port_iface_name = port_iface_desired_state[Interface.NAME]
Packit Service 0535c1
        if port_iface_name not in new_ifaces_names:
Packit Service 0535c1
            new_ifaces_names.add(port_iface_name)
Packit Service 0535c1
            new_ifaces_desired_state.append(port_iface_desired_state)
Packit Service 0535c1
        # The "visible" slave/interface needs to point to the port profile
Packit Service 0535c1
        iface_desired_state[MASTER_METADATA] = port_iface_desired_state[
Packit Service 0535c1
            Interface.NAME
Packit Service 0535c1
        ]
Packit Service 0535c1
        iface_desired_state[MASTER_TYPE_METADATA] = InterfaceType.OVS_PORT
Packit Service 0535c1
    return new_ifaces_desired_state
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _create_ovs_port_iface_desired_state(iface_desired_state, port_options):
Packit Service 0535c1
    iface_name = iface_desired_state[Interface.NAME]
Packit Service 0535c1
    if _is_ovs_lag_port(port_options):
Packit Service 0535c1
        port_name = port_options[OvsB.Port.NAME]
Packit Service 0535c1
    else:
Packit Service 0535c1
        port_name = ovs.PORT_PROFILE_PREFIX + iface_name
Packit Service 0535c1
    return {
Packit Service 0535c1
        Interface.NAME: port_name,
Packit Service 0535c1
        Interface.TYPE: InterfaceType.OVS_PORT,
Packit Service 0535c1
        Interface.STATE: iface_desired_state[Interface.STATE],
Packit Service 0535c1
        OvsB.OPTIONS_SUBTREE: port_options,
Packit Service 0535c1
        MASTER_METADATA: iface_desired_state[MASTER_METADATA],
Packit Service 0535c1
        MASTER_TYPE_METADATA: iface_desired_state[MASTER_TYPE_METADATA],
Packit Service 0535c1
    }
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _is_ovs_lag_port(port_state):
Packit Service 0535c1
    return port_state.get(OvsB.Port.LINK_AGGREGATION_SUBTREE) is not None
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _build_connection_profile(
Packit Service 0535c1
    context,
Packit Service 0535c1
    iface_desired_state,
Packit Service 0535c1
    base_con_profile,
Packit Service 0535c1
    original_desired_iface_state,
Packit Service 0535c1
):
Packit Service 0535c1
    iface_type = translator.Api2Nm.get_iface_type(
Packit Service 0535c1
        iface_desired_state[Interface.TYPE]
Packit Service 0535c1
    )
Packit Service 0535c1
Packit Service 0535c1
    base_profile = base_con_profile.profile if base_con_profile else None
Packit Service 0535c1
Packit Service 0535c1
    settings = [
Packit Service 0535c1
        ipv4.create_setting(
Packit Service 0535c1
            iface_desired_state.get(Interface.IPV4), base_profile
Packit Service 0535c1
        ),
Packit Service 0535c1
        ipv6.create_setting(
Packit Service 0535c1
            iface_desired_state.get(Interface.IPV6), base_profile
Packit Service 0535c1
        ),
Packit Service 0535c1
    ]
Packit Service 0535c1
Packit Service 0535c1
    con_setting = connection.ConnectionSetting()
Packit Service 0535c1
    iface_name = iface_desired_state[Interface.NAME]
Packit Service 0535c1
    if base_profile:
Packit Service 0535c1
        con_setting.import_by_profile(base_con_profile)
Packit Service 0535c1
        con_setting.set_profile_name(iface_name)
Packit Service 0535c1
    else:
Packit Service 0535c1
        con_setting.create(
Packit Service 0535c1
            con_name=iface_name, iface_name=iface_name, iface_type=iface_type,
Packit Service 0535c1
        )
Packit Service 0535c1
    lldp.apply_lldp_setting(con_setting, iface_desired_state)
Packit Service 0535c1
Packit Service 0535c1
    master = iface_desired_state.get(MASTER_METADATA)
Packit Service 0535c1
    _translate_master_type(iface_desired_state)
Packit Service 0535c1
    master_type = iface_desired_state.get(MASTER_TYPE_METADATA)
Packit Service 0535c1
    con_setting.set_master(master, master_type)
Packit Service 0535c1
    settings.append(con_setting.setting)
Packit Service 0535c1
Packit Service 0535c1
    # Only apply wired/ethernet configuration based on original desire
Packit Service 0535c1
    # state rather than the merged one.
Packit Service 0535c1
    wired_setting = wired.create_setting(
Packit Service 0535c1
        original_desired_iface_state, base_profile
Packit Service 0535c1
    )
Packit Service 0535c1
    if wired_setting:
Packit Service 0535c1
        settings.append(wired_setting)
Packit Service 0535c1
Packit Service 0535c1
    user_setting = user.create_setting(iface_desired_state, base_profile)
Packit Service 0535c1
    if user_setting:
Packit Service 0535c1
        settings.append(user_setting)
Packit Service 0535c1
Packit Service 0535c1
    bond_opts = translator.Api2Nm.get_bond_options(iface_desired_state)
Packit Service 0535c1
    if bond_opts:
Packit Service 0535c1
        settings.append(bond.create_setting(bond_opts, wired_setting))
Packit Service 0535c1
    elif iface_type == bridge.BRIDGE_TYPE:
Packit Service 0535c1
        bridge_config = iface_desired_state.get(bridge.BRIDGE_TYPE, {})
Packit Service 0535c1
        bridge_options = bridge_config.get(LB.OPTIONS_SUBTREE)
Packit Service 0535c1
        bridge_ports = bridge_config.get(LB.PORT_SUBTREE)
Packit Service 0535c1
Packit Service 0535c1
        if bridge_options or bridge_ports:
Packit Service 0535c1
            linux_bridge_setting = bridge.create_setting(
Packit Service 0535c1
                iface_desired_state,
Packit Service 0535c1
                base_profile,
Packit Service 0535c1
                original_desired_iface_state,
Packit Service 0535c1
            )
Packit Service 0535c1
            settings.append(linux_bridge_setting)
Packit Service 0535c1
    elif iface_type == InterfaceType.OVS_BRIDGE:
Packit Service 0535c1
        ovs_bridge_state = iface_desired_state.get(OvsB.CONFIG_SUBTREE, {})
Packit Service 0535c1
        ovs_bridge_options = ovs_bridge_state.get(OvsB.OPTIONS_SUBTREE)
Packit Service 0535c1
        if ovs_bridge_options:
Packit Service 0535c1
            settings.append(ovs.create_bridge_setting(ovs_bridge_options))
Packit Service 0535c1
    elif iface_type == InterfaceType.OVS_PORT:
Packit Service 0535c1
        ovs_port_options = iface_desired_state.get(OvsB.OPTIONS_SUBTREE)
Packit Service 0535c1
        settings.append(ovs.create_port_setting(ovs_port_options))
Packit Service 0535c1
    elif iface_type == InterfaceType.OVS_INTERFACE:
Packit Service 0535c1
        patch_state = iface_desired_state.get(
Packit Service 0535c1
            OVSInterface.PATCH_CONFIG_SUBTREE
Packit Service 0535c1
        )
Packit Service 0535c1
        settings.extend(ovs.create_interface_setting(patch_state))
Packit Service 0535c1
Packit Service 0535c1
    bridge_port_options = iface_desired_state.get(
Packit Service 0535c1
        BridgeIface.BRPORT_OPTIONS_METADATA
Packit Service 0535c1
    )
Packit Service 0535c1
    if bridge_port_options and master_type == bridge.BRIDGE_TYPE:
Packit Service 0535c1
        settings.append(
Packit Service 0535c1
            bridge.create_port_setting(bridge_port_options, base_profile)
Packit Service 0535c1
        )
Packit Service 0535c1
Packit Service 0535c1
    vlan_setting = vlan.create_setting(iface_desired_state, base_profile)
Packit Service 0535c1
    if vlan_setting:
Packit Service 0535c1
        settings.append(vlan_setting)
Packit Service 0535c1
Packit Service 0535c1
    vxlan_setting = vxlan.create_setting(iface_desired_state, base_profile)
Packit Service 0535c1
    if vxlan_setting:
Packit Service 0535c1
        settings.append(vxlan_setting)
Packit Service 0535c1
Packit Service 0535c1
    sriov_setting = sriov.create_setting(
Packit Service 0535c1
        context, iface_desired_state, base_con_profile
Packit Service 0535c1
    )
Packit Service 0535c1
    if sriov_setting:
Packit Service 0535c1
        settings.append(sriov_setting)
Packit Service 0535c1
Packit Service 0535c1
    team_setting = team.create_setting(iface_desired_state, base_con_profile)
Packit Service 0535c1
    if team_setting:
Packit Service 0535c1
        settings.append(team_setting)
Packit Service 0535c1
Packit Service 0535c1
    new_profile = connection.ConnectionProfile(context)
Packit Service 0535c1
    new_profile.create(settings)
Packit Service 0535c1
    return new_profile
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _translate_master_type(iface_desired_state):
Packit Service 0535c1
    """
Packit Service 0535c1
    Translates the master type metadata names to their equivalent
Packit Service 0535c1
    NM type names.
Packit Service 0535c1
    """
Packit Service 0535c1
    master_type = iface_desired_state.get(MASTER_TYPE_METADATA)
Packit Service 0535c1
    if master_type == LB.TYPE:
Packit Service 0535c1
        iface_desired_state[MASTER_TYPE_METADATA] = bridge.BRIDGE_TYPE
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def _preapply_dns_fix(context, net_state):
Packit Service 0535c1
    """
Packit Service 0535c1
     * When DNS configuration does not changed and old interface hold DNS
Packit Service 0535c1
       configuration is not included in `ifaces_desired_state`, preserve
Packit Service 0535c1
       the old DNS configure by removing DNS metadata from
Packit Service 0535c1
       `ifaces_desired_state`.
Packit Service 0535c1
     * When DNS configuration changed, include old interface which is holding
Packit Service 0535c1
       DNS configuration, so it's DNS configure could be removed.
Packit Service 0535c1
    """
Packit Service 0535c1
    cur_dns_iface_names = get_dns_config_iface_names(
Packit Service 0535c1
        ipv4.acs_and_ip_profiles(context.client),
Packit Service 0535c1
        ipv6.acs_and_ip_profiles(context.client),
Packit Service 0535c1
    )
Packit Service 0535c1
Packit Service 0535c1
    # Whether to mark interface as changed which is used for holding old DNS
Packit Service 0535c1
    # configurations
Packit Service 0535c1
    remove_existing_dns_config = False
Packit Service 0535c1
    # Whether to preserve old DNS config by DNS metadata to be removed from
Packit Service 0535c1
    # desired state
Packit Service 0535c1
    preserve_old_dns_config = False
Packit Service 0535c1
    if net_state.dns.config == net_state.dns.current_config:
Packit Service 0535c1
        for cur_dns_iface_name in cur_dns_iface_names:
Packit Service 0535c1
            iface = net_state.ifaces[cur_dns_iface_name]
Packit Service 0535c1
            if iface.is_changed or iface.is_desired:
Packit Service 0535c1
                remove_existing_dns_config = True
Packit Service 0535c1
        if not remove_existing_dns_config:
Packit Service 0535c1
            preserve_old_dns_config = True
Packit Service 0535c1
    else:
Packit Service 0535c1
        remove_existing_dns_config = True
Packit Service 0535c1
Packit Service 0535c1
    if remove_existing_dns_config:
Packit Service 0535c1
        for cur_dns_iface_name in cur_dns_iface_names:
Packit Service 0535c1
            iface = net_state.ifaces[cur_dns_iface_name]
Packit Service 0535c1
            iface.mark_as_changed()
Packit Service 0535c1
Packit Service 0535c1
    if preserve_old_dns_config:
Packit Service 0535c1
        for iface in net_state.ifaces.values():
Packit Service 0535c1
            if iface.is_changed or iface.is_desired:
Packit Service 0535c1
                iface.remove_dns_metadata()