def test_update_leases_replaces_reassigned_ip(self): nodegroup = factory.make_node_group() ip = factory.getRandomIPAddress() factory.make_dhcp_lease(nodegroup=nodegroup, ip=ip) new_mac = factory.getRandomMACAddress() DHCPLease.objects.update_leases(nodegroup, {ip: new_mac}) self.assertEqual({ip: new_mac}, map_leases(nodegroup))
def test_ip_addresses_uses_result_cache(self): # ip_addresses has a specialized code path for the case where the # node group's set of DHCP leases is already cached in Django's ORM. # This test exercises that code path. node = factory.make_node() macs = [factory.make_mac_address(node=node) for i in range(2)] leases = [ factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) for mac in macs] # Other nodes in the nodegroup have leases, but those are not # relevant here. factory.make_dhcp_lease(nodegroup=node.nodegroup) # Don't address the node directly; address it through a query with # prefetched DHCP leases, to ensure that the query cache for those # leases on the nodegroup will be populated. query = Node.objects.filter(id=node.id) query = query.prefetch_related('nodegroup__dhcplease_set') # The cache is populated. This is the condition that triggers the # separate code path in Node.ip_addresses(). self.assertIsNotNone( query[0].nodegroup.dhcplease_set.all()._result_cache) # ip_addresses() still returns the node's leased addresses. num_queries, addresses = self.getNumQueries(query[0].ip_addresses) # It only takes one query: to get the node's MAC addresses. self.assertEqual(1, num_queries) # The result is not a query set, so this isn't hiding a further query. no_queries, _ = self.getNumQueries(list, addresses) self.assertEqual(0, no_queries) # We still get exactly the right IP addresses. self.assertItemsEqual([lease.ip for lease in leases], addresses)
def test_update_leases_combines_additions_deletions_and_replacements(self): nodegroup = factory.make_node_group() mac1 = factory.getRandomMACAddress() mac2 = factory.getRandomMACAddress() obsolete_lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac1) # The obsolete lease won't be in the update, so it'll disappear. ignore_unused(obsolete_lease) unchanged_lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac1) reassigned_lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac1) new_ip = factory.getRandomIPAddress() DHCPLease.objects.update_leases(nodegroup, { reassigned_lease.ip: mac2, unchanged_lease.ip: mac1, new_ip: mac1, }) self.assertEqual( { reassigned_lease.ip: mac2, unchanged_lease.ip: mac1, new_ip: mac1, }, map_leases(nodegroup))
def test_update_leases_adds_new_ip_to_mac(self): nodegroup = factory.make_node_group() mac = factory.getRandomMACAddress() ip1 = factory.getRandomIPAddress() ip2 = factory.getRandomIPAddress() factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=ip1) DHCPLease.objects.update_leases(nodegroup, {ip1: mac, ip2: mac}) self.assertEqual({ip1: mac, ip2: mac}, map_leases(nodegroup))
def test_update_leases_deletes_only_obsolete_ips(self): nodegroup = factory.make_node_group() mac = factory.getRandomMACAddress() obsolete_ip = factory.getRandomIPAddress() current_ip = factory.getRandomIPAddress() factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=obsolete_ip) factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=current_ip) DHCPLease.objects.update_leases(nodegroup, {current_ip: mac}) self.assertEqual({current_ip: mac}, map_leases(nodegroup))
def test_delete_node_removes_multiple_host_maps(self): lease1 = factory.make_dhcp_lease() lease2 = factory.make_dhcp_lease(nodegroup=lease1.nodegroup) node = factory.make_node(nodegroup=lease1.nodegroup) node.add_mac_address(lease1.mac) node.add_mac_address(lease2.mac) mocked_task = self.patch(node_module, "remove_dhcp_host_map") mocked_apply_async = self.patch(mocked_task, "apply_async") node.delete() self.assertEqual(2, mocked_apply_async.call_count)
def test_delete_node_removes_multiple_host_maps(self): lease1 = factory.make_dhcp_lease() lease2 = factory.make_dhcp_lease(nodegroup=lease1.nodegroup) node = factory.make_node(nodegroup=lease1.nodegroup) node.add_mac_address(lease1.mac) node.add_mac_address(lease2.mac) mocked_task = self.patch(node_module, "remove_dhcp_host_map") mocked_apply_async = self.patch(mocked_task, "apply_async") node.delete() self.assertEqual(2, mocked_apply_async.call_count)
def test_get_hostname_ip_mapping_considers_only_first_mac(self): nodegroup = factory.make_node_group() node = factory.make_node( nodegroup=nodegroup) factory.make_mac_address(node=node) second_mac = factory.make_mac_address(node=node) # Create a lease for the second MAC Address. factory.make_dhcp_lease( nodegroup=nodegroup, mac=second_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual({}, mapping)
def test_get_hostname_ip_mapping_considers_given_nodegroup(self): nodegroup = factory.make_node_group() node = factory.make_node( nodegroup=nodegroup) mac = factory.make_mac_address(node=node) factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) another_nodegroup = factory.make_node_group() mapping = DHCPLease.objects.get_hostname_ip_mapping( another_nodegroup) self.assertEqual({}, mapping)
def test_get_hostname_ip_mapping_picks_oldest_mac_with_lease(self): node = factory.make_node(hostname=factory.make_name('host')) older_mac = factory.make_mac_address(node=node) newer_mac = factory.make_mac_address(node=node) factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=newer_mac.mac_address) lease_for_older_mac = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=older_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup) self.assertEqual({node.hostname: lease_for_older_mac.ip}, mapping)
def test_update_leases_processes_empty_leases_dict(self): nodegroup = factory.make_node_group() factory.make_dhcp_lease(nodegroup=nodegroup) client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'update_leases', 'leases': json.dumps({}), }) self.assertEqual((httplib.OK, "Leases updated."), (response.status_code, response.content)) self.assertItemsEqual([], DHCPLease.objects.filter(nodegroup=nodegroup))
def test_ip_addresses_filters_by_mac_addresses(self): node = factory.make_node() # Another node in the same nodegroup has some IP leases. The one thing # that tells ip_addresses what nodes these leases belong to are their # MAC addresses. other_node = factory.make_node(nodegroup=node.nodegroup) macs = [factory.make_mac_address(node=node) for i in range(2)] for mac in macs: factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) # The other node's leases do not get mistaken for ones that belong to # our original node. self.assertItemsEqual([], other_node.ip_addresses())
def test_update_leases_returns_new_leases(self): nodegroup = factory.make_node_group() obsolete_lease = factory.make_dhcp_lease(nodegroup=nodegroup) ignore_unused(obsolete_lease) remaining_lease = factory.make_dhcp_lease(nodegroup=nodegroup) new_lease = factory.make_random_leases() surviving_leases = { remaining_lease.ip: remaining_lease.mac, new_lease.keys()[0]: new_lease.values()[0], } self.assertItemsEqual( new_lease.keys(), DHCPLease.objects.update_leases(nodegroup, surviving_leases))
def test_update_leases_processes_empty_leases_dict(self): nodegroup = factory.make_node_group() factory.make_dhcp_lease(nodegroup=nodegroup) client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'update_leases', 'leases': json.dumps({}), }) self.assertEqual( (httplib.OK, "Leases updated."), (response.status_code, response.content)) self.assertItemsEqual( [], DHCPLease.objects.filter(nodegroup=nodegroup))
def test_update_leases_leaves_other_nodegroups_alone(self): innocent_nodegroup = factory.make_node_group() innocent_lease = factory.make_dhcp_lease(nodegroup=innocent_nodegroup) DHCPLease.objects.update_leases( factory.make_node_group(), factory.make_random_leases()) self.assertItemsEqual( [innocent_lease], get_leases(innocent_nodegroup))
def test_get_hostname_ip_mapping_picks_mac_with_lease(self): node = factory.make_node(hostname=factory.make_name('host')) factory.make_mac_address(node=node) second_mac = factory.make_mac_address(node=node) # Create a lease for the second MAC Address. lease = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=second_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup) self.assertEqual({node.hostname: lease.ip}, mapping)
def test_ip_addresses_queries_leases(self): node = factory.make_node() macs = [factory.make_mac_address(node=node) for i in range(2)] leases = [ factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) for mac in macs] self.assertItemsEqual( [lease.ip for lease in leases], node.ip_addresses())
def test_GET_returns_associated_ip_addresses(self): node = factory.make_node() mac = factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) response = self.client.get(self.get_node_uri(node)) self.assertEqual( httplib.OK, response.status_code, response.content) parsed_result = json.loads(response.content) self.assertEqual([lease.ip], parsed_result['ip_addresses'])
def test_get_hostname_ip_mapping_strips_out_domain(self): nodegroup = factory.make_node_group() hostname = factory.make_name('hostname') domain = factory.make_name('domain') node = factory.make_node( nodegroup=nodegroup, hostname='%s.%s' % (hostname, domain)) mac = factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual({hostname: lease.ip}, mapping)
def test_get_hostname_ip_mapping_returns_mapping(self): nodegroup = factory.make_node_group() expected_mapping = {} for i in range(3): node = factory.make_node( nodegroup=nodegroup) mac = factory.make_mac_address(node=node) factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) expected_mapping[node.hostname] = lease.ip mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual(expected_mapping, mapping)
def create_nodegroup_with_lease(self, lease_number=1, nodegroup=None): if nodegroup is None: nodegroup = self.create_managed_nodegroup() interface = nodegroup.get_managed_interface() node = factory.make_node(nodegroup=nodegroup) mac = factory.make_mac_address(node=node) ips = IPRange(interface.ip_range_low, interface.ip_range_high) lease_ip = unicode(islice(ips, lease_number, lease_number + 1).next()) lease = factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac.mac_address, ip=lease_ip) # Simulate that this lease was created by # DHCPLease.objects.update_leases: update its DNS config. dns.change_dns_zones([nodegroup]) return nodegroup, node, lease
def test_delete_node_also_deletes_dhcp_host_map(self): lease = factory.make_dhcp_lease() node = factory.make_node(nodegroup=lease.nodegroup) node.add_mac_address(lease.mac) mocked_task = self.patch(node_module, "remove_dhcp_host_map") mocked_apply_async = self.patch(mocked_task, "apply_async") node.delete() args, kwargs = mocked_apply_async.call_args expected = ( Equals(kwargs['queue']), Equals({ 'ip_address': lease.ip, 'server_address': "127.0.0.1", 'omapi_key': lease.nodegroup.dhcp_key, })) observed = node.work_queue, kwargs['kwargs'] self.assertThat(observed, MatchesListwise(expected))
def test_delete_node_also_deletes_dhcp_host_map(self): lease = factory.make_dhcp_lease() node = factory.make_node(nodegroup=lease.nodegroup) node.add_mac_address(lease.mac) mocked_task = self.patch(node_module, "remove_dhcp_host_map") mocked_apply_async = self.patch(mocked_task, "apply_async") node.delete() args, kwargs = mocked_apply_async.call_args expected = ( Equals(kwargs['queue']), Equals({ 'ip_address': lease.ip, 'server_address': "127.0.0.1", 'omapi_key': lease.nodegroup.dhcp_key, })) observed = node.work_queue, kwargs['kwargs'] self.assertThat(observed, MatchesListwise(expected))
def test_update_leases_deletes_obsolete_lease(self): nodegroup = factory.make_node_group() factory.make_dhcp_lease(nodegroup=nodegroup) DHCPLease.objects.update_leases(nodegroup, {}) self.assertItemsEqual([], get_leases(nodegroup))
def test_dhcplease_gets_removed_when_corresponding_node_is_deleted(self): lease = factory.make_dhcp_lease() mac = factory.make_mac_address(address=lease.mac) mac.node.delete() self.assertItemsEqual( [], DHCPLease.objects.filter(mac=mac.mac_address))
def test_update_leases_keeps_unchanged_mappings(self): original_lease = factory.make_dhcp_lease() nodegroup = original_lease.nodegroup DHCPLease.objects.update_leases( nodegroup, {original_lease.ip: original_lease.mac}) self.assertItemsEqual([original_lease], get_leases(nodegroup))