~ubuntu-branches/ubuntu/precise/maas/precise-updates

« back to all changes in this revision

Viewing changes to src/maasserver/tests/test_dhcplease.py

Tags: 1.2+bzr1373+dfsg-0ubuntu1~12.04.4
* SECURITY UPDATE: failure to authenticate downloaded content (LP: #1039513)
  - debian/patches/CVE-2013-1058.patch: Authenticate downloaded files with
    GnuPG and MD5SUM files. Thanks to Julian Edwards.
  - CVE-2013-1058
* SECURITY UPDATE: configuration options may be loaded from current working
  directory (LP: #1158425)
  - debian/patches/CVE-2013-1057-1-2.patch: Do not load configuration
    options from the current working directory. Thanks to Julian Edwards.
  - CVE-2013-1057

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2013 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Tests for the :class:`DHCPLease` model."""
 
5
 
 
6
from __future__ import (
 
7
    absolute_import,
 
8
    print_function,
 
9
    unicode_literals,
 
10
    )
 
11
 
 
12
__metaclass__ = type
 
13
__all__ = []
 
14
 
 
15
from maasserver import dns
 
16
from maasserver.models import DHCPLease
 
17
from maasserver.testing.factory import factory
 
18
from maasserver.testing.testcase import TestCase
 
19
from maasserver.utils import ignore_unused
 
20
 
 
21
 
 
22
def get_leases(nodegroup):
 
23
    """Return DHCPLease records for `nodegroup`."""
 
24
    return DHCPLease.objects.filter(nodegroup=nodegroup)
 
25
 
 
26
 
 
27
def map_leases(nodegroup):
 
28
    """Return IP/MAC mappings dict for leases in `nodegroup`."""
 
29
    return {lease.ip: lease.mac for lease in get_leases(nodegroup)}
 
30
 
 
31
 
 
32
class TestDHCPLease(TestCase):
 
33
    """Tests for :class:`DHCPLease`."""
 
34
 
 
35
    def test_init(self):
 
36
        nodegroup = factory.make_node_group()
 
37
        ip = factory.getRandomIPAddress()
 
38
        mac = factory.getRandomMACAddress()
 
39
 
 
40
        lease = DHCPLease(nodegroup=nodegroup, ip=ip, mac=mac)
 
41
        lease.save()
 
42
 
 
43
        self.assertItemsEqual([lease], get_leases(nodegroup))
 
44
        self.assertEqual(nodegroup, lease.nodegroup)
 
45
        self.assertEqual(ip, lease.ip)
 
46
        self.assertEqual(mac, lease.mac)
 
47
 
 
48
 
 
49
class TestDHCPLeaseManager(TestCase):
 
50
    """Tests for :class:`DHCPLeaseManager`."""
 
51
 
 
52
    def test_update_leases_accepts_empty_leases(self):
 
53
        nodegroup = factory.make_node_group()
 
54
        DHCPLease.objects.update_leases(nodegroup, {})
 
55
        self.assertItemsEqual([], get_leases(nodegroup))
 
56
 
 
57
    def test_update_leases_creates_new_lease(self):
 
58
        nodegroup = factory.make_node_group()
 
59
        lease = factory.make_random_leases()
 
60
        DHCPLease.objects.update_leases(nodegroup, lease)
 
61
        self.assertEqual(lease, map_leases(nodegroup))
 
62
 
 
63
    def test_update_leases_returns_new_leases(self):
 
64
        nodegroup = factory.make_node_group()
 
65
        obsolete_lease = factory.make_dhcp_lease(nodegroup=nodegroup)
 
66
        ignore_unused(obsolete_lease)
 
67
        remaining_lease = factory.make_dhcp_lease(nodegroup=nodegroup)
 
68
        new_lease = factory.make_random_leases()
 
69
 
 
70
        surviving_leases = {
 
71
            remaining_lease.ip: remaining_lease.mac,
 
72
            new_lease.keys()[0]: new_lease.values()[0],
 
73
        }
 
74
 
 
75
        self.assertItemsEqual(
 
76
            new_lease.keys(),
 
77
            DHCPLease.objects.update_leases(nodegroup, surviving_leases))
 
78
 
 
79
    def test_update_leases_deletes_obsolete_lease(self):
 
80
        nodegroup = factory.make_node_group()
 
81
        factory.make_dhcp_lease(nodegroup=nodegroup)
 
82
        DHCPLease.objects.update_leases(nodegroup, {})
 
83
        self.assertItemsEqual([], get_leases(nodegroup))
 
84
 
 
85
    def test_update_leases_replaces_reassigned_ip(self):
 
86
        nodegroup = factory.make_node_group()
 
87
        ip = factory.getRandomIPAddress()
 
88
        factory.make_dhcp_lease(nodegroup=nodegroup, ip=ip)
 
89
        new_mac = factory.getRandomMACAddress()
 
90
        DHCPLease.objects.update_leases(nodegroup, {ip: new_mac})
 
91
        self.assertEqual({ip: new_mac}, map_leases(nodegroup))
 
92
 
 
93
    def test_update_leases_keeps_unchanged_mappings(self):
 
94
        original_lease = factory.make_dhcp_lease()
 
95
        nodegroup = original_lease.nodegroup
 
96
        DHCPLease.objects.update_leases(
 
97
            nodegroup, {original_lease.ip: original_lease.mac})
 
98
        self.assertItemsEqual([original_lease], get_leases(nodegroup))
 
99
 
 
100
    def test_update_leases_adds_new_ip_to_mac(self):
 
101
        nodegroup = factory.make_node_group()
 
102
        mac = factory.getRandomMACAddress()
 
103
        ip1 = factory.getRandomIPAddress()
 
104
        ip2 = factory.getRandomIPAddress()
 
105
        factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=ip1)
 
106
        DHCPLease.objects.update_leases(nodegroup, {ip1: mac, ip2: mac})
 
107
        self.assertEqual({ip1: mac, ip2: mac}, map_leases(nodegroup))
 
108
 
 
109
    def test_update_leases_deletes_only_obsolete_ips(self):
 
110
        nodegroup = factory.make_node_group()
 
111
        mac = factory.getRandomMACAddress()
 
112
        obsolete_ip = factory.getRandomIPAddress()
 
113
        current_ip = factory.getRandomIPAddress()
 
114
        factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=obsolete_ip)
 
115
        factory.make_dhcp_lease(nodegroup=nodegroup, mac=mac, ip=current_ip)
 
116
        DHCPLease.objects.update_leases(nodegroup, {current_ip: mac})
 
117
        self.assertEqual({current_ip: mac}, map_leases(nodegroup))
 
118
 
 
119
    def test_update_leases_leaves_other_nodegroups_alone(self):
 
120
        innocent_nodegroup = factory.make_node_group()
 
121
        innocent_lease = factory.make_dhcp_lease(nodegroup=innocent_nodegroup)
 
122
        DHCPLease.objects.update_leases(
 
123
            factory.make_node_group(), factory.make_random_leases())
 
124
        self.assertItemsEqual(
 
125
            [innocent_lease], get_leases(innocent_nodegroup))
 
126
 
 
127
    def test_update_leases_combines_additions_deletions_and_replacements(self):
 
128
        nodegroup = factory.make_node_group()
 
129
        mac1 = factory.getRandomMACAddress()
 
130
        mac2 = factory.getRandomMACAddress()
 
131
        obsolete_lease = factory.make_dhcp_lease(
 
132
            nodegroup=nodegroup, mac=mac1)
 
133
        # The obsolete lease won't be in the update, so it'll disappear.
 
134
        ignore_unused(obsolete_lease)
 
135
        unchanged_lease = factory.make_dhcp_lease(
 
136
            nodegroup=nodegroup, mac=mac1)
 
137
        reassigned_lease = factory.make_dhcp_lease(
 
138
            nodegroup=nodegroup, mac=mac1)
 
139
        new_ip = factory.getRandomIPAddress()
 
140
        DHCPLease.objects.update_leases(nodegroup, {
 
141
            reassigned_lease.ip: mac2,
 
142
            unchanged_lease.ip: mac1,
 
143
            new_ip: mac1,
 
144
        })
 
145
        self.assertEqual(
 
146
            {
 
147
                reassigned_lease.ip: mac2,
 
148
                unchanged_lease.ip: mac1,
 
149
                new_ip: mac1,
 
150
            },
 
151
            map_leases(nodegroup))
 
152
 
 
153
    def test_update_leases_updates_dns_zone(self):
 
154
        self.patch(dns, 'change_dns_zones')
 
155
        nodegroup = factory.make_node_group()
 
156
        DHCPLease.objects.update_leases(
 
157
            nodegroup, factory.make_random_leases())
 
158
        dns.change_dns_zones.assert_called_once_with([nodegroup])
 
159
 
 
160
    def test_update_leases_does_not_update_dns_zone_if_nothing_added(self):
 
161
        self.patch(dns, 'change_dns_zones')
 
162
        nodegroup = factory.make_node_group()
 
163
        DHCPLease.objects.update_leases(nodegroup, {})
 
164
        self.assertFalse(dns.change_dns_zones.called)
 
165
 
 
166
    def test_get_hostname_ip_mapping_returns_mapping(self):
 
167
        nodegroup = factory.make_node_group()
 
168
        expected_mapping = {}
 
169
        for i in range(3):
 
170
            node = factory.make_node(
 
171
                nodegroup=nodegroup)
 
172
            mac = factory.make_mac_address(node=node)
 
173
            factory.make_mac_address(node=node)
 
174
            lease = factory.make_dhcp_lease(
 
175
                nodegroup=nodegroup, mac=mac.mac_address)
 
176
            expected_mapping[node.hostname] = lease.ip
 
177
        mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup)
 
178
        self.assertEqual(expected_mapping, mapping)
 
179
 
 
180
    def test_get_hostname_ip_mapping_strips_out_domain(self):
 
181
        nodegroup = factory.make_node_group()
 
182
        hostname = factory.make_name('hostname')
 
183
        domain = factory.make_name('domain')
 
184
        node = factory.make_node(
 
185
            nodegroup=nodegroup,
 
186
            hostname='%s.%s' % (hostname, domain))
 
187
        mac = factory.make_mac_address(node=node)
 
188
        lease = factory.make_dhcp_lease(
 
189
            nodegroup=nodegroup, mac=mac.mac_address)
 
190
        mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup)
 
191
        self.assertEqual({hostname: lease.ip}, mapping)
 
192
 
 
193
    def test_get_hostname_ip_mapping_picks_mac_with_lease(self):
 
194
        node = factory.make_node(hostname=factory.make_name('host'))
 
195
        factory.make_mac_address(node=node)
 
196
        second_mac = factory.make_mac_address(node=node)
 
197
        # Create a lease for the second MAC Address.
 
198
        lease = factory.make_dhcp_lease(
 
199
            nodegroup=node.nodegroup, mac=second_mac.mac_address)
 
200
        mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup)
 
201
        self.assertEqual({node.hostname: lease.ip}, mapping)
 
202
 
 
203
    def test_get_hostname_ip_mapping_picks_oldest_mac_with_lease(self):
 
204
        node = factory.make_node(hostname=factory.make_name('host'))
 
205
        older_mac = factory.make_mac_address(node=node)
 
206
        newer_mac = factory.make_mac_address(node=node)
 
207
 
 
208
        factory.make_dhcp_lease(
 
209
            nodegroup=node.nodegroup, mac=newer_mac.mac_address)
 
210
        lease_for_older_mac = factory.make_dhcp_lease(
 
211
            nodegroup=node.nodegroup, mac=older_mac.mac_address)
 
212
 
 
213
        mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup)
 
214
        self.assertEqual({node.hostname: lease_for_older_mac.ip}, mapping)
 
215
 
 
216
    def test_get_hostname_ip_mapping_considers_given_nodegroup(self):
 
217
        nodegroup = factory.make_node_group()
 
218
        node = factory.make_node(
 
219
            nodegroup=nodegroup)
 
220
        mac = factory.make_mac_address(node=node)
 
221
        factory.make_dhcp_lease(
 
222
            nodegroup=nodegroup, mac=mac.mac_address)
 
223
        another_nodegroup = factory.make_node_group()
 
224
        mapping = DHCPLease.objects.get_hostname_ip_mapping(
 
225
            another_nodegroup)
 
226
        self.assertEqual({}, mapping)