1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# This file is part of cloud-init. See LICENSE file for license information.
"""Tests netinfo module functions and classes."""
from copy import copy
from cloudinit.netinfo import netdev_pformat, route_pformat
from cloudinit.tests.helpers import CiTestCase, mock, readResource
# Example ifconfig and route output
SAMPLE_OLD_IFCONFIG_OUT = readResource("netinfo/old-ifconfig-output")
SAMPLE_NEW_IFCONFIG_OUT = readResource("netinfo/new-ifconfig-output")
SAMPLE_IPADDRSHOW_OUT = readResource("netinfo/sample-ipaddrshow-output")
SAMPLE_ROUTE_OUT_V4 = readResource("netinfo/sample-route-output-v4")
SAMPLE_ROUTE_OUT_V6 = readResource("netinfo/sample-route-output-v6")
SAMPLE_IPROUTE_OUT_V4 = readResource("netinfo/sample-iproute-output-v4")
SAMPLE_IPROUTE_OUT_V6 = readResource("netinfo/sample-iproute-output-v6")
NETDEV_FORMATTED_OUT = readResource("netinfo/netdev-formatted-output")
ROUTE_FORMATTED_OUT = readResource("netinfo/route-formatted-output")
class TestNetInfo(CiTestCase):
maxDiff = None
with_logs = True
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_netdev_old_nettools_pformat(self, m_subp, m_which):
"""netdev_pformat properly rendering old nettools info."""
m_subp.return_value = (SAMPLE_OLD_IFCONFIG_OUT, '')
m_which.side_effect = lambda x: x if x == 'ifconfig' else None
content = netdev_pformat()
self.assertEqual(NETDEV_FORMATTED_OUT, content)
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_netdev_new_nettools_pformat(self, m_subp, m_which):
"""netdev_pformat properly rendering netdev new nettools info."""
m_subp.return_value = (SAMPLE_NEW_IFCONFIG_OUT, '')
m_which.side_effect = lambda x: x if x == 'ifconfig' else None
content = netdev_pformat()
self.assertEqual(NETDEV_FORMATTED_OUT, content)
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_netdev_iproute_pformat(self, m_subp, m_which):
"""netdev_pformat properly rendering ip route info."""
m_subp.return_value = (SAMPLE_IPADDRSHOW_OUT, '')
m_which.side_effect = lambda x: x if x == 'ip' else None
content = netdev_pformat()
new_output = copy(NETDEV_FORMATTED_OUT)
# ip route show describes global scopes on ipv4 addresses
# whereas ifconfig does not. Add proper global/host scope to output.
new_output = new_output.replace('| . | 50:7b', '| global | 50:7b')
new_output = new_output.replace(
'255.0.0.0 | . |', '255.0.0.0 | host |')
self.assertEqual(new_output, content)
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_netdev_warn_on_missing_commands(self, m_subp, m_which):
"""netdev_pformat warns when missing both ip and 'netstat'."""
m_which.return_value = None # Niether ip nor netstat found
content = netdev_pformat()
self.assertEqual('\n', content)
self.assertEqual(
"WARNING: Could not print networks: missing 'ip' and 'ifconfig'"
" commands\n",
self.logs.getvalue())
m_subp.assert_not_called()
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_route_nettools_pformat(self, m_subp, m_which):
"""route_pformat properly rendering nettools route info."""
def subp_netstat_route_selector(*args, **kwargs):
if args[0] == ['netstat', '--route', '--numeric', '--extend']:
return (SAMPLE_ROUTE_OUT_V4, '')
if args[0] == ['netstat', '-A', 'inet6', '--route', '--numeric']:
return (SAMPLE_ROUTE_OUT_V6, '')
raise Exception('Unexpected subp call %s' % args[0])
m_subp.side_effect = subp_netstat_route_selector
m_which.side_effect = lambda x: x if x == 'netstat' else None
content = route_pformat()
self.assertEqual(ROUTE_FORMATTED_OUT, content)
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_route_iproute_pformat(self, m_subp, m_which):
"""route_pformat properly rendering ip route info."""
def subp_iproute_selector(*args, **kwargs):
if ['ip', '-o', 'route', 'list'] == args[0]:
return (SAMPLE_IPROUTE_OUT_V4, '')
v6cmd = ['ip', '--oneline', '-6', 'route', 'list', 'table', 'all']
if v6cmd == args[0]:
return (SAMPLE_IPROUTE_OUT_V6, '')
raise Exception('Unexpected subp call %s' % args[0])
m_subp.side_effect = subp_iproute_selector
m_which.side_effect = lambda x: x if x == 'ip' else None
content = route_pformat()
self.assertEqual(ROUTE_FORMATTED_OUT, content)
@mock.patch('cloudinit.netinfo.util.which')
@mock.patch('cloudinit.netinfo.util.subp')
def test_route_warn_on_missing_commands(self, m_subp, m_which):
"""route_pformat warns when missing both ip and 'netstat'."""
m_which.return_value = None # Niether ip nor netstat found
content = route_pformat()
self.assertEqual('\n', content)
self.assertEqual(
"WARNING: Could not print routes: missing 'ip' and 'netstat'"
" commands\n",
self.logs.getvalue())
m_subp.assert_not_called()
# vi: ts=4 expandtab
|