~ubuntu-branches/ubuntu/trusty/maas/trusty

« back to all changes in this revision

Viewing changes to src/maasserver/models/tests/test_nodegroupinterface.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Andres Rodriguez, Jason Hobbs, Jeroen Vermeulen
  • Date: 2014-04-03 13:45:02 UTC
  • mfrom: (1.2.27)
  • Revision ID: package-import@ubuntu.com-20140403134502-k8ocidn51k203zzw
Tags: 1.5+bzr2227-0ubuntu1
* New upstream bugfix release:
  - Fix catching exceptions raised by
    twisted.conch.ssh.keys.Key.fromString (LP: #1298788)
  - Fix validationg in default NodeGroupInterface.broadcast_ip making it
    optional. (LP: #1299374)
  - Drop install-pxe-bootloader as it conflicts with newer import script.
  - Remove references to old import script.
  - Fix changes that cause overwriting of existing entries.
  - Fix inappropriate ValidationError when defining networks with nested
    (but non-identical) address ranges. (LP: #1299114)
  - Fix issue where if a node does not provide an architecture type on dhcp
    request, or no other boot method is available for that architecture,
    the node still uses pxelinux.0 to boot. (LP: #1300285)
  - Take an advisory lock to prevent concurrent creation of the
    eventloops table. (LP: #1300363)
  - Remove the cloud_images_archive setting, as it conflicts with new
    import script. (LP: #1300587)
  - Add a 'logout confirmation' page. Using this, the logout action is
    protected against CSRF attacks because it uses a POST request, in
    conjunction with Django's CSRF protection feature. (LP: #1298790)
  - Fix cluster listings when dealing with large number of clusters by
    paginating it. (LP: #1301242)
  - Change list_boot_images() so that it can cope with a missing boot
    images directory: this happens if the reporting task runs before the
    images have been imported. (LP: #213984)
  - Fix internal server error on fast path installer. (LP: #1293676)
  - Fix uploading files using maas-cli. (LP: #1187826)
  - Fix SM15k Invalid Power Control and Fix enlisting machines with
    2.0 api. (LP: #1302818, LP: #1302819)

[ Andres Rodriguez ]
* debian/maas-cluster-controller.install: Install UEFI templates
* debian/maas-cluster-controller.dirs: Create 'boot-resources' dir.

[ Jason Hobbs ]
* debian/extras/99-maas: Allow access to keyserver.ubuntu.com via
  squid-deb-proxy.
 
[Jeroen Vermeulen]
* debian/maas-cluster-controller.postinst:
  - Make the tgt config link point to the new boot-resources dir.
* debian/maas-region-controller-min.dirs:
  - Don't create /var/lib/maas/tftp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
    NODEGROUPINTERFACE_MANAGEMENT,
21
21
    NODEGROUPINTERFACE_MANAGEMENT_CHOICES_DICT,
22
22
    )
23
 
from maasserver.models import NodeGroup
 
23
from maasserver.models import (
 
24
    NodeGroup,
 
25
    NodeGroupInterface,
 
26
    )
24
27
from maasserver.models.nodegroupinterface import MINIMUM_NETMASK_BITS
 
28
from maasserver.testing import reload_object
25
29
from maasserver.testing.factory import factory
26
30
from maasserver.testing.testcase import MAASServerTestCase
27
31
from maasserver.utils.network import make_network
44
48
        interface = make_interface(network=network)
45
49
        self.assertEqual(IPNetwork("10.0.0.0/24"), interface.network)
46
50
 
47
 
    def test_network_is_defined_when_broadcast_and_mask_are(self):
 
51
    def test_network_is_defined_when_netmask_is(self):
48
52
        interface = make_interface()
49
 
        interface.broadcast = "10.0.0.255"
 
53
        interface.ip = "10.0.0.9"
50
54
        interface.subnet_mask = "255.255.255.0"
51
55
        self.assertIsInstance(interface.network, IPNetwork)
52
56
 
53
 
    def test_network_is_undefined_when_broadcast_is_None(self):
 
57
    def test_network_does_not_require_broadcast_address(self):
54
58
        interface = make_interface()
55
59
        interface.broadcast_ip = None
56
 
        self.assertIsNone(interface.network)
 
60
        self.assertIsInstance(interface.network, IPNetwork)
57
61
 
58
 
    def test_network_is_undefined_when_broadcast_is_empty(self):
 
62
    def test_network_does_not_require_nonempty_broadcast_address(self):
59
63
        interface = make_interface()
60
64
        interface.broadcast_ip = ""
61
 
        self.assertIsNone(interface.network)
 
65
        self.assertIsInstance(interface.network, IPNetwork)
62
66
 
63
67
    def test_network_is_undefined_when_subnet_mask_is_None(self):
64
68
        interface = make_interface()
65
69
        interface.subnet_mask = None
66
70
        self.assertIsNone(interface.network)
67
71
 
68
 
    def test_network_is_undefined_subnet_mask_is_empty(self):
 
72
    def test_network_is_undefined_when_subnet_mask_is_empty(self):
69
73
        interface = make_interface()
70
74
        interface.subnet_mask = ""
71
75
        self.assertIsNone(interface.network)
78
82
 
79
83
    def test_clean_ips_in_network_validates_IP(self):
80
84
        network = IPNetwork('192.168.0.3/24')
 
85
        ip_outside_network = '192.168.2.1'
81
86
        checked_fields = [
82
 
            'ip',
 
87
            'broadcast_ip',
83
88
            'router_ip',
84
89
            'ip_range_low',
85
90
            'ip_range_high',
87
92
        for field in checked_fields:
88
93
            nodegroup = factory.make_node_group(network=network)
89
94
            [interface] = nodegroup.get_managed_interfaces()
90
 
            ip = '192.168.2.1'
91
 
            setattr(interface, field, '192.168.2.1')
92
 
            message = (
93
 
                "%s not in the %s network" % (ip, '192.168.0.0/24'))
 
95
            setattr(interface, field, ip_outside_network)
 
96
            message = "%s not in the %s network" % (
 
97
                ip_outside_network,
 
98
                '192.168.0.0/24',
 
99
                )
94
100
            exception = self.assertRaises(
95
101
                ValidationError, interface.full_clean)
96
 
            self.assertEqual(
97
 
                {field: [message]}, exception.message_dict)
 
102
            self.assertEqual({field: [message]}, exception.message_dict)
98
103
 
99
104
    def test_clean_network(self):
100
105
        nodegroup = factory.make_node_group(
102
107
        [interface] = nodegroup.get_managed_interfaces()
103
108
        # Set a bogus subnet mask.
104
109
        interface.subnet_mask = '0.9.0.4'
105
 
        message = 'invalid IPNetwork 192.168.0.255/0.9.0.4'
 
110
        message = "invalid IPNetwork %s/0.9.0.4" % interface.ip
106
111
        exception = self.assertRaises(ValidationError, interface.full_clean)
107
112
        self.assertEqual(
108
 
            {
109
 
                'subnet_mask': [message],
110
 
                'broadcast_ip': [message],
111
 
            },
 
113
            {'subnet_mask': [message]},
112
114
            exception.message_dict)
113
115
 
114
116
    def test_clean_network_rejects_huge_network(self):
120
122
            "This network is a /%d network." % (
121
123
                MINIMUM_NETMASK_BITS, MINIMUM_NETMASK_BITS - 1))
122
124
        self.assertEqual(
123
 
            {
124
 
                'subnet_mask': [message],
125
 
                'broadcast_ip': [message],
126
 
            },
 
125
            {'subnet_mask': [message]},
127
126
            exception.message_dict)
128
127
 
129
128
    def test_clean_network_accepts_network_if_not_too_big(self):
142
141
        network = IPNetwork('192.168.0.3/24')
143
142
        checked_fields = [
144
143
            'interface',
145
 
            'broadcast_ip',
146
144
            'subnet_mask',
147
145
            'router_ip',
148
146
            'ip_range_low',
160
158
                "That field cannot be empty (unless that interface is "
161
159
                "'unmanaged')")
162
160
            self.assertEqual({field: [message]}, exception.message_dict)
 
161
 
 
162
    def test_clean_network_config_sets_default_if_netmask_not_given(self):
 
163
        network = factory.getRandomNetwork()
 
164
        nodegroup = factory.make_node_group(
 
165
            network=network,
 
166
            management=NODEGROUPINTERFACE_MANAGEMENT.DHCP_AND_DNS)
 
167
        [interface] = nodegroup.get_managed_interfaces()
 
168
        interface.full_clean()
 
169
        self.assertEqual(unicode(network.broadcast), interface.broadcast_ip)
 
170
 
 
171
    def test_clean_network_config_sets_no_broadcast_without_netmask(self):
 
172
        network = factory.getRandomNetwork()
 
173
        nodegroup = factory.make_node_group(
 
174
            network=network,
 
175
            management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
 
176
        interface = NodeGroupInterface.objects.get(nodegroup=nodegroup)
 
177
        interface.subnet_mask = None
 
178
        interface.broadcast_ip = None
 
179
        interface.full_clean()
 
180
        self.assertIsNone(interface.broadcast_ip)
 
181
 
 
182
    def test_default_broadcast_ip_saves_cleanly(self):
 
183
        # When the default value for broadcast_ip was introduced, it broke
 
184
        # the form but not tests.  The reason: the default was an IPAddress,
 
185
        # but GenericIPAddressValidation expects a string.
 
186
        nodegroup = factory.make_node_group()
 
187
        # Can't use the factory for this one; it may hide the problem.
 
188
        interface = NodeGroupInterface(
 
189
            nodegroup=nodegroup, ip='10.1.1.1', router_ip='10.1.1.254',
 
190
            subnet_mask='255.255.255.0', ip_range_low='10.1.1.100',
 
191
            ip_range_high='10.1.1.200', interface='eth99',
 
192
            management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
 
193
        interface.save()
 
194
        self.assertEqual(interface, reload_object(interface))