Merge ~smoser/cloud-init:bug/1675576-netplan-delete-builtin into cloud-init:master

Proposed by Scott Moser on 2017-03-30
Status: Merged
Merged at revision: d23543eb206326a53a59d86afba862edbd02c231
Proposed branch: ~smoser/cloud-init:bug/1675576-netplan-delete-builtin
Merge into: cloud-init:master
Diff against target: 162 lines (+106/-1)
2 files modified
cloudinit/net/netplan.py (+40/-0)
tests/unittests/test_net.py (+66/-1)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve on 2017-03-30
Ryan Harper 2017-03-30 Approve on 2017-03-30
Review via email: mp+321471@code.launchpad.net

Commit message

net: in netplan renderer delete known image-builtin content.

When rendering network configuration to netplan, remove known
"builtin" configurations. The specific example here is Ubuntu Core
that has netplan configuration in etc/netplan/00-snapd-config.yaml.

We also delete the derived files since netplan will have created
these derived files in its generator that runs well before cloud-init.

LP: #1675576

To post a comment you must log in.
Ryan Harper (raharper) wrote :

Looks good, noted some leftover print statements that likely need removed or converted to LOG.debug()

review: Needs Fixing
Ryan Harper (raharper) wrote :

Thanks

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py
2index 7444ae3..825fe83 100644
3--- a/cloudinit/net/netplan.py
4+++ b/cloudinit/net/netplan.py
5@@ -10,6 +10,21 @@ from cloudinit import log as logging
6 from cloudinit import util
7 from cloudinit.net import SYS_CLASS_NET, get_devicelist
8
9+KNOWN_SNAPD_CONFIG = b"""\
10+# This is the initial network config.
11+# It can be overwritten by cloud-init or console-conf.
12+network:
13+ version: 2
14+ ethernets:
15+ all-en:
16+ match:
17+ name: "en*"
18+ dhcp4: true
19+ all-eth:
20+ match:
21+ name: "eth*"
22+ dhcp4: true
23+"""
24
25 LOG = logging.getLogger(__name__)
26 NET_CONFIG_TO_V2 = {
27@@ -154,6 +169,28 @@ def _extract_bond_slaves_by_name(interfaces, entry, bond_master):
28 entry.update({'interfaces': bond_slave_names})
29
30
31+def _clean_default(target=None):
32+ # clean out any known default files and derived files in target
33+ # LP: #1675576
34+ tpath = util.target_path(target, "etc/netplan/00-snapd-config.yaml")
35+ if not os.path.isfile(tpath):
36+ return
37+ content = util.load_file(tpath, decode=False)
38+ if content != KNOWN_SNAPD_CONFIG:
39+ return
40+
41+ derived = [util.target_path(target, f) for f in (
42+ 'run/systemd/network/10-netplan-all-en.network',
43+ 'run/systemd/network/10-netplan-all-eth.network',
44+ 'run/systemd/generator/netplan.stamp')]
45+ existing = [f for f in derived if os.path.isfile(f)]
46+ LOG.debug("removing known config '%s' and derived existing files: %s",
47+ tpath, existing)
48+
49+ for f in [tpath] + existing:
50+ os.unlink(f)
51+
52+
53 class Renderer(renderer.Renderer):
54 """Renders network information in a /etc/netplan/network.yaml format."""
55
56@@ -166,6 +203,7 @@ class Renderer(renderer.Renderer):
57 'etc/netplan/50-cloud-init.yaml')
58 self.netplan_header = config.get('netplan_header', None)
59 self._postcmds = config.get('postcmds', False)
60+ self.clean_default = config.get('clean_default', True)
61
62 def render_network_state(self, target, network_state):
63 # check network state for version
64@@ -182,6 +220,8 @@ class Renderer(renderer.Renderer):
65 header += "\n"
66 util.write_file(fpnplan, header + content)
67
68+ if self.clean_default:
69+ _clean_default(target=target)
70 self._netplan_generate(run=self._postcmds)
71 self._net_setup_link(run=self._postcmds)
72
73diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
74index 4f07d80..bfd04ba 100644
75--- a/tests/unittests/test_net.py
76+++ b/tests/unittests/test_net.py
77@@ -974,12 +974,14 @@ iface eth0 inet dhcp
78
79 class TestNetplanNetRendering(CiTestCase):
80
81+ @mock.patch("cloudinit.net.netplan._clean_default")
82 @mock.patch("cloudinit.net.sys_dev_path")
83 @mock.patch("cloudinit.net.read_sys_net")
84 @mock.patch("cloudinit.net.get_devicelist")
85 def test_default_generation(self, mock_get_devicelist,
86 mock_read_sys_net,
87- mock_sys_dev_path):
88+ mock_sys_dev_path,
89+ mock_clean_default):
90 tmp_dir = self.tmp_dir()
91 _setup_test(tmp_dir, mock_get_devicelist,
92 mock_read_sys_net, mock_sys_dev_path)
93@@ -1013,6 +1015,69 @@ network:
94 set-name: eth1000
95 """
96 self.assertEqual(expected.lstrip(), contents.lstrip())
97+ self.assertEqual(1, mock_clean_default.call_count)
98+
99+
100+class TestNetplanCleanDefault(CiTestCase):
101+ snapd_known_path = 'etc/netplan/00-snapd-config.yaml'
102+ snapd_known_content = textwrap.dedent("""\
103+ # This is the initial network config.
104+ # It can be overwritten by cloud-init or console-conf.
105+ network:
106+ version: 2
107+ ethernets:
108+ all-en:
109+ match:
110+ name: "en*"
111+ dhcp4: true
112+ all-eth:
113+ match:
114+ name: "eth*"
115+ dhcp4: true
116+ """)
117+ stub_known = {
118+ 'run/systemd/network/10-netplan-all-en.network': 'foo-en',
119+ 'run/systemd/network/10-netplan-all-eth.network': 'foo-eth',
120+ 'run/systemd/generator/netplan.stamp': 'stamp',
121+ }
122+
123+ def test_clean_known_config_cleaned(self):
124+ content = {self.snapd_known_path: self.snapd_known_content, }
125+ content.update(self.stub_known)
126+ tmpd = self.tmp_dir()
127+ files = sorted(populate_dir(tmpd, content))
128+ netplan._clean_default(target=tmpd)
129+ found = [t for t in files if os.path.exists(t)]
130+ self.assertEqual([], found)
131+
132+ def test_clean_unknown_config_not_cleaned(self):
133+ content = {self.snapd_known_path: self.snapd_known_content, }
134+ content.update(self.stub_known)
135+ content[self.snapd_known_path] += "# user put a comment\n"
136+ tmpd = self.tmp_dir()
137+ files = sorted(populate_dir(tmpd, content))
138+ netplan._clean_default(target=tmpd)
139+ found = [t for t in files if os.path.exists(t)]
140+ self.assertEqual(files, found)
141+
142+ def test_clean_known_config_cleans_only_expected(self):
143+ astamp = "run/systemd/generator/another.stamp"
144+ anet = "run/systemd/network/10-netplan-all-lo.network"
145+ ayaml = "etc/netplan/01-foo-config.yaml"
146+ content = {
147+ self.snapd_known_path: self.snapd_known_content,
148+ astamp: "stamp",
149+ anet: "network",
150+ ayaml: "yaml",
151+ }
152+ content.update(self.stub_known)
153+
154+ tmpd = self.tmp_dir()
155+ files = sorted(populate_dir(tmpd, content))
156+ netplan._clean_default(target=tmpd)
157+ found = [t for t in files if os.path.exists(t)]
158+ expected = [util.target_path(tmpd, f) for f in (astamp, anet, ayaml)]
159+ self.assertEqual(sorted(expected), found)
160
161
162 class TestNetplanPostcommands(CiTestCase):

Subscribers

People subscribed via source and target branches