Ejemplo n.º 1
0
 def test__returns_all_authoritative_domains(self):
     domain_names = get_dns_search_paths()
     domain_names.update(
         factory.make_Domain(authoritative=True).name for _ in range(3))
     for _ in range(3):
         factory.make_Domain(authoritative=False)
     self.assertItemsEqual(domain_names, get_dns_search_paths())
Ejemplo n.º 2
0
 def collectDNSConfig(self, node, ipv4=True, ipv6=True):
     config = "- type: nameserver\n  address: %s\n  search:\n" % (repr(
         node.get_default_dns_servers(ipv4=ipv4, ipv6=ipv6)))
     domain_name = node.domain.name
     dns_searches = [domain_name] + [
         name
         for name in sorted(get_dns_search_paths()) if name != domain_name
     ]
     for dns_name in dns_searches:
         config += "   - %s\n" % dns_name
     return config
Ejemplo n.º 3
0
 def get_dns_search_list(self, domain_name):
     return [domain_name] + [
         name
         for name in sorted(get_dns_search_paths()) if name != domain_name
     ]
Ejemplo n.º 4
0
    def __init__(self, node, version=1, source_routing=False):
        """Create the YAML network configuration for the specified node, and
        store it in the `config` ivar.
        """
        self.node = node
        self.matching_routes = set()
        self.v1_config = []
        self.v2_config = [
            ("version", 2),
        ]
        self.v2_ethernets = {}
        self.v2_vlans = {}
        self.v2_bonds = {}
        self.v2_bridges = {}
        # Reserved routing tables in Linux are 0, 253, 254, and 255.
        self.next_routing_table_id = 1
        self.gateway_ipv4_set = False
        self.gateway_ipv6_set = False
        self.source_routing = source_routing

        # The default value is False: expected keys are 4 and 6.
        self.addr_family_present = defaultdict(bool)

        # Ensure the machine's primary domain always comes first in the list.
        self.default_search_list = [self.node.domain.name] + [
            name for name in sorted(get_dns_search_paths())
            if name != self.node.domain.name
        ]

        self.gateways = self.node.get_default_gateways()
        if self.gateways.ipv4 is not None:
            dest_ip = self.gateways.ipv4.gateway_ip
        elif self.gateways.ipv6 is not None:
            dest_ip = self.gateways.ipv6.gateway_ip
        else:
            dest_ip = None
        if dest_ip is not None:
            default_source_ip = get_source_address(dest_ip)
        else:
            default_source_ip = None

        self.routes = StaticRoute.objects.all()

        interfaces = Interface.objects.all_interfaces_parents_first(self.node)
        for iface in interfaces:
            if not iface.is_enabled():
                continue
            generator = InterfaceConfiguration(
                iface,
                self,
                version=version,
                source_routing=self.source_routing)
            self.matching_routes.update(generator.matching_routes)
            self.addr_family_present.update(generator.addr_family_present)
            if version == 1:
                self.v1_config.append(generator.config)
            elif version == 2:
                v2_config = {generator.name: generator.config}
                if generator.type == INTERFACE_TYPE.PHYSICAL:
                    self.v2_ethernets.update(v2_config)
                elif generator.type == INTERFACE_TYPE.VLAN:
                    self.v2_vlans.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BOND:
                    self.v2_bonds.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BRIDGE:
                    self.v2_bridges.update(v2_config)

        # If we have no IPv6 addresses present, make sure we claim IPv4, so
        # that we at least get some address.
        if not self.addr_family_present[6]:
            self.addr_family_present[4] = True
        self.default_dns_servers = self.node.get_default_dns_servers(
            ipv4=self.addr_family_present[4],
            ipv6=self.addr_family_present[6],
            default_region_ip=default_source_ip)
        self.v1_config.append({
            "type": "nameserver",
            "address": self.default_dns_servers,
            "search": self.default_search_list,
        })
        if version == 1:
            network_config = {
                "network": {
                    "version": 1,
                    "config": self.v1_config,
                },
            }
        else:
            if len(self.v2_ethernets) > 0:
                self.v2_config.append(('ethernets', self.v2_ethernets))
            if len(self.v2_vlans) > 0:
                self.v2_config.append(('vlans', self.v2_vlans))
            if len(self.v2_bonds) > 0:
                self.v2_config.append(('bonds', self.v2_bonds))
            if len(self.v2_bridges) > 0:
                self.v2_config.append(('bridges', self.v2_bridges))
            self.set_v2_default_dns()
            network_config = {
                "network": OrderedDict(self.v2_config),
            }
        self.config = network_config
