Merge ~smoser/cloud-init:fix/1766302-show-nics-not-up into cloud-init:master

Proposed by Scott Moser
Status: Merged
Approved by: Chad Smith
Approved revision: 9f0a1506cab8861c6a1c391715e4507bbbbaf97c
Merge reported by: Chad Smith
Merged at revision: 14cb4924a6cf191107f9c04698ace2753eb44d2b
Proposed branch: ~smoser/cloud-init:fix/1766302-show-nics-not-up
Merge into: cloud-init:master
Diff against target: 183 lines (+107/-11)
5 files modified
cloudinit/netinfo.py (+30/-10)
cloudinit/tests/test_netinfo.py (+46/-1)
tests/data/netinfo/netdev-formatted-output-down (+8/-0)
tests/data/netinfo/new-ifconfig-output-down (+15/-0)
tests/data/netinfo/sample-ipaddrshow-output-down (+8/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Chad Smith Approve
Review via email: mp+343846@code.launchpad.net

Commit message

netinfo: fix netdev_pformat when a nic does not have an address assigned.

The last set of changes to netdev_pformat ended up dropping the output
of devices that were not up. This adds back the 'down' interfaces to the
rendered output.

LP: #1766302

Description of the change

see commit message

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:094609b8f51bc05d5bb57315836ec720aa78387f
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1044/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1044/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:caa585b9e599681a90d66511d0dd43bc4e3eac6a
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1045/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1045/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Given the test failure, I think you need something like this to fix the logic in netdev_pformat
http://paste.ubuntu.com/p/693vYVCM7r/

Also this branch was proposed on top of my WIP OpenStackLocal branch which we want to separate I think. Please re-propose without the dependency.

review: Needs Fixing
Revision history for this message
Chad Smith (chad.smith) wrote :

Thanks for separating it. Looks good.

review: Approve
Revision history for this message
Chad Smith (chad.smith) wrote :

An upstream commit landed for this bug.

To view that commit see the following URL:
https://git.launchpad.net/cloud-init/commit/?id=14cb4924

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1091/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/1091/rebuild

review: Approve (continuous-integration)

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/netinfo.py b/cloudinit/netinfo.py
2index f090616..1be76fe 100644
3--- a/cloudinit/netinfo.py
4+++ b/cloudinit/netinfo.py
5@@ -158,12 +158,28 @@ def netdev_info(empty=""):
6 LOG.warning(
7 "Could not print networks: missing 'ip' and 'ifconfig' commands")
8
9- if empty != "":
10- for (_devname, dev) in devs.items():
11- for field in dev:
12- if dev[field] == "":
13- dev[field] = empty
14+ if empty == "":
15+ return devs
16+
17+ recurse_types = (dict, tuple, list)
18+
19+ def fill(data, new_val="", empty_vals=("", b"")):
20+ """Recursively replace 'empty_vals' in data (dict, tuple, list)
21+ with new_val"""
22+ if isinstance(data, dict):
23+ myiter = data.items()
24+ elif isinstance(data, (tuple, list)):
25+ myiter = enumerate(data)
26+ else:
27+ raise TypeError("Unexpected input to fill")
28+
29+ for key, val in myiter:
30+ if val in empty_vals:
31+ data[key] = new_val
32+ elif isinstance(val, recurse_types):
33+ fill(val, new_val)
34
35+ fill(devs, new_val=empty)
36 return devs
37
38
39@@ -353,8 +369,9 @@ def getgateway():
40
41 def netdev_pformat():
42 lines = []
43+ empty = "."
44 try:
45- netdev = netdev_info(empty=".")
46+ netdev = netdev_info(empty=empty)
47 except Exception as e:
48 lines.append(
49 util.center(
50@@ -368,12 +385,15 @@ def netdev_pformat():
51 for (dev, data) in sorted(netdev.items()):
52 for addr in data.get('ipv4'):
53 tbl.add_row(
54- [dev, data["up"], addr["ip"], addr["mask"],
55- addr.get('scope', '.'), data["hwaddr"]])
56+ (dev, data["up"], addr["ip"], addr["mask"],
57+ addr.get('scope', empty), data["hwaddr"]))
58 for addr in data.get('ipv6'):
59 tbl.add_row(
60- [dev, data["up"], addr["ip"], ".", addr["scope6"],
61- data["hwaddr"]])
62+ (dev, data["up"], addr["ip"], empty, addr["scope6"],
63+ data["hwaddr"]))
64+ if len(data.get('ipv6')) + len(data.get('ipv4')) == 0:
65+ tbl.add_row((dev, data["up"], empty, empty, empty,
66+ data["hwaddr"]))
67 netdev_s = tbl.get_string()
68 max_len = len(max(netdev_s.splitlines(), key=len))
69 header = util.center("Net device info", "+", max_len)
70diff --git a/cloudinit/tests/test_netinfo.py b/cloudinit/tests/test_netinfo.py
71index 2537c1c..d76e768 100644
72--- a/cloudinit/tests/test_netinfo.py
73+++ b/cloudinit/tests/test_netinfo.py
74@@ -4,7 +4,7 @@
75
76 from copy import copy
77
78-from cloudinit.netinfo import netdev_pformat, route_pformat
79+from cloudinit.netinfo import netdev_info, netdev_pformat, route_pformat
80 from cloudinit.tests.helpers import CiTestCase, mock, readResource
81
82
83@@ -73,6 +73,51 @@ class TestNetInfo(CiTestCase):
84
85 @mock.patch('cloudinit.netinfo.util.which')
86 @mock.patch('cloudinit.netinfo.util.subp')
87+ def test_netdev_info_nettools_down(self, m_subp, m_which):
88+ """test netdev_info using nettools and down interfaces."""
89+ m_subp.return_value = (
90+ readResource("netinfo/new-ifconfig-output-down"), "")
91+ m_which.side_effect = lambda x: x if x == 'ifconfig' else None
92+ self.assertEqual(
93+ {'eth0': {'ipv4': [], 'ipv6': [],
94+ 'hwaddr': '00:16:3e:de:51:a6', 'up': False},
95+ 'lo': {'ipv4': [{'ip': '127.0.0.1', 'mask': '255.0.0.0'}],
96+ 'ipv6': [{'ip': '::1/128', 'scope6': 'host'}],
97+ 'hwaddr': '.', 'up': True}},
98+ netdev_info("."))
99+
100+ @mock.patch('cloudinit.netinfo.util.which')
101+ @mock.patch('cloudinit.netinfo.util.subp')
102+ def test_netdev_info_iproute_down(self, m_subp, m_which):
103+ """Test netdev_info with ip and down interfaces."""
104+ m_subp.return_value = (
105+ readResource("netinfo/sample-ipaddrshow-output-down"), "")
106+ m_which.side_effect = lambda x: x if x == 'ip' else None
107+ self.assertEqual(
108+ {'lo': {'ipv4': [{'ip': '127.0.0.1', 'bcast': '.',
109+ 'mask': '255.0.0.0', 'scope': 'host'}],
110+ 'ipv6': [{'ip': '::1/128', 'scope6': 'host'}],
111+ 'hwaddr': '.', 'up': True},
112+ 'eth0': {'ipv4': [], 'ipv6': [],
113+ 'hwaddr': '00:16:3e:de:51:a6', 'up': False}},
114+ netdev_info("."))
115+
116+ @mock.patch('cloudinit.netinfo.netdev_info')
117+ def test_netdev_pformat_with_down(self, m_netdev_info):
118+ """test netdev_pformat when netdev_info returns 'down' interfaces."""
119+ m_netdev_info.return_value = (
120+ {'lo': {'ipv4': [{'ip': '127.0.0.1', 'mask': '255.0.0.0',
121+ 'scope': 'host'}],
122+ 'ipv6': [{'ip': '::1/128', 'scope6': 'host'}],
123+ 'hwaddr': '.', 'up': True},
124+ 'eth0': {'ipv4': [], 'ipv6': [],
125+ 'hwaddr': '00:16:3e:de:51:a6', 'up': False}})
126+ self.assertEqual(
127+ readResource("netinfo/netdev-formatted-output-down"),
128+ netdev_pformat())
129+
130+ @mock.patch('cloudinit.netinfo.util.which')
131+ @mock.patch('cloudinit.netinfo.util.subp')
132 def test_route_nettools_pformat(self, m_subp, m_which):
133 """route_pformat properly rendering nettools route info."""
134
135diff --git a/tests/data/netinfo/netdev-formatted-output-down b/tests/data/netinfo/netdev-formatted-output-down
136new file mode 100644
137index 0000000..038dfb4
138--- /dev/null
139+++ b/tests/data/netinfo/netdev-formatted-output-down
140@@ -0,0 +1,8 @@
141++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++
142++--------+-------+-----------+-----------+-------+-------------------+
143+| Device | Up | Address | Mask | Scope | Hw-Address |
144++--------+-------+-----------+-----------+-------+-------------------+
145+| eth0 | False | . | . | . | 00:16:3e:de:51:a6 |
146+| lo | True | 127.0.0.1 | 255.0.0.0 | host | . |
147+| lo | True | ::1/128 | . | host | . |
148++--------+-------+-----------+-----------+-------+-------------------+
149diff --git a/tests/data/netinfo/new-ifconfig-output-down b/tests/data/netinfo/new-ifconfig-output-down
150new file mode 100644
151index 0000000..5d12e35
152--- /dev/null
153+++ b/tests/data/netinfo/new-ifconfig-output-down
154@@ -0,0 +1,15 @@
155+eth0: flags=4098<BROADCAST,MULTICAST> mtu 1500
156+ ether 00:16:3e:de:51:a6 txqueuelen 1000 (Ethernet)
157+ RX packets 126229 bytes 158139342 (158.1 MB)
158+ RX errors 0 dropped 0 overruns 0 frame 0
159+ TX packets 59317 bytes 4839008 (4.8 MB)
160+ TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
161+
162+lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
163+ inet 127.0.0.1 netmask 255.0.0.0
164+ inet6 ::1 prefixlen 128 scopeid 0x10<host>
165+ loop txqueuelen 1000 (Local Loopback)
166+ RX packets 260 bytes 20092 (20.0 KB)
167+ RX errors 0 dropped 0 overruns 0 frame 0
168+ TX packets 260 bytes 20092 (20.0 KB)
169+ TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
170diff --git a/tests/data/netinfo/sample-ipaddrshow-output-down b/tests/data/netinfo/sample-ipaddrshow-output-down
171new file mode 100644
172index 0000000..cb516d6
173--- /dev/null
174+++ b/tests/data/netinfo/sample-ipaddrshow-output-down
175@@ -0,0 +1,8 @@
176+1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
177+ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
178+ inet 127.0.0.1/8 scope host lo
179+ valid_lft forever preferred_lft forever
180+ inet6 ::1/128 scope host
181+ valid_lft forever preferred_lft forever
182+44: eth0@if45: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
183+ link/ether 00:16:3e:de:51:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Subscribers

People subscribed via source and target branches