def test_skips_dns_record_for_coerced_hostname_from_existing_node(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) hostname = "gaming device" factory.make_Node(hostname="gaming-device") kwargs = self.make_kwargs(action="commit", ip=ip, hostname=hostname) update_lease(**kwargs) unknown_interface = UnknownInterface.objects.filter( mac_address=kwargs["mac"]).first() self.assertIsNotNone(unknown_interface) self.assertEquals(subnet.vlan, unknown_interface.vlan) sip = unknown_interface.ip_addresses.first() self.assertIsNotNone(sip) self.assertThat(sip.dnsresource_set.all(), Not(Contains(sip)))
def test_creates_dns_record_for_hostname(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) hostname = factory.make_name().lower() kwargs = self.make_kwargs(action="commit", ip=ip, hostname=hostname) update_lease(**kwargs) unknown_interface = UnknownInterface.objects.filter( mac_address=kwargs["mac"]).first() self.assertIsNotNone(unknown_interface) self.assertEqual(subnet.vlan, unknown_interface.vlan) sip = unknown_interface.ip_addresses.first() self.assertIsNotNone(sip) dnsrr = get_one(DNSResource.objects.filter(name=hostname)) self.assertThat(sip.dnsresource_set.all(), Contains(dnsrr))
def test_bind_configuration_includes_dynamic_ips_of_deployed_nodes(self): self.patch(settings, "DNS_CONNECT", True) subnet = factory.make_ipv4_Subnet_with_IPRanges() node = factory.make_Node(interface=True, status=NODE_STATUS.DEPLOYED) nic = node.get_boot_interface() # Get an IP in the dynamic range. dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) ip_obj = factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip, subnet=subnet, interface=nic, ) dns_update_all_zones() self.assertDNSMatches(node.hostname, node.domain.name, ip_obj.ip)
def test_factory_make_DHCPSnippet_sets_iprange(self): name = factory.make_name("dhcp_snippet") value = VersionedTextFile.objects.create(data=factory.make_string()) description = factory.make_string() enabled = factory.pick_bool() subnet = factory.make_ipv4_Subnet_with_IPRanges() iprange = subnet.get_dynamic_ranges().first() iprange.save() dhcp_snippet = factory.make_DHCPSnippet( name, value, description, enabled, subnet=subnet, iprange=iprange ) self.assertEqual(name, dhcp_snippet.name) self.assertEqual(value.data, dhcp_snippet.value.data) self.assertEqual(description, dhcp_snippet.description) self.assertEqual(enabled, dhcp_snippet.enabled) self.assertEqual(subnet, dhcp_snippet.subnet) self.assertEqual(iprange, dhcp_snippet.iprange)
def test__accounts_for_reserved_ip_address(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_dynamic_range=False, dns_servers=[], with_router=False) network = subnet.get_ipnetwork() # Pick an address in the middle of the range. (that way we'll always # expect there to be two unreserved ranges, arranged around the # allocated IP address.) middle_ip = (network.first + network.last) // 2 ip = inet_ntop(middle_ip) factory.make_StaticIPAddress(ip=ip, alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet) expected_addresses = (network.last - network.first + 1) expected_first_address = inet_ntop(network.first + 1) first_range_end = inet_ntop(middle_ip - 1) first_range_size = middle_ip - network.first - 1 second_range_start = inet_ntop(middle_ip + 1) if network.version == 6: # Don't count the IPv6 network address in num_addresses expected_addresses -= 1 expected_last_address = inet_ntop(network.last) second_range_size = network.last - middle_ip else: # Don't count the IPv4 broadcast/network addresses in num_addresses expected_addresses -= 2 expected_last_address = inet_ntop(network.last - 1) second_range_size = network.last - middle_ip - 1 response = self.client.get(get_subnet_uri(subnet), {'op': 'unreserved_ip_ranges'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( result, Equals([{ "start": expected_first_address, "end": first_range_end, "num_addresses": first_range_size, }, { "start": second_range_start, "end": expected_last_address, "num_addresses": second_range_size, }]), "Reserved ranges: %s" % (subnet.get_ipranges_in_use()))
def test_create_dhcp_snippet_with_iprange_requires_subnet(self): subnet = factory.make_ipv4_Subnet_with_IPRanges() iprange = subnet.get_dynamic_ranges().first() iprange.save() name = factory.make_name("name") value = factory.make_string() description = factory.make_string() enabled = factory.pick_bool() form = DHCPSnippetForm( data={ "name": name, "value": value, "dscription": description, "enabled": enabled, "iprange": iprange.id, } ) self.assertFalse(form.is_valid(), form.errors)
def test__STATIC_not_allowed_if_ip_address_in_dynamic_range(self): interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) subnet = factory.make_ipv4_Subnet_with_IPRanges(vlan=interface.vlan) dynamic_range = subnet.get_dynamic_ranges()[0] ip_in_dynamic = factory.pick_ip_in_IPRange(dynamic_range) form = InterfaceLinkForm(instance=interface, data={ "mode": INTERFACE_LINK_TYPE.STATIC, "subnet": subnet.id, "ip_address": "%s" % ip_in_dynamic, }) self.assertFalse(form.is_valid(), form.errors) self.assertEqual( { "ip_address": [ "IP address is inside a dynamic range %s to %s." % (dynamic_range.start_ip, dynamic_range.end_ip) ] }, form.errors)
def test_expiry_removes_lease_keeps_discovered_subnet(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs = self.make_kwargs(action="expiry", mac=boot_interface.mac_address, ip=ip) update_lease(**kwargs) sip = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=None, subnet=subnet, interface=boot_interface).first() self.assertIsNotNone( sip, "DISCOVERED IP address shold have been created without an " "IP address.") self.assertItemsEqual([boot_interface.id], sip.interface_set.values_list("id", flat=True))
def test_expiry_does_not_keep_adding_null_ip_records_other_interface(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) node1 = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface1 = node1.get_boot_interface() node2 = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface2 = node2.get_boot_interface() # We now have two nodes, both having null IP records linking # them to the same subnet. self.assertIsNone(boot_interface1.ip_addresses.first().ip) self.assertIsNone(boot_interface2.ip_addresses.first().ip) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs1 = self.make_kwargs(action="expiry", mac=boot_interface1.mac_address, ip=ip) kwargs2 = self.make_kwargs(action="expiry", mac=boot_interface2.mac_address, ip=ip) self.assertEqual(1, boot_interface1.ip_addresses.count()) self.assertEqual(1, boot_interface2.ip_addresses.count()) # When expiring the leases for the two nodes, they keep the # existing links they have. previous_ip_id1 = boot_interface1.ip_addresses.first().id previous_ip_id2 = boot_interface2.ip_addresses.first().id update_lease(**kwargs1) update_lease(**kwargs2) [ip_address1] = boot_interface1.ip_addresses.all() self.assertEqual(previous_ip_id1, ip_address1.id) self.assertEqual(1, ip_address1.interface_set.count()) [ip_address2] = boot_interface2.ip_addresses.all() self.assertEqual(previous_ip_id2, ip_address2.id) self.assertEqual(1, ip_address2.interface_set.count()) self.assertEqual(1, boot_interface1.ip_addresses.count()) self.assertEqual(1, boot_interface2.ip_addresses.count())
def test_creates_lease_for_unknown_interface(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs = self.make_kwargs(action="commit", ip=ip) update_lease(**kwargs) unknown_interface = UnknownInterface.objects.filter( mac_address=kwargs["mac"]).first() self.assertIsNotNone(unknown_interface) self.assertEquals(subnet.vlan, unknown_interface.vlan) sip = unknown_interface.ip_addresses.first() self.assertIsNotNone(sip) self.assertThat( sip, MatchesStructure.byEquality( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip, subnet=subnet, lease_time=kwargs["lease_time"], created=datetime.fromtimestamp(kwargs["timestamp"]), updated=datetime.fromtimestamp(kwargs["timestamp"]), ))
def test_expiry_does_not_keep_adding_null_ip_records_repeated_calls(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) # Create a bunch of null IPs to show the effects of bug 1817056. null_ips = [ StaticIPAddress( created=timezone.now(), updated=timezone.now(), ip=None, alloc_type=IPADDRESS_TYPE.DISCOVERED, subnet=subnet, ) for _ in range(10) ] StaticIPAddress.objects.bulk_create(null_ips) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() boot_interface.ip_addresses.add(*null_ips) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs = self.make_kwargs(action="expiry", mac=boot_interface.mac_address, ip=ip) null_ip_query = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=None, subnet=subnet) update_lease(**kwargs) # XXX: We shouldn't need to record the previous count and # instead expect the count to be 1. This will be addressed # in bug 1817305. previous_null_ip_count = null_ip_query.count() previous_interface_ip_count = boot_interface.ip_addresses.count() update_lease(**kwargs) self.assertEqual(previous_null_ip_count, null_ip_query.count()) self.assertEqual(previous_interface_ip_count, boot_interface.ip_addresses.count())
def test_creates_lease_for_bond_interface(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) bond_interface = factory.make_Interface( INTERFACE_TYPE.BOND, mac_address=boot_interface.mac_address, parents=[boot_interface], ) kwargs = self.make_kwargs(action="commit", mac=bond_interface.mac_address, ip=ip) update_lease(**kwargs) sip = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip).first() self.assertThat( sip, MatchesStructure.byEquality( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip, subnet=subnet, lease_time=kwargs["lease_time"], created=datetime.fromtimestamp(kwargs["timestamp"]), updated=datetime.fromtimestamp(kwargs["timestamp"]), ), ) self.assertItemsEqual( [boot_interface.id, bond_interface.id], sip.interface_set.values_list("id", flat=True), )
def test_POST_reserve_ip_address_rejects_ip_in_dynamic_range(self): subnet = factory.make_ipv4_Subnet_with_IPRanges() ip = str(IPAddress(subnet.get_dynamic_maasipset().first)) response = self.post_reservation_request(subnet, ip) self.assertEqual(http.client.FORBIDDEN, response.status_code, response.content)
def make_managed_subnet(self): return factory.make_ipv4_Subnet_with_IPRanges(with_static_range=False, dhcp_on=True)