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())
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
def get_dns_search_list(self, domain_name): return [domain_name] + [ name for name in sorted(get_dns_search_paths()) if name != domain_name ]
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
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, )
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
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