def test__alternates_support_ipv4_and_ipv6(self): factory.make_Subnet(cidr='192.168.0.0/24') factory.make_Subnet(cidr='192.168.1.0/24') factory.make_Subnet(cidr='2001:db8::/64') maas_url = 'http://maas.io/MAAS' self.patch_resolve_hostname(["192.168.0.1", "2001:db8::1"]) rack = factory.make_RackController(url=maas_url) r1 = factory.make_RegionController() factory.make_Interface(node=r1, ip='192.168.0.1') factory.make_Interface(node=r1, ip='2001:db8::1') factory.make_Interface(node=r1, ip='192.168.1.254') r2 = factory.make_RegionController() factory.make_Interface(node=r2, ip='192.168.0.2') factory.make_Interface(node=r2, ip='2001:db8::2') r3 = factory.make_RegionController() factory.make_Interface(node=r3, ip='192.168.0.4') factory.make_Interface(node=r3, ip='2001:db8::4') # Make the "current" region controller r1. self.patch(server_address, 'get_maas_id').return_value = r1.system_id region_ips = get_maas_facing_server_addresses(rack, include_alternates=True) self.assertThat( region_ips, Equals([ IPAddress("2001:db8::1"), IPAddress("192.168.0.1"), IPAddress("2001:db8::2"), IPAddress("2001:db8::4"), IPAddress("192.168.0.2"), IPAddress("192.168.0.4"), ]))
def test__falls_back_on_IPv6_if_ipv4_set_but_no_IPv4_address_found(self): v6_ip = factory.make_ipv6_address() self.patch_resolve_hostname([v6_ip]) self.patch_get_maas_facing_server_host() self.assertEqual([IPAddress(v6_ip)], get_maas_facing_server_addresses(ipv4=True, ipv6=True))
def test__alternates_use_consistent_subnet(self): factory.make_Subnet(cidr='192.168.0.0/24') factory.make_Subnet(cidr='192.168.1.0/24') maas_url = 'http://192.168.0.1/MAAS' rack = factory.make_RackController(url=maas_url) r1 = factory.make_RegionController() factory.make_Interface(node=r1, ip='192.168.0.1') factory.make_Interface(node=r1, ip='192.168.1.254') r2 = factory.make_RegionController() factory.make_Interface(node=r2, ip='192.168.0.2') factory.make_Interface(node=r2, ip='192.168.1.3') r3 = factory.make_RegionController() factory.make_Interface(node=r3, ip='192.168.0.4') factory.make_Interface(node=r3, ip='192.168.1.5') # Make the "current" region controller r1. self.patch(server_address, 'get_maas_id').return_value = r1.system_id region_ips = get_maas_facing_server_addresses(rack, include_alternates=True) self.assertThat( region_ips, Equals([ IPAddress("192.168.0.1"), IPAddress("192.168.0.2"), IPAddress("192.168.0.4"), ]))
def test__alternates_include_one_ip_address_per_region_and_maas_url(self): factory.make_Subnet(cidr="192.168.0.0/24") maas_url = "http://192.168.0.254/MAAS" rack = factory.make_RackController(url=maas_url) r1 = factory.make_RegionController() factory.make_Interface(node=r1, ip="192.168.0.1") factory.make_Interface(node=r1, ip="192.168.0.254") r2 = factory.make_RegionController() factory.make_Interface(node=r2, ip="192.168.0.2") factory.make_Interface(node=r2, ip="192.168.0.3") r3 = factory.make_RegionController() factory.make_Interface(node=r3, ip="192.168.0.4") factory.make_Interface(node=r3, ip="192.168.0.5") # Make the "current" region controller r1. self.patch(server_address, "get_maas_id").return_value = r1.system_id region_ips = get_maas_facing_server_addresses(rack, include_alternates=True) self.assertThat( region_ips, Equals([ IPAddress("192.168.0.254"), IPAddress("192.168.0.1"), IPAddress("192.168.0.2"), IPAddress("192.168.0.4"), ]), )
def test__ignores_IPv4_if_ipv4_not_set(self): v4_ip = factory.make_ipv4_address() v6_ip = factory.make_ipv6_address() self.patch_resolve_hostname([v4_ip, v6_ip]) self.patch_get_maas_facing_server_host() self.assertEqual([IPAddress(v6_ip)], get_maas_facing_server_addresses(ipv4=False, ipv6=True))
def test__resolves_hostname(self): hostname = make_hostname() self.patch_get_maas_facing_server_host(hostname) ip = factory.make_ipv4_address() fake_resolve = self.patch_resolve_hostname([ip]) result = get_maas_facing_server_addresses() self.assertEqual([IPAddress(ip)], result) self.assertEqual(hostname, fake_resolve.hostname)
def test__does_not_return_link_local_addresses(self): global_ipv6 = factory.make_ipv6_address() local_ipv6 = [ 'fe80::%d:9876:5432:10' % randint(0, 9999) for _ in range(5) ] self.patch_resolve_hostname([global_ipv6] + local_ipv6) self.patch_get_maas_facing_server_host() self.assertEqual([IPAddress(global_ipv6)], get_maas_facing_server_addresses())
def get_dns_server_addresses( rack_controller=None, ipv4=True, ipv6=True, include_alternates=False, default_region_ip=None, filter_allowed_dns=True, ): """Return the DNS server's IP addresses. That address is derived from the config maas_url or rack_controller.url. Consult the 'maas-region local_config_set --maas-url' command for details on how to set the MAAS URL. :param rack_controller: Optional rack controller to which the DNS server should be accessible. If given, the server addresses will be taken from the rack controller's `maas_url` setting. Otherwise, it will be taken from the globally configured default MAAS URL. :param ipv4: Include IPv4 server addresses? :param ipv6: Include IPv6 server addresses? :param include_alternates: Include IP addresses from other regions? :param default_region_ip: The default source IP address to be used, if a specific URL is not defined. :param filter_allowed_dns: If true, only include addresses for subnets with allow_dns=True. :return: List of IPAddress to use. Loopback addresses are removed from the list, unless there are no non-loopback addresses. """ try: ips = get_maas_facing_server_addresses( rack_controller=rack_controller, ipv4=ipv4, ipv6=ipv6, include_alternates=include_alternates, default_region_ip=default_region_ip, ) except socket.error as e: raise UnresolvableHost( "Unable to find MAAS server IP address: %s. MAAS's DNS server " "requires this IP address for the NS records in its zone files. " "Make sure that the configuration setting for the MAAS URL has " "the correct hostname. Consult the 'maas-region " "local_config_set --maas-url' command." % e.strerror) if filter_allowed_dns: ips = [ ip for ip in ips if getattr( Subnet.objects.get_best_subnet_for_ip(ip), "allow_dns", True) ] non_loop = [ip for ip in ips if not ip.is_loopback()] if non_loop: return non_loop else: for ip in ips: warn_loopback(ip) return ips
def test__returns_link_local_addresses_if_asked(self): global_ipv6 = factory.make_ipv6_address() local_ipv6 = [ 'fe80::%d:9876:5432:10' % randint(0, 9999) for _ in range(5) ] self.patch_resolve_hostname([global_ipv6] + local_ipv6) self.patch_get_maas_facing_server_host() self.assertItemsEqual( [IPAddress(ip) for ip in local_ipv6] + [IPAddress(global_ipv6)], get_maas_facing_server_addresses(link_local=True))
def test__returns_v4_and_v6_addresses(self): # If a server has mixed v4 and v6 addresses, # get_maas_facing_server_addresses() will return both. v4_ip = factory.make_ipv4_address() v6_ip = factory.make_ipv6_address() self.patch_resolve_hostname([v4_ip, v6_ip]) self.patch_get_maas_facing_server_host() self.assertItemsEqual( [IPAddress(v4_ip), IPAddress(v6_ip)], get_maas_facing_server_addresses(ipv4=True, ipv6=True))
def get_dns_server_addresses(rack_controller=None, ipv4=True, ipv6=True, include_alternates=False): """Return the DNS server's IP addresses. That address is derived from the config maas_url or rack_controller.url. Consult the 'maas-region local_config_set --maas-url' command for details on how to set the MAAS URL. :param rack_controller: Optional rack controller to which the DNS server should be accessible. If given, the server addresses will be taken from the rack controller's `maas_url` setting. Otherwise, it will be taken from the globally configured default MAAS URL. :param ipv4: Include IPv4 server addresses? :param ipv6: Include IPv6 server addresses? :param include_alternates: Include IP addresses from other regions? :return: List of IPAddress to use. Loopback addresses are removed from the list, unless there are no non-loopback addresses. """ try: iplist = get_maas_facing_server_addresses( rack_controller, ipv4=ipv4, ipv6=ipv6, include_alternates=include_alternates) except socket.error as e: raise UnresolvableHost( "Unable to find MAAS server IP address: %s. MAAS's DNS server " "requires this IP address for the NS records in its zone files. " "Make sure that the configuration setting for the MAAS URL has " "the correct hostname. Consult the 'maas-region " "local_config_set --maas-url' command." % e.strerror) non_loop = [ip for ip in iplist if not ip.is_loopback()] if len(non_loop) > 0: return non_loop else: for ip in iplist: warn_loopback(ip) return iplist
def test__alternates_do_not_contain_duplicate_for_maas_url_ip(self): # See bug #1753493. (This tests to ensure we don't provide the same # IP address from maas_url twice.) Also ensures that the IP address # from maas_url comes first. factory.make_Subnet(cidr="192.168.0.0/24") maas_url = "http://192.168.0.2/MAAS" rack = factory.make_RackController(url=maas_url) r1 = factory.make_RegionController() factory.make_Interface(node=r1, ip="192.168.0.1") r2 = factory.make_RegionController() factory.make_Interface(node=r2, ip="192.168.0.2") # Make the "current" region controller r1. self.patch(server_address, "get_maas_id").return_value = r1.system_id region_ips = get_maas_facing_server_addresses(rack, include_alternates=True) self.assertThat( region_ips, Equals([IPAddress("192.168.0.2"), IPAddress("192.168.0.1")]), )