Ejemplo n.º 5
0
def get_dhcp_configuration(rack_controller, test_dhcp_snippet=None):
    """Return tuple with IPv4 and IPv6 configurations for the
    rack controller."""
    # Get list of all vlans that are being managed by the rack controller.
    vlans = gen_managed_vlans_for(rack_controller)

    # Group the subnets on each VLAN into IPv4 and IPv6 subnets.
    vlan_subnets = {
        vlan: split_managed_ipv4_ipv6_subnets(vlan.subnet_set.all())
        for vlan in vlans
    }

    # Get the list of all DHCP snippets so we only have to query the database
    # 1 + (the number of DHCP snippets used in this VLAN) instead of
    # 1 + (the number of subnets in this VLAN) +
    #     (the number of nodes in this VLAN)
    dhcp_snippets = DHCPSnippet.objects.filter(enabled=True)
    # If we're testing a DHCP Snippet insert it into our list
    if test_dhcp_snippet is not None:
        dhcp_snippets = list(dhcp_snippets)
        replaced_snippet = False
        # If its an existing DHCPSnippet with its contents being modified
        # replace it with the new values and test
        for i, dhcp_snippet in enumerate(dhcp_snippets):
            if dhcp_snippet.id == test_dhcp_snippet.id:
                dhcp_snippets[i] = test_dhcp_snippet
                replaced_snippet = True
                break
        # If the snippet wasn't updated its either new or testing a currently
        # disabled snippet
        if not replaced_snippet:
            dhcp_snippets.append(test_dhcp_snippet)
    global_dhcp_snippets = [
        make_dhcp_snippet(dhcp_snippet) for dhcp_snippet in dhcp_snippets
        if dhcp_snippet.node is None and dhcp_snippet.subnet is None
    ]

    # Configure both DHCPv4 and DHCPv6 on the rack controller.
    failover_peers_v4 = []
    shared_networks_v4 = []
    hosts_v4 = []
    interfaces_v4 = set()
    failover_peers_v6 = []
    shared_networks_v6 = []
    hosts_v6 = []
    interfaces_v6 = set()

    # DNS can either go through the rack controller or directly to the
    # region controller.
    use_rack_proxy = Config.objects.get_config("use_rack_proxy")

    # NTP configuration can get tricky...
    ntp_external_only = Config.objects.get_config("ntp_external_only")
    if ntp_external_only:
        ntp_servers = Config.objects.get_config("ntp_servers")
        ntp_servers = list(split_string_list(ntp_servers))
    else:
        ntp_servers = get_ntp_server_addresses_for_rack(rack_controller)

    default_domain = Domain.objects.get_default_domain()
    search_list = [default_domain.name] + [
        name for name in sorted(get_dns_search_paths())
        if name != default_domain.name
    ]
    for vlan, (subnets_v4, subnets_v6) in vlan_subnets.items():
        # IPv4
        if len(subnets_v4) > 0:
            config = get_dhcp_configure_for(
                4,
                rack_controller,
                vlan,
                subnets_v4,
                ntp_servers,
                default_domain,
                search_list=search_list,
                dhcp_snippets=dhcp_snippets,
                use_rack_proxy=use_rack_proxy,
            )
            failover_peer, subnets, hosts, interface = config
            if failover_peer is not None:
                failover_peers_v4.append(failover_peer)
            shared_network = {
                "name": "vlan-%d" % vlan.id,
                "mtu": vlan.mtu,
                "subnets": subnets,
            }
            shared_networks_v4.append(shared_network)
            hosts_v4.extend(hosts)
            if interface is not None:
                interfaces_v4.add(interface)
                shared_network["interface"] = interface
        # IPv6
        if len(subnets_v6) > 0:
            config = get_dhcp_configure_for(
                6,
                rack_controller,
                vlan,
                subnets_v6,
                ntp_servers,
                default_domain,
                search_list=search_list,
                dhcp_snippets=dhcp_snippets,
                use_rack_proxy=use_rack_proxy,
            )
            failover_peer, subnets, hosts, interface = config
            if failover_peer is not None:
                failover_peers_v6.append(failover_peer)
            shared_network = {
                "name": "vlan-%d" % vlan.id,
                "mtu": vlan.mtu,
                "subnets": subnets,
            }
            shared_networks_v6.append(shared_network)
            hosts_v6.extend(hosts)
            if interface is not None:
                interfaces_v6.add(interface)
                shared_network["interface"] = interface
    # When no interfaces exist for each IP version clear the shared networks
    # as DHCP server cannot be started and needs to be stopped.
    if len(interfaces_v4) == 0:
        shared_networks_v4 = {}
    if len(interfaces_v6) == 0:
        shared_networks_v6 = {}
    return DHCPConfigurationForRack(
        failover_peers_v4,
        shared_networks_v4,
        hosts_v4,
        interfaces_v4,
        failover_peers_v6,
        shared_networks_v6,
        hosts_v6,
        interfaces_v6,
        get_omapi_key(),
        global_dhcp_snippets,
    )
