Merge lp:~therve/landscape-client/duplicate-network-interfaces into lp:~landscape/landscape-client/trunk

Proposed by Thomas Herve
Status: Merged
Merged at revision: 266
Proposed branch: lp:~therve/landscape-client/duplicate-network-interfaces
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 105 lines (+61/-4)
2 files modified
landscape/lib/network.py (+6/-3)
landscape/lib/tests/test_network.py (+55/-1)
To merge this branch: bzr merge lp:~therve/landscape-client/duplicate-network-interfaces
Reviewer Review Type Date Requested Status
Kevin McDermott (community) Approve
Jamu Kakar (community) Approve
Review via email: mp+28141@code.launchpad.net

Description of the change

Triavial change, I hope, except the test which is quite scary.

To post a comment you must log in.
Revision history for this message
Jamu Kakar (jkakar) wrote :

Nice work, +1!

review: Approve
Revision history for this message
Kevin McDermott (bigkevmcd) wrote :

Other than the ioctl response blob, which is unfortunate :-) this is great +1

(Could you maybe build up the blob using pack?)

Oh, and nice use of Mocker :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/lib/network.py'
2--- landscape/lib/network.py 2010-06-10 08:37:55 +0000
3+++ landscape/lib/network.py 2010-06-22 08:26:24 +0000
4@@ -48,7 +48,7 @@
5 """
6 max_interfaces = 128
7
8- # setup an an array to hold our response, and initialized to null strings.
9+ # Setup an an array to hold our response, and initialized to null strings.
10 interfaces = array.array("B", "\0" * max_interfaces * IF_STRUCT_SIZE)
11 buffer_size = interfaces.buffer_info()[0]
12 packed_bytes = struct.pack(
13@@ -59,11 +59,14 @@
14
15 result = interfaces.tostring()
16
17- # generator over the interface names
18+ # Generator over the interface names
19+ already_found = set()
20 for index in range(0, byte_length, IF_STRUCT_SIZE):
21 ifreq_struct = result[index:index+IF_STRUCT_SIZE]
22 interface_name = ifreq_struct[:ifreq_struct.index("\0")]
23- yield interface_name
24+ if interface_name not in already_found:
25+ already_found.add(interface_name)
26+ yield interface_name
27
28
29 def get_broadcast_address(sock, interface):
30
31=== modified file 'landscape/lib/tests/test_network.py'
32--- landscape/lib/tests/test_network.py 2010-06-10 08:37:55 +0000
33+++ landscape/lib/tests/test_network.py 2010-06-22 08:26:24 +0000
34@@ -1,9 +1,12 @@
35+import array
36 from cStringIO import StringIO
37+import socket
38 from subprocess import Popen, PIPE
39 from landscape.tests.helpers import LandscapeTest
40
41 from landscape.lib.network import (
42- get_network_traffic, get_active_device_info)
43+ get_network_traffic, get_active_device_info, get_active_interfaces)
44+from landscape.tests.mocker import ANY
45
46
47 class NetworkInfoTest(LandscapeTest):
48@@ -39,6 +42,57 @@
49 if flags & 4096:
50 self.assertIn("MULTICAST", block)
51
52+ def test_duplicate_network_interfaces(self):
53+ """
54+ L{get_active_interfaces} doesn't return duplicate network interfaces.
55+ The call to C{fcntl.ioctl} might return the same interface several
56+ times, so we make sure to clean it up.
57+ """
58+ import landscape.lib.network
59+ original_struct_size = landscape.lib.network.IF_STRUCT_SIZE
60+ landscape.lib.network.IF_STRUCT_SIZE = 40
61+ self.addCleanup(
62+ setattr, landscape.lib.network, "IF_STRUCT_SIZE",
63+ original_struct_size)
64+ # This is a fake response observed to return the same interface several
65+ # times (here, br1:priv)
66+ response = (
67+ "lo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
68+ "\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
69+ "\x00\x00\x00\x00\x00\x00\x00eth1:pub\x00\x00\x00\x00\x00\x00\x00"
70+ "\x00\x02\x00\x00\x00\xc8\xb4\xc4.\x00\x00\x00\x00\x00\x00\x00\x00"
71+ "\x00\x00\x00\x00\x00\x00\x00\x00br1:metadata\x00\x00\x00\x00\x02"
72+ "\x00\x00\x00\xa9\xfe\xa9\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00"
73+ "\x00\x00\x00\x00\x00\x00\x00br1:0\x00\x00\x00\x00\x00\x00\x00\x00"
74+ "\x00\x00\x00\x02\x00\x00\x00\xc9\x19\x1f\x1d\x00\x00\x00\x00\x00"
75+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00br1\x00\x00\x00\x00"
76+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\xc0\xa8d"
77+ "\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
78+ "\x00br1:priv\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\xac"
79+ "\x13\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
80+ "\x00\x00\x00br1:priv\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00"
81+ "\x00\xac\x13\x02A")
82+
83+ fake_array = array.array("B", response + "\0" * 4855)
84+ mock_array = self.mocker.replace("array.array")
85+ mock_array("B", ANY)
86+ self.mocker.result(fake_array)
87+
88+ mock_ioctl = self.mocker.replace("fcntl.ioctl")
89+ mock_ioctl(ANY, ANY, ANY)
90+ self.mocker.result(0)
91+
92+ mock_unpack = self.mocker.replace("struct.unpack")
93+ mock_unpack("iL", ANY)
94+ self.mocker.result((280, 38643456))
95+ self.mocker.replay()
96+
97+ sock = socket.socket(
98+ socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_IP)
99+ self.assertEqual(
100+ ["lo", "eth1:pub", "br1:metadata", "br1:0", "br1", "br1:priv"],
101+ list(get_active_interfaces(sock)))
102+
103 def test_get_network_traffic(self):
104 """
105 Network traffic is assessed via reading /proc/net/dev, verify

Subscribers

People subscribed via source and target branches

to all changes: