~ubuntu-branches/ubuntu/utopic/maas/utopic-updates

« back to all changes in this revision

Viewing changes to src/provisioningserver/utils/tests/test_network.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Jeroen Vermeulen, Andres Rodriguez, Jason Hobbs, Raphaël Badin, Louis Bouchard, Gavin Panella
  • Date: 2014-08-21 19:36:30 UTC
  • mfrom: (1.3.1)
  • Revision ID: package-import@ubuntu.com-20140821193630-kertpu5hd8yyss8h
Tags: 1.7.0~beta7+bzr3266-0ubuntu1
* New Upstream Snapshot, Beta 7 bzr3266

[ Jeroen Vermeulen ]
* debian/extras/99-maas-sudoers
  debian/maas-dhcp.postinst
  debian/rules
  - Add second DHCP server instance for IPv6.
* debian/maas-region-controller-min.install
  debian/maas-region-controller-min.lintian-overrides
  - Install deployment user-data: maas_configure_interfaces.py script.
* debian/maas-cluster-controller.links
  debian/maas-cluster-controller.install
  debian/maas-cluster-controller.postinst
  - Reflect Celery removal changes made in trunk r3067.
  - Don't install celeryconfig_cluster.py any longer. 
  - Don't install maas_local_celeryconfig_cluster.py any longer.
  - Don't symlink maas_local_celeryconfig_cluster.py from /etc to /usr.
  - Don't insert UUID into maas_local_celeryconfig_cluster.py.

[ Andres Rodriguez ]
* debian/maas-region-controller-min.postrm: Cleanup lefover files.
* debian/maas-dhcp.postrm: Clean leftover configs.
* Provide new maas-proxy package that replaces the usage of
  squid-deb-proxy:
  - debian/control: New maas-proxy package that replaces the usage
    of squid-deb-proxy; Drop depends on squid-deb-proxy.
  - Add upstrart job.
  - Ensure squid3 is stopped as maas-proxy uses a caching proxy.
* Remove Celery references to cluster controller:
  - Rename upstart job from maas-pserv to maas-cluster; rename
    maas-cluster-celery to maas-cluster-register. Ensure services
    are stopped on upgrade.
  - debian/maintscript: Cleanup config files.
  - Remove all references to the MAAS celery daemon and config
    files as we don't use it like that anymore
* Move some entries in debian/maintscript to
  debian/maas-cluster-controller.maintscript
* Remove usage of txlongpoll and rabbitmq-server. Handle upgrades
  to ensure these are removed correctly.

[ Jason Hobbs ]
* debian/maas-region-controller-min.install: Install
  maas-generate-winrm-cert script.