Ejemplo n.º 6
0
    def __init__(self, node, version=1):
        """Create the YAML network configuration for the specified node, and
        store it in the `config` ivar.
        """
        self.node = node
        self.matching_routes = set()
        self.v1_config = []
        self.v2_config = {"version": 2}
        self.v2_ethernets = {}
        self.v2_vlans = {}
        self.v2_bonds = {}
        self.v2_bridges = {}
        self.gateway_ipv4_set = False
        self.gateway_ipv6_set = False

        # The default value is False: expected keys are 4 and 6.
        self.addr_family_present = defaultdict(bool)

        # Ensure the machine's primary domain always comes first in the list.
        self.default_search_list = [self.node.domain.name] + [
            name for name in sorted(get_dns_search_paths())
            if name != self.node.domain.name
        ]

        self.gateways = self.node.get_default_gateways()
        if self.gateways.ipv4 is not None:
            dest_ip = self.gateways.ipv4.gateway_ip
        elif self.gateways.ipv6 is not None:
            dest_ip = self.gateways.ipv6.gateway_ip
        else:
            dest_ip = None
        if dest_ip is not None:
            default_source_ip = get_source_address(dest_ip)
        else:
            default_source_ip = None

        self.routes = StaticRoute.objects.all()

        interfaces = Interface.objects.all_interfaces_parents_first(self.node)
        for iface in interfaces:
            if not iface.is_enabled():
                continue
            generator = InterfaceConfiguration(iface, self, version=version)
            self.matching_routes.update(generator.matching_routes)
            self.addr_family_present.update(generator.addr_family_present)
            if version == 1:
                self.v1_config.append(generator.config)
            elif version == 2:
                v2_config = {generator.name: generator.config}
                if generator.type == INTERFACE_TYPE.PHYSICAL:
                    self.v2_ethernets.update(v2_config)
                elif generator.type == INTERFACE_TYPE.VLAN:
                    self.v2_vlans.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BOND:
                    self.v2_bonds.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BRIDGE:
                    self.v2_bridges.update(v2_config)

        # If we have no IPv6 addresses present, make sure we claim IPv4, so
        # that we at least get some address.
        if not self.addr_family_present[6]:
            self.addr_family_present[4] = True
        default_dns_servers = self.node.get_default_dns_servers(
            ipv4=self.addr_family_present[4],
            ipv6=self.addr_family_present[6],
            default_region_ip=default_source_ip)
        self.v1_config.append({
            "type": "nameserver",
            "address": default_dns_servers,
            "search": self.default_search_list,
        })
        if version == 1:
            network_config = {
                "network": {
                    "version": 1,
                    "config": self.v1_config,
                },
            }
        else:
            network_config = {
                "network": self.v2_config,
            }
            v2_config = network_config['network']
            if len(self.v2_ethernets) > 0:
                v2_config.update({"ethernets": self.v2_ethernets})
            if len(self.v2_vlans) > 0:
                v2_config.update({"vlans": self.v2_vlans})
            if len(self.v2_bonds) > 0:
                v2_config.update({"bonds": self.v2_bonds})
            if len(self.v2_bridges) > 0:
                v2_config.update({"bridges": self.v2_bridges})
            # XXX mpontillo 2017-02-17: netplan has no concept of "default"
            # DNS servers. Need to define how to convey this.
            # See launchpad bug #1664806.
            # if len(default_dns_servers) > 0 or len(search_list) > 0:
            #     nameservers = {}
            #     if len(search_list) > 0:
            #         nameservers.update({"search": search_list})
            #     if len(default_dns_servers) > 0:
            #         nameservers.update({"addresses": default_dns_servers})
            #     v2_config.update({"nameservers": nameservers})
        self.config = network_config
Ejemplo n.º 7
0
    def __init__(self, node, version=1, source_routing=False):
        """Create the YAML network configuration for the specified node, and
        store it in the `config` ivar.
        """
        self.node = node
        self.matching_routes = set()
        self.v1_config = []
        self.v2_config = [("version", 2)]
        self.v2_ethernets = {}
        self.v2_vlans = {}
        self.v2_bonds = {}
        self.v2_bridges = {}
        # Reserved routing tables in Linux are 0, 253, 254, and 255.
        self.next_routing_table_id = 1
        self.gateway_ipv4_set = False
        self.gateway_ipv6_set = False
        self.source_routing = source_routing

        # The default value is False: expected keys are 4 and 6.
        self.addr_family_present = defaultdict(bool)

        # Ensure the machine's primary domain always comes first in the list.
        self.default_search_list = [self.node.domain.name] + [
            name for name in sorted(get_dns_search_paths())
            if name != self.node.domain.name
        ]

        self.gateways = self.node.get_default_gateways()
        if self.gateways.ipv4 is not None:
            dest_ip = self.gateways.ipv4.gateway_ip
        elif self.gateways.ipv6 is not None:
            dest_ip = self.gateways.ipv6.gateway_ip
        else:
            dest_ip = None
        if dest_ip is not None:
            default_source_ip = get_source_address(dest_ip)
        else:
            default_source_ip = None

        self.routes = StaticRoute.objects.all()

        interfaces = Interface.objects.all_interfaces_parents_first(self.node)
        for iface in interfaces:
            if not iface.is_enabled():
                continue
            generator = InterfaceConfiguration(
                iface,
                self,
                version=version,
                source_routing=self.source_routing,
            )
            self.matching_routes.update(generator.matching_routes)
            self.addr_family_present.update(generator.addr_family_present)
            if version == 1:
                self.v1_config.append(generator.config)
            elif version == 2:
                v2_config = {generator.name: generator.config}
                if generator.type == INTERFACE_TYPE.PHYSICAL:
                    self.v2_ethernets.update(v2_config)
                elif generator.type == INTERFACE_TYPE.VLAN:
                    self.v2_vlans.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BOND:
                    self.v2_bonds.update(v2_config)
                elif generator.type == INTERFACE_TYPE.BRIDGE:
                    self.v2_bridges.update(v2_config)

        # If we have no IPv6 addresses present, make sure we claim IPv4, so
        # that we at least get some address.
        if not self.addr_family_present[6]:
            self.addr_family_present[4] = True
        self.default_dns_servers = self.node.get_default_dns_servers(
            ipv4=self.addr_family_present[4],
            ipv6=self.addr_family_present[6],
            default_region_ip=default_source_ip,
        )
        # LP:1847537 - V1 network config only allows global DNS configuration
        # while V1 allows DNS configuration per interface. If interfaces are
        # only being manually configured or use DHCP do not include DNS servers
        # in the configuration. The DHCP server will provide them.
        dhcp_only = True
        for i in self.v1_config:
            for subnet in i.get("subnets", []):
                if subnet.get("type", "manual") not in [
                        "manual",
                        "dhcp",
                        "dhcp4",
                        "dhcp6",
                ]:
                    dhcp_only = False
                    break
            if not dhcp_only:
                break
        if self.default_dns_servers and not dhcp_only:
            self.v1_config.append({
                "type": "nameserver",
                "address": self.default_dns_servers,
                "search": self.default_search_list,
            })
        if version == 1:
            network_config = {
                "network": {
                    "version": 1,
                    "config": self.v1_config
                }
            }
        else:
            if len(self.v2_ethernets) > 0:
                self.v2_config.append(("ethernets", self.v2_ethernets))
            if len(self.v2_vlans) > 0:
                self.v2_config.append(("vlans", self.v2_vlans))
            if len(self.v2_bonds) > 0:
                self.v2_config.append(("bonds", self.v2_bonds))
            if len(self.v2_bridges) > 0:
                self.v2_config.append(("bridges", self.v2_bridges))
            self.set_v2_default_dns()
            network_config = {"network": OrderedDict(self.v2_config)}
        self.config = network_config