Blame libnmstate/nm/dns.py

Packit Service 0535c1
#
Packit Service 0535c1
# Copyright (c) 2019-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 itertools import chain
Packit Service 0535c1
from operator import itemgetter
Packit Service 0535c1
Packit Service 0535c1
from libnmstate import iplib
Packit Service 0535c1
from libnmstate.dns import DnsState
Packit Service 0535c1
from libnmstate.error import NmstateInternalError
Packit Service 0535c1
from libnmstate.nm import active_connection as nm_ac
Packit Service 0535c1
from libnmstate.schema import DNS
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
DNS_DEFAULT_PRIORITY_VPN = 50
Packit Service 0535c1
DNS_DEFAULT_PRIORITY_OTHER = 100
Packit Service 0535c1
DEFAULT_DNS_PRIORITY = 0
Packit Service 0535c1
# The 40 is chose as default DHCP DNS priority is 100, and VPN DNS priority is
Packit Service 0535c1
# 50, the static DNS configuration should be list before them.
Packit Service 0535c1
DNS_PRIORITY_STATIC_BASE = 40
Packit Service 0535c1
Packit Service 0535c1
IPV6_ADDRESS_LENGTH = 128
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def get_running(context):
Packit Service 0535c1
    dns_state = {DNS.SERVER: [], DNS.SEARCH: []}
Packit Service 0535c1
    for dns_conf in context.get_dns_configuration():
Packit Service 0535c1
        iface_name = dns_conf.get_interface()
Packit Service 0535c1
        for ns in dns_conf.get_nameservers():
Packit Service 0535c1
            if iplib.is_ipv6_link_local_addr(ns, IPV6_ADDRESS_LENGTH):
Packit Service 0535c1
                if not iface_name:
Packit Service 0535c1
                    # For IPv6 link local address, the interface name should be
Packit Service 0535c1
                    # appended also.
Packit Service 0535c1
                    raise NmstateInternalError(
Packit Service 0535c1
                        "Missing interface for IPv6 link-local DNS server "
Packit Service 0535c1
                        "entry {}".format(ns)
Packit Service 0535c1
                    )
Packit Service 0535c1
                ns_addr = "{}%{}".format(ns, iface_name)
Packit Service 0535c1
            else:
Packit Service 0535c1
                ns_addr = ns
Packit Service 0535c1
            if ns_addr not in dns_state[DNS.SERVER]:
Packit Service 0535c1
                dns_state[DNS.SERVER].append(ns_addr)
Packit Service 0535c1
        dns_domains = [
Packit Service 0535c1
            dns_domain
Packit Service 0535c1
            for dns_domain in dns_conf.get_domains()
Packit Service 0535c1
            if dns_domain not in dns_state[DNS.SEARCH]
Packit Service 0535c1
        ]
Packit Service 0535c1
        dns_state[DNS.SEARCH].extend(dns_domains)
Packit Service 0535c1
    if not dns_state[DNS.SERVER] and not dns_state[DNS.SEARCH]:
Packit Service 0535c1
        dns_state = {}
Packit Service 0535c1
    return dns_state
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def get_config(acs_and_ipv4_profiles, acs_and_ipv6_profiles):
Packit Service 0535c1
    dns_conf = {DNS.SERVER: [], DNS.SEARCH: []}
Packit Service 0535c1
    tmp_dns_confs = []
Packit Service 0535c1
    for ac, ip_profile in chain(acs_and_ipv6_profiles, acs_and_ipv4_profiles):
Packit Service 0535c1
        if not ip_profile.props.dns and not ip_profile.props.dns_search:
Packit Service 0535c1
            continue
Packit Service 0535c1
        priority = ip_profile.props.dns_priority
Packit Service 0535c1
        if priority == DEFAULT_DNS_PRIORITY:
Packit Service 0535c1
            # ^ The dns_priority in 'NetworkManager.conf' is been ignored
Packit Service 0535c1
            #   due to the lacking of query function in libnm API.
Packit Service 0535c1
            if ac.get_vpn():
Packit Service 0535c1
                priority = DNS_DEFAULT_PRIORITY_VPN
Packit Service 0535c1
            else:
Packit Service 0535c1
                priority = DNS_DEFAULT_PRIORITY_OTHER
Packit Service 0535c1
Packit Service 0535c1
        tmp_dns_confs.append(
Packit Service 0535c1
            {
Packit Service 0535c1
                "server": ip_profile.props.dns,
Packit Service 0535c1
                "priority": priority,
Packit Service 0535c1
                "search": ip_profile.props.dns_search,
Packit Service 0535c1
            }
Packit Service 0535c1
        )
Packit Service 0535c1
    # NetworkManager sorts the DNS entries based on various criteria including
Packit Service 0535c1
    # which profile was activated first when profiles are activated. Therefore
Packit Service 0535c1
    # the configuration does not completely define the order. To define the
Packit Service 0535c1
    # order in a declarative way, Nmstate only uses the priority to order the
Packit Service 0535c1
    # entries. Reference:
Packit Service 0535c1
    # https://developer.gnome.org/NetworkManager/stable/nm-settings.html#nm-settings.property.ipv4.dns-priority
Packit Service 0535c1
    tmp_dns_confs.sort(key=itemgetter("priority"))
Packit Service 0535c1
    for e in tmp_dns_confs:
Packit Service 0535c1
        dns_conf[DNS.SERVER].extend(e["server"])
Packit Service 0535c1
        dns_conf[DNS.SEARCH].extend(e["search"])
Packit Service 0535c1
    if not dns_conf[DNS.SERVER] and dns_conf[DNS.SEARCH]:
Packit Service 0535c1
        return {}
Packit Service 0535c1
    return dns_conf
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def add_dns(setting_ip, dns_state):
Packit Service 0535c1
    priority = dns_state.get(DnsState.PRIORITY_METADATA)
Packit Service 0535c1
    if priority is not None:
Packit Service 0535c1
        setting_ip.props.dns_priority = priority + DNS_PRIORITY_STATIC_BASE
Packit Service 0535c1
    for server in dns_state.get(DNS.SERVER, []):
Packit Service 0535c1
        setting_ip.add_dns(server)
Packit Service 0535c1
    for search in dns_state.get(DNS.SEARCH, []):
Packit Service 0535c1
        setting_ip.add_dns_search(search)
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def get_dns_config_iface_names(acs_and_ipv4_profiles, acs_and_ipv6_profiles):
Packit Service 0535c1
    """
Packit Service 0535c1
    Return a list of interface names which hold static DNS configuration.
Packit Service 0535c1
    """
Packit Service 0535c1
    iface_names = []
Packit Service 0535c1
    for ac, ip_profile in chain(acs_and_ipv6_profiles, acs_and_ipv4_profiles):
Packit Service 0535c1
        if ip_profile.props.dns or ip_profile.props.dns_search:
Packit Service 0535c1
            iface_names.append(nm_ac.ActiveConnection(nm_ac_con=ac).devname)
Packit Service 0535c1
    return iface_names