~ubuntu-branches/ubuntu/raring/maas/raring-updates

« back to all changes in this revision

Viewing changes to src/maasserver/utils/tests/test_utils.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Raphaël Badin, Julian Edwards, Andres Rodriguez, Gavin Panella, Jeroen Vermeulen
  • Date: 2012-11-13 14:58:21 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20121113145821-6jq53jtljo3qou80
Tags: 1.2+bzr1349+dfsg-0ubuntu1
* New upstream bugfix release. Fixes:
  - The DNS configuration is not created if maas-dns is installed after
    the DNS config has been set up (LP: #1085865).
  - IPMI detection ends up with power_address of 0.0.0.0 (LP: #1064224)
  - Main page slow to load with many nodes (LP: #1066775)
  - maas-cluster-controller doesn't have images for
    provisioning (LP: #1068843)
  - Filestorage is unique to each appserver instance (LP: #1069734)
  - import_pxe_files does not include quantal (LP: #1069850)
  - maas-cli nodes new incomplete documentation (LP: #1070522)
  - DNS forward zone ends up with nonsensical entries (LP: #1070765)
  - The hostname of a node can still be changed once the node is in
    use. (LP: #1070774)
  - The zone name (attached to a cluster controller) can still be changed
    when it contains in-use nodes and DNS is managed. (LP: #1070775)
  - Duplicated prefix in the url used by the CLI (LP: #1075597)
  - Not importing Quantal boot images (LP: #1077180)
  - Nodes are deployed with wrong domain name. (LP: #1078744)
  - src/maasserver/api.py calls request.data.getlist with a 'default'
    parameter. That parameter is not supported by Django 1.3. (LP: #1080673)
  - API calls that return a node leak private data (LP: #1034318)
  - MAAS hostnames should be 5 easily disambiguated characters (LP: #1058998)
  - URI in API description wrong when accessing machine via alternative
    interface. (LP: #1059645)
  - Oops when renaming nodegroup w/o interface (LP: #1077075)
  - Error in log when using 'Start node' button: MAASAPINotFound: No user
    data available for this node. (LP: #1069603)

[ Raphaël Badin ]
* debian/maas-dns.postinst: Call write_dns_config (LP: #1085865).
* debian/maas-dns.postinst: fix permissions and group ownership of
  file /etc/bind/maas/named.conf.rndc.maas. (LP: #1066935)

[ Julian Edwards ]
* debian/maas-region-controller.install: Remove installation of maas-gc; it
  is no longer required as upstream no longer stores files in the filesystem.
  (LP: #1069734)
* debian/maas-cluster-controller.postinst: Ensure that /etc/maas/pserv.yaml
  is updated when reconfiguring. (LP: #1081212)

[ Andres Rodriguez ]
* debian/control:
  - maas-cluster-controller Conflicts with tftpd-hpa (LP: #1076028)
  - maas-dns: Conflicts with dnsmasq
  - Drop Dependency on rabbitmq-server for maas-cluster-controller.
    (LP: #1072744)
  - Add conflicts/replaces for maas-region-controller to
    maas-cluster-controller.
* debian/maas-cluster-controller.config: If URL has been detected, add
  /MAAS if it doesn't contain it. This helps upgrades from versions where
  DEFAULT_MAAS_URL didn't use /MAAS.
* Install maas-import-pxe-files and related files with
  maas-cluster-controller, as well as configure tgtd, as
  maas-region-controller no longer stores images. Thanks to Jeroen
  Vermuelen.

[ Gavin Panella ]
* debian/extras/99-maas: squashfs image download is no longer needed.
* debian/maas-cluster-controller.install: maas-import-squashfs and its
  configuration file are no longer part of upstream.

[ Jeroen Vermeulen ]
* debian/maas-cluster-controller.maas-pserv.upstart: Source maas_cluster.conf
  before starting pserv (tftpd) process.
* debian/maas-cluster-controller.postinst: Duplicate CLUSTER_UUID setting
  to maas_cluster.conf.
* Bumped revision number to current 1.2 revision 1342 (requested by rvba).

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
from django.conf import settings
18
18
from django.core.urlresolvers import reverse
19
 
from maasserver.enum import NODE_STATUS_CHOICES
 
19
from django.http import HttpRequest
 
20
from django.test.client import RequestFactory
 
21
from maasserver.enum import (
 
22
    NODE_STATUS_CHOICES,
 
23
    NODEGROUPINTERFACE_MANAGEMENT,
 
24
    )
 
25
from maasserver.models import (
 
26
    NodeGroup,
 
27
    nodegroupinterface,
 
28
    NodeGroupInterface,
 
29
    )
20
30
from maasserver.testing.factory import factory
21
31
from maasserver.testing.testcase import TestCase as DjangoTestCase
22
32
from maasserver.utils import (
23
33
    absolute_reverse,
 
34
    build_absolute_uri,
 
35
    find_nodegroup,
24
36
    get_db_state,
25
37
    map_enum,
 
38
    strip_domain,
26
39
    )
27
40
from maastesting.testcase import TestCase
 
41
from netaddr import IPNetwork
28
42
 
29
43
 
30
44
class TestEnum(TestCase):
64
78
 
65
79
class TestAbsoluteReverse(DjangoTestCase):
66
80
 
67
 
    def test_absolute_reverse_uses_DEFAULT_MAAS_URL(self):
 
81
    def test_absolute_reverse_uses_DEFAULT_MAAS_URL_by_default(self):
68
82
        maas_url = 'http://%s' % factory.getRandomString()
69
83
        self.patch(settings, 'DEFAULT_MAAS_URL', maas_url)
70
84
        absolute_url = absolute_reverse('settings')
71
85
        expected_url = settings.DEFAULT_MAAS_URL + reverse('settings')
72
86
        self.assertEqual(expected_url, absolute_url)
73
87
 
 
88
    def test_absolute_reverse_uses_given_base_url(self):
 
89
        maas_url = 'http://%s' % factory.getRandomString()
 
90
        absolute_url = absolute_reverse('settings', base_url=maas_url)
 
91
        expected_url = maas_url + reverse('settings')
 
92
        self.assertEqual(expected_url, absolute_url)
 
93
 
74
94
    def test_absolute_reverse_uses_query_string(self):
75
95
        self.patch(settings, 'DEFAULT_MAAS_URL', '')
76
96
        parameters = {factory.getRandomString(): factory.getRandomString()}
104
124
            NODE_STATUS_CHOICES, but_not=[status])
105
125
        node.status = another_status
106
126
        self.assertEqual(status, get_db_state(node, 'status'))
 
127
 
 
128
 
 
129
class TestBuildAbsoluteURI(TestCase):
 
130
    """Tests for `build_absolute_uri`."""
 
131
 
 
132
    def make_request(self, host="example.com", port=80, script_name="",
 
133
                     is_secure=False):
 
134
        """Return a :class:`HttpRequest` with the given parameters."""
 
135
        request = HttpRequest()
 
136
        request.META["SERVER_NAME"] = host
 
137
        request.META["SERVER_PORT"] = port
 
138
        request.META["SCRIPT_NAME"] = script_name
 
139
        request.is_secure = lambda: is_secure
 
140
        return request
 
141
 
 
142
    def test_simple(self):
 
143
        request = self.make_request()
 
144
        self.assertEqual(
 
145
            "http://example.com/fred",
 
146
            build_absolute_uri(request, "/fred"))
 
147
 
 
148
    def test_different_port(self):
 
149
        request = self.make_request(port=1234)
 
150
        self.assertEqual(
 
151
            "http://example.com:1234/fred",
 
152
            build_absolute_uri(request, "/fred"))
 
153
 
 
154
    def test_script_name_is_ignored(self):
 
155
        # The given path already includes the script_name, so the
 
156
        # script_name passed in the request is not included again.
 
157
        request = self.make_request(script_name="/foo/bar")
 
158
        self.assertEqual(
 
159
            "http://example.com/foo/bar/fred",
 
160
            build_absolute_uri(request, "/foo/bar/fred"))
 
161
 
 
162
    def test_secure(self):
 
163
        request = self.make_request(port=443, is_secure=True)
 
164
        self.assertEqual(
 
165
            "https://example.com/fred",
 
166
            build_absolute_uri(request, "/fred"))
 
167
 
 
168
    def test_different_port_and_secure(self):
 
169
        request = self.make_request(port=9443, is_secure=True)
 
170
        self.assertEqual(
 
171
            "https://example.com:9443/fred",
 
172
            build_absolute_uri(request, "/fred"))
 
173
 
 
174
    def test_preserve_two_leading_slashes(self):
 
175
        # Whilst this shouldn't ordinarily happen, two leading slashes in the
 
176
        # path should be preserved, and not treated specially.
 
177
        request = self.make_request()
 
178
        self.assertEqual(
 
179
            "http://example.com//foo",
 
180
            build_absolute_uri(request, "//foo"))
 
181
 
 
182
 
 
183
class TestStripDomain(TestCase):
 
184
 
 
185
    def test_strip_domain(self):
 
186
        input_and_results = [
 
187
            ('name.domain',  'name'),
 
188
            ('name', 'name'),
 
189
            ('name.domain.what', 'name'),
 
190
            ('name..domain', 'name'),
 
191
            ]
 
192
        inputs = [input for input, _ in input_and_results]
 
193
        results = [result for _, result in input_and_results]
 
194
        self.assertEqual(results, map(strip_domain, inputs))
 
195
 
 
196
 
 
197
def get_request(origin_ip):
 
198
    return RequestFactory().post('/', REMOTE_ADDR=origin_ip)
 
199
 
 
200
 
 
201
class TestFindNodegroup(DjangoTestCase):
 
202
 
 
203
    def test_finds_nodegroup_by_network_address(self):
 
204
        nodegroup = factory.make_node_group(
 
205
            network=IPNetwork("192.168.28.1/24"))
 
206
        self.assertEqual(
 
207
            nodegroup,
 
208
            find_nodegroup(get_request('192.168.28.0')))
 
209
 
 
210
    def test_find_nodegroup_looks_up_nodegroup_by_controller_ip(self):
 
211
        nodegroup = factory.make_node_group()
 
212
        ip = nodegroup.get_managed_interface().ip
 
213
        self.assertEqual(
 
214
            nodegroup,
 
215
            find_nodegroup(get_request(ip)))
 
216
 
 
217
    def test_find_nodegroup_looks_up_only_configured_interfaces(self):
 
218
        network = IPNetwork("192.168.41.0/24")
 
219
        factory.make_node_group(
 
220
            network=network,
 
221
            management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
 
222
        ip = factory.getRandomIPInNetwork(network)
 
223
        self.assertIsNone(find_nodegroup(get_request(ip)))
 
224
 
 
225
    def test_find_nodegroup_accepts_any_ip_in_nodegroup_subnet(self):
 
226
        nodegroup = factory.make_node_group(
 
227
            network=IPNetwork("192.168.41.0/24"))
 
228
        self.assertEqual(
 
229
            nodegroup,
 
230
            find_nodegroup(get_request('192.168.41.199')))
 
231
 
 
232
    def test_find_nodegroup_returns_None_if_not_found(self):
 
233
        self.assertIsNone(
 
234
            find_nodegroup(get_request(factory.getRandomIPAddress())))
 
235
 
 
236
    def test_find_nodegroup_errors_if_multiple_matches(self):
 
237
        self.patch(nodegroupinterface, "MINIMUM_NETMASK_BITS", 1)
 
238
        factory.make_node_group(network=IPNetwork("10/8"))
 
239
        factory.make_node_group(network=IPNetwork("10.1.1/24"))
 
240
        self.assertRaises(
 
241
            NodeGroup.MultipleObjectsReturned,
 
242
            find_nodegroup, get_request('10.1.1.2'))
 
243
 
 
244
    def test_find_nodegroup_handles_multiple_matches_on_same_nodegroup(self):
 
245
        self.patch(nodegroupinterface, "MINIMUM_NETMASK_BITS", 1)
 
246
        nodegroup = factory.make_node_group(network=IPNetwork("10/8"))
 
247
        NodeGroupInterface.objects.create(
 
248
            nodegroup=nodegroup, ip='10.0.0.2', subnet_mask='255.0.0.0',
 
249
            broadcast_ip='10.0.0.1', interface='eth71')
 
250
        NodeGroupInterface.objects.create(
 
251
            nodegroup=nodegroup, ip='10.0.0.3', subnet_mask='255.0.0.0',
 
252
            broadcast_ip='10.0.0.2', interface='eth72')
 
253
        self.assertEqual(nodegroup, find_nodegroup(get_request('10.0.0.9')))