[ Raphaël Badin ]
* debian/extras/maas-region-admin: Bypass django-admin as it prints
  spurious messages to stdout (LP: #1365130).

[Louis Bouchard]
* debian/maas-cluster-controller.postinst:
  - Exclude /var/log/maas/rsyslog when changing ownership
    (LP: #1346703)

[Gavin Panella]
* debian/maas-cluster-controller.maas-clusterd.upstart:
  - Don't start-up the cluster controller unless a shared-secret has
    been installed.
* debian/maas-cluster-controller.maas-cluster-register.upstart: Drop.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
__metaclass__ = type
15
15
__all__ = []
16
16
 
 
17
from socket import (
 
18
    EAI_BADFLAGS,
 
19
    EAI_NODATA,
 
20
    EAI_NONAME,
 
21
    gaierror,
 
22
    )
 
23
 
17
24
from maastesting.factory import factory
18
25
from maastesting.matchers import MockCalledOnceWith
19
26
from maastesting.testcase import MAASTestCase
20
27
import mock
21
 
from netaddr import IPNetwork
 
28
from netaddr import (
 
29
    IPAddress,
 
30
    IPNetwork,
 
31
    )
22
32
import netifaces
23
33
from netifaces import (
24
34
    AF_LINK,
34
44
    get_all_addresses_for_interface,
35
45
    get_all_interface_addresses,
36
46
    make_network,
 
47
    resolve_hostname,
37
48
    )
38
49
 
39
50
 
79
90
        self.assertEqual("192.168.0.1", ip_address_observed)
80
91
 
81
92
    def test__returns_consistent_output(self):
82
 
        mac = factory.getRandomMACAddress()
 
93
        mac = factory.make_mac_address()
83
94
        ips = [
84
95
            '10.0.0.11',
85
96
            '10.0.0.99',
93
104
        self.assertIn(one_result, ips)
94
105
        self.assertEqual(one_result, other_result)
95
106
 
 
107
    def test__ignores_case(self):
 
108
        sample = """\
 
109
        192.168.0.1 ether   90:f6:52:f6:17:92   C                     eth0
 
110
        """
 
111
        self.patch_call(sample)
 
112
        ip_address_observed = find_ip_via_arp("90:f6:52:f6:17:92".upper())
 
113
        self.assertEqual("192.168.0.1", ip_address_observed)
 
114
 
96
115
 
97
116
class TestFindMACViaARP(MAASTestCase):
98
117
 
105
124
    def make_output_line(self, ip=None, mac=None, dev=None):
106
125
        """Compose an `ip neigh` output line for given `ip` and `mac`."""
107
126
        if ip is None:
108
 
            ip = factory.getRandomIPAddress()
 
127
            ip = factory.make_ipv4_address()
109
128
        if mac is None:
110
 
            mac = factory.getRandomMACAddress()
 
129
            mac = factory.make_mac_address()
111
130
        if dev is None:
112
131
            dev = factory.make_name('eth', sep='')
113
132
        return "%(ip)s dev %(dev)s lladdr %(mac)s\n" % {
118
137
 
119
138
    def test__calls_ip_neigh(self):
120
139
        call_and_check = self.patch_call('')
121
 
        find_mac_via_arp(factory.getRandomIPAddress())
 
140
        find_mac_via_arp(factory.make_ipv4_address())
122
141
        self.assertThat(
123
142
            call_and_check,
124
143
            MockCalledOnceWith(['ip', 'neigh'], env={'LC_ALL': 'C'}))
125
144
 
126
145
    def test__works_with_real_call(self):
127
 
        find_mac_via_arp(factory.getRandomIPAddress())
 
146
        find_mac_via_arp(factory.make_ipv4_address())
128
147
        # No error.
129
148
        pass
130
149
 
131
150
    def test__fails_on_nonsensical_output(self):
132
151
        self.patch_call("Weird output...")
133
152
        self.assertRaises(
134
 
            Exception, find_mac_via_arp, factory.getRandomIPAddress())
 
153
            Exception, find_mac_via_arp, factory.make_ipv4_address())
135
154
 
136
155
    def test__returns_None_if_not_found(self):
137
156
        self.patch_call(self.make_output_line())
138
 
        self.assertIsNone(find_mac_via_arp(factory.getRandomIPAddress()))
 
157
        self.assertIsNone(find_mac_via_arp(factory.make_ipv4_address()))
139
158
 
140
159
    def test__resolves_IPv4_address_to_MAC(self):
141
160
        sample = "10.55.60.9 dev eth0 lladdr 3c:41:92:68:2e:00 REACHABLE\n"
152
171
        self.assertEqual('3c:41:92:6b:2e:00', mac_address_observed)
153
172
 
154
173
    def test__ignores_failed_neighbours(self):
155
 
        ip = factory.getRandomIPAddress()
 
174
        ip = factory.make_ipv4_address()
156
175
        self.patch_call("%s dev eth0  FAILED\n" % ip)
157
176
        self.assertIsNone(find_mac_via_arp(ip))
158
177
 
162
181
        self.assertIsNone(find_mac_via_arp('10.1.1.100'))
163
182
 
164
183
    def test__is_not_fooled_by_different_notations(self):
165
 
        mac = factory.getRandomMACAddress()
 
184
        mac = factory.make_mac_address()
166
185
        self.patch_call(self.make_output_line('9::0:05', mac=mac))
167
186
        self.assertEqual(mac, find_mac_via_arp('09:0::5'))
168
187
 
169
188
    def test__returns_consistent_output(self):
170
 
        ip = factory.getRandomIPAddress()
 
189
        ip = factory.make_ipv4_address()
171
190
        macs = [
172
191
            '52:54:00:02:86:4b',
173
192
            '90:f6:52:f6:17:92',
200
219
    scenarios = [
201
220
        ('ipv4', {
202
221
            'inet_class': AF_INET,
203
 
            'network_factory': factory.getRandomNetwork,
204
 
            'ip_address_factory': factory.getRandomIPAddress,
 
222
            'network_factory': factory.make_ipv4_network,
 
223
            'ip_address_factory': factory.make_ipv4_address,
205
224
            'loopback_address': '127.0.0.1',
206
225
            }),
207
226
        ('ipv6', {
243
262
        patch_interfaces(self, {
244
263
            interface: {
245
264
                AF_LINK: [{
246
 
                    'addr': unicode(factory.getRandomMACAddress()),
247
 
                    'peer': unicode(factory.getRandomMACAddress()),
 
265
                    'addr': unicode(factory.make_mac_address()),
 
266
                    'peer': unicode(factory.make_mac_address()),
248
267
                    }],
249
268
                },
250
269
            })
282
301
            list(get_all_interface_addresses()))
283
302
 
284
303
    def test_returns_all_addresses_for_all_interfaces(self):
285
 
        v4_ips = [factory.getRandomIPAddress() for i in range(2)]
286
 
        v6_ips = [factory.make_ipv6_address() for i in range(2)]
 
304
        v4_ips = [factory.make_ipv4_address() for _ in range(2)]
 
305
        v6_ips = [factory.make_ipv6_address() for _ in range(2)]
287
306
        ips = zip(v4_ips, v6_ips)
288
307
        interfaces = {
289
308
            factory.make_name('eth', sep=''): {
312
331
        self.patch(netifaces, 'ifaddresses', interfaces.get)
313
332
 
314
333
    def test_returns_all_addresses_for_interface(self):
315
 
        v4_ip = factory.getRandomIPAddress()
 
334
        v4_ip = factory.make_ipv4_address()
316
335
        v6_ip = factory.make_ipv6_address()
317
336
        interface = factory.make_name('eth', sep='')
318
337
        patch_interfaces(self, {
330
349
    """Tests for `clean_up_netifaces_address`."""
331
350
 
332
351
    def test__leaves_IPv4_intact(self):
333
 
        ip = unicode(factory.getRandomIPAddress())
 
352
        ip = unicode(factory.make_ipv4_address())
334
353
        interface = factory.make_name('eth')
335
354
        self.assertEqual(ip, clean_up_netifaces_address(ip, interface))
336
355
 
345
364
        self.assertEqual(
346
365
            ip,
347
366
            clean_up_netifaces_address('%s%%%s' % (ip, interface), interface))
 
367
 
 
368
 
 
369
class TestResolveHostname(MAASTestCase):
 
370
    """Tests for `resolve_hostname`."""
 
371
 
 
372
    def patch_getaddrinfo(self, *addrs):
 
373
        fake = self.patch(network_module, 'getaddrinfo')
 
374
        fake.return_value = [
 
375
            (None, None, None, None, (unicode(address), None))
 
376
            for address in addrs
 
377
            ]
 
378
        return fake
 
379
 
 
380
    def patch_getaddrinfo_fail(self, exception):
 
381
        fake = self.patch(network_module, 'getaddrinfo')
 
382
        fake.side_effect = exception
 
383
        return fake
 
384
 
 
385
    def test__rejects_weird_IP_version(self):
 
386
        self.assertRaises(
 
387
            AssertionError,
 
388
            resolve_hostname, factory.make_hostname(), ip_version=5)
 
389
 
 
390
    def test__integrates_with_getaddrinfo(self):
 
391
        result = resolve_hostname('localhost', 4)
 
392
        self.assertIsInstance(result, set)
 
393
        [localhost] = result
 
394
        self.assertIsInstance(localhost, IPAddress)
 
395
        self.assertIn(localhost, IPNetwork('127.0.0.0/8'))
 
396
 
 
397
    def test__resolves_IPv4_address(self):
 
398
        ip = factory.make_ipv4_address()
 
399
        fake = self.patch_getaddrinfo(ip)
 
400
        hostname = factory.make_hostname()
 
401
        result = resolve_hostname(hostname, 4)
 
402
        self.assertIsInstance(result, set)
 
403
        self.assertEqual({IPAddress(ip)}, result)
 
404
        self.assertThat(fake, MockCalledOnceWith(hostname, mock.ANY, AF_INET))
 
405
 
 
406
    def test__resolves_IPv6_address(self):
 
407
        ip = factory.make_ipv6_address()
 
408
        fake = self.patch_getaddrinfo(ip)
 
409
        hostname = factory.make_hostname()
 
410
        result = resolve_hostname(hostname, 6)
 
411
        self.assertIsInstance(result, set)
 
412
        self.assertEqual({IPAddress(ip)}, result)
 
413
        self.assertThat(fake, MockCalledOnceWith(hostname, mock.ANY, AF_INET6))
 
414
 
 
415
    def test__returns_empty_if_address_does_not_resolve(self):
 
416
        self.patch_getaddrinfo_fail(
 
417
            gaierror(EAI_NONAME, "Name or service not known"))
 
418
        self.assertEqual(set(), resolve_hostname(factory.make_hostname(), 4))
 
419
 
 
420
    def test__returns_empty_if_address_resolves_to_no_data(self):
 
421
        self.patch_getaddrinfo_fail(
 
422
            gaierror(EAI_NODATA, "No data returned"))
 
423
        self.assertEqual(set(), resolve_hostname(factory.make_hostname(), 4))
 
424
 
 
425
    def test__propagates_other_gaierrors(self):
 
426
        self.patch_getaddrinfo_fail(gaierror(EAI_BADFLAGS, "Bad parameters"))
 
427
        self.assertRaises(
 
428
            gaierror,
 
429
            resolve_hostname, factory.make_hostname(), 4)
 
430
 
 
431
    def test__propagates_unexpected_errors(self):
 
432
        self.patch_getaddrinfo_fail(KeyError("Huh what?"))
 
433
        self.assertRaises(
 
434
            KeyError,
 
435
            resolve_hostname, factory.make_hostname(), 4)