def upgrade_shared_networks(shared_networks): """Update the `shared_networks` structure to match the V2 calls. Mutates `shared_networks` in place. """ for shared_network in shared_networks: for subnet in shared_network["subnets"]: dns_servers = subnet["dns_servers"] if isinstance(dns_servers, str): dns_servers = map(IPAddress, split_string_list(dns_servers)) subnet["dns_servers"] = list(dns_servers) if "ntp_server" in subnet: # Note singular. ntp_servers = split_string_list(subnet.pop("ntp_server")) subnet["ntp_servers"] = list(ntp_servers)
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 test__eliminates_empty_words(self, delimiter): word = factory.make_name("word") self.assertThat(list(split_string_list(delimiter + word + delimiter)), Equals([word]))
def test__normalises_nothing_but_delimiter_to_empty_list(self, delimiter): self.assertThat(list(split_string_list(delimiter)), Equals([]))
def test__splits_at_delimiters(self, delimiter): words = [factory.make_name("word") for _ in range(5)] string = delimiter.join(words) self.assertThat(list(split_string_list(string)), Equals(words))
def _get_external_servers() -> Iterable[str]: """Get the configured external NTP servers.""" ntp_servers = Config.objects.get_config("ntp_servers") return split_string_list(ntp_servers)