Merge ~smoser/cloud-init:fix/lxd-only-create-network-if-noexist into cloud-init:master
- Git
- lp:~smoser/cloud-init
- fix/lxd-only-create-network-if-noexist
- Merge into master
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Chad Smith | ||||
Approved revision: | 01ce34e069827aa4cd0bac732acab119df90a901 | ||||
Merge reported by: | Chad Smith | ||||
Merged at revision: | 4ce6720104ec92d8d7c5aa993bf7ec405a2f53db | ||||
Proposed branch: | ~smoser/cloud-init:fix/lxd-only-create-network-if-noexist | ||||
Merge into: | cloud-init:master | ||||
Diff against target: |
277 lines (+120/-24) 2 files modified
cloudinit/config/cc_lxd.py (+56/-8) tests/unittests/test_handler/test_handler_lxd.py (+64/-16) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chad Smith | Approve | ||
Server Team CI bot | continuous-integration | Approve | |
Ryan Harper | Approve | ||
Review via email:
|
Commit message
lxd: Delete default network and detach device if lxd-init created them.
Newer versions (3.0.1+) of lxd create the 'lxdbr0' network when
'lxd init --auto' is invoked.
When cloud-init is given a network configuration to pass on to
lxc and that config had no name specified or 'lxdbr0', then cloud-init
would fail to create the network as it already exists.
Similarly, we need to remove the device from the default profile
so that the attach code can work.
Also, add a _lxc method and use it to make sure we're getting the
--force-local flag everywhere.
LP: #1776958
Description of the change
see commit message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ryan Harper (raharper) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:0cede0e8ee8
https:/
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chad Smith (chad.smith) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Scott Moser (smoser) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ryan Harper (raharper) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Scott Moser (smoser) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:3df8f0f56e8
https:/
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chad Smith (chad.smith) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Scott Moser (smoser) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:5de7fc34c8e
https:/
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:5164e07ffad
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ryan Harper (raharper) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Scott Moser (smoser) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:fe884295ba8
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:63dc423b222
https:/
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:01ce34e0698
https:/
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chad Smith (chad.smith) wrote : | # |
Good rework, validated on xenial and cosmic on Ec2
tox -e citest -- run --os-name xenial --platform ec2 --preserve-data --data-dir results --verbose --deb cloud-init_
2018-06-16 01:58:09,290 - tests.cloud_tests - DEBUG -
---- Verify summarized results:
Platform: ec2
Distro: xenial
test modules passed:1 tests failed:0
Distro: cosmic
test modules passed:1 tests failed:0
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Chad Smith (chad.smith) wrote : | # |
An upstream commit landed for this bug.
To view that commit see the following URL:
https:/
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
1 | diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py | |||
2 | index 09374d2..ac72ac4 100644 | |||
3 | --- a/cloudinit/config/cc_lxd.py | |||
4 | +++ b/cloudinit/config/cc_lxd.py | |||
5 | @@ -47,11 +47,16 @@ lxd-bridge will be configured accordingly. | |||
6 | 47 | domain: <domain> | 47 | domain: <domain> |
7 | 48 | """ | 48 | """ |
8 | 49 | 49 | ||
9 | 50 | from cloudinit import log as logging | ||
10 | 50 | from cloudinit import util | 51 | from cloudinit import util |
11 | 51 | import os | 52 | import os |
12 | 52 | 53 | ||
13 | 53 | distros = ['ubuntu'] | 54 | distros = ['ubuntu'] |
14 | 54 | 55 | ||
15 | 56 | LOG = logging.getLogger(__name__) | ||
16 | 57 | |||
17 | 58 | _DEFAULT_NETWORK_NAME = "lxdbr0" | ||
18 | 59 | |||
19 | 55 | 60 | ||
20 | 56 | def handle(name, cfg, cloud, log, args): | 61 | def handle(name, cfg, cloud, log, args): |
21 | 57 | # Get config | 62 | # Get config |
22 | @@ -109,6 +114,7 @@ def handle(name, cfg, cloud, log, args): | |||
23 | 109 | # Set up lxd-bridge if bridge config is given | 114 | # Set up lxd-bridge if bridge config is given |
24 | 110 | dconf_comm = "debconf-communicate" | 115 | dconf_comm = "debconf-communicate" |
25 | 111 | if bridge_cfg: | 116 | if bridge_cfg: |
26 | 117 | net_name = bridge_cfg.get("name", _DEFAULT_NETWORK_NAME) | ||
27 | 112 | if os.path.exists("/etc/default/lxd-bridge") \ | 118 | if os.path.exists("/etc/default/lxd-bridge") \ |
28 | 113 | and util.which(dconf_comm): | 119 | and util.which(dconf_comm): |
29 | 114 | # Bridge configured through packaging | 120 | # Bridge configured through packaging |
30 | @@ -135,15 +141,18 @@ def handle(name, cfg, cloud, log, args): | |||
31 | 135 | else: | 141 | else: |
32 | 136 | # Built-in LXD bridge support | 142 | # Built-in LXD bridge support |
33 | 137 | cmd_create, cmd_attach = bridge_to_cmd(bridge_cfg) | 143 | cmd_create, cmd_attach = bridge_to_cmd(bridge_cfg) |
34 | 144 | maybe_cleanup_default( | ||
35 | 145 | net_name=net_name, did_init=bool(init_cfg), | ||
36 | 146 | create=bool(cmd_create), attach=bool(cmd_attach)) | ||
37 | 138 | if cmd_create: | 147 | if cmd_create: |
38 | 139 | log.debug("Creating lxd bridge: %s" % | 148 | log.debug("Creating lxd bridge: %s" % |
39 | 140 | " ".join(cmd_create)) | 149 | " ".join(cmd_create)) |
41 | 141 | util.subp(cmd_create) | 150 | _lxc(cmd_create) |
42 | 142 | 151 | ||
43 | 143 | if cmd_attach: | 152 | if cmd_attach: |
44 | 144 | log.debug("Setting up default lxd bridge: %s" % | 153 | log.debug("Setting up default lxd bridge: %s" % |
45 | 145 | " ".join(cmd_create)) | 154 | " ".join(cmd_create)) |
47 | 146 | util.subp(cmd_attach) | 155 | _lxc(cmd_attach) |
48 | 147 | 156 | ||
49 | 148 | elif bridge_cfg: | 157 | elif bridge_cfg: |
50 | 149 | raise RuntimeError( | 158 | raise RuntimeError( |
51 | @@ -204,10 +213,10 @@ def bridge_to_cmd(bridge_cfg): | |||
52 | 204 | if bridge_cfg.get("mode") == "none": | 213 | if bridge_cfg.get("mode") == "none": |
53 | 205 | return None, None | 214 | return None, None |
54 | 206 | 215 | ||
56 | 207 | bridge_name = bridge_cfg.get("name", "lxdbr0") | 216 | bridge_name = bridge_cfg.get("name", _DEFAULT_NETWORK_NAME) |
57 | 208 | cmd_create = [] | 217 | cmd_create = [] |
60 | 209 | cmd_attach = ["lxc", "network", "attach-profile", bridge_name, | 218 | cmd_attach = ["network", "attach-profile", bridge_name, |
61 | 210 | "default", "eth0", "--force-local"] | 219 | "default", "eth0"] |
62 | 211 | 220 | ||
63 | 212 | if bridge_cfg.get("mode") == "existing": | 221 | if bridge_cfg.get("mode") == "existing": |
64 | 213 | return None, cmd_attach | 222 | return None, cmd_attach |
65 | @@ -215,7 +224,7 @@ def bridge_to_cmd(bridge_cfg): | |||
66 | 215 | if bridge_cfg.get("mode") != "new": | 224 | if bridge_cfg.get("mode") != "new": |
67 | 216 | raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) | 225 | raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) |
68 | 217 | 226 | ||
70 | 218 | cmd_create = ["lxc", "network", "create", bridge_name] | 227 | cmd_create = ["network", "create", bridge_name] |
71 | 219 | 228 | ||
72 | 220 | if bridge_cfg.get("ipv4_address") and bridge_cfg.get("ipv4_netmask"): | 229 | if bridge_cfg.get("ipv4_address") and bridge_cfg.get("ipv4_netmask"): |
73 | 221 | cmd_create.append("ipv4.address=%s/%s" % | 230 | cmd_create.append("ipv4.address=%s/%s" % |
74 | @@ -247,8 +256,47 @@ def bridge_to_cmd(bridge_cfg): | |||
75 | 247 | if bridge_cfg.get("domain"): | 256 | if bridge_cfg.get("domain"): |
76 | 248 | cmd_create.append("dns.domain=%s" % bridge_cfg.get("domain")) | 257 | cmd_create.append("dns.domain=%s" % bridge_cfg.get("domain")) |
77 | 249 | 258 | ||
78 | 250 | cmd_create.append("--force-local") | ||
79 | 251 | |||
80 | 252 | return cmd_create, cmd_attach | 259 | return cmd_create, cmd_attach |
81 | 253 | 260 | ||
82 | 261 | |||
83 | 262 | def _lxc(cmd): | ||
84 | 263 | env = {'LC_ALL': 'C'} | ||
85 | 264 | util.subp(['lxc'] + list(cmd) + ["--force-local"], update_env=env) | ||
86 | 265 | |||
87 | 266 | |||
88 | 267 | def maybe_cleanup_default(net_name, did_init, create, attach, | ||
89 | 268 | profile="default", nic_name="eth0"): | ||
90 | 269 | """Newer versions of lxc (3.0.1+) create a lxdbr0 network when | ||
91 | 270 | 'lxd init --auto' is run. Older versions did not. | ||
92 | 271 | |||
93 | 272 | By removing ay that lxd-init created, we simply leave the add/attach | ||
94 | 273 | code in-tact. | ||
95 | 274 | |||
96 | 275 | https://github.com/lxc/lxd/issues/4649""" | ||
97 | 276 | if net_name != _DEFAULT_NETWORK_NAME or not did_init: | ||
98 | 277 | return | ||
99 | 278 | |||
100 | 279 | fail_assume_enoent = " failed. Assuming it did not exist." | ||
101 | 280 | succeeded = " succeeded." | ||
102 | 281 | if create: | ||
103 | 282 | msg = "Deletion of lxd network '%s'" % net_name | ||
104 | 283 | try: | ||
105 | 284 | _lxc(["network", "delete", net_name]) | ||
106 | 285 | LOG.debug(msg + succeeded) | ||
107 | 286 | except util.ProcessExecutionError as e: | ||
108 | 287 | if e.exit_code != 1: | ||
109 | 288 | raise e | ||
110 | 289 | LOG.debug(msg + fail_assume_enoent) | ||
111 | 290 | |||
112 | 291 | if attach: | ||
113 | 292 | msg = "Removal of device '%s' from profile '%s'" % (nic_name, profile) | ||
114 | 293 | try: | ||
115 | 294 | _lxc(["profile", "device", "remove", profile, nic_name]) | ||
116 | 295 | LOG.debug(msg + succeeded) | ||
117 | 296 | except util.ProcessExecutionError as e: | ||
118 | 297 | if e.exit_code != 1: | ||
119 | 298 | raise e | ||
120 | 299 | LOG.debug(msg + fail_assume_enoent) | ||
121 | 300 | |||
122 | 301 | |||
123 | 254 | # vi: ts=4 expandtab | 302 | # vi: ts=4 expandtab |
124 | diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py | |||
125 | index a205498..4dd7e09 100644 | |||
126 | --- a/tests/unittests/test_handler/test_handler_lxd.py | |||
127 | +++ b/tests/unittests/test_handler/test_handler_lxd.py | |||
128 | @@ -33,12 +33,16 @@ class TestLxd(t_help.CiTestCase): | |||
129 | 33 | cc = cloud.Cloud(ds, paths, {}, d, None) | 33 | cc = cloud.Cloud(ds, paths, {}, d, None) |
130 | 34 | return cc | 34 | return cc |
131 | 35 | 35 | ||
132 | 36 | @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default") | ||
133 | 36 | @mock.patch("cloudinit.config.cc_lxd.util") | 37 | @mock.patch("cloudinit.config.cc_lxd.util") |
135 | 37 | def test_lxd_init(self, mock_util): | 38 | def test_lxd_init(self, mock_util, m_maybe_clean): |
136 | 38 | cc = self._get_cloud('ubuntu') | 39 | cc = self._get_cloud('ubuntu') |
137 | 39 | mock_util.which.return_value = True | 40 | mock_util.which.return_value = True |
138 | 41 | m_maybe_clean.return_value = None | ||
139 | 40 | cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, []) | 42 | cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, []) |
140 | 41 | self.assertTrue(mock_util.which.called) | 43 | self.assertTrue(mock_util.which.called) |
141 | 44 | # no bridge config, so maybe_cleanup should not be called. | ||
142 | 45 | self.assertFalse(m_maybe_clean.called) | ||
143 | 42 | init_call = mock_util.subp.call_args_list[0][0][0] | 46 | init_call = mock_util.subp.call_args_list[0][0][0] |
144 | 43 | self.assertEqual(init_call, | 47 | self.assertEqual(init_call, |
145 | 44 | ['lxd', 'init', '--auto', | 48 | ['lxd', 'init', '--auto', |
146 | @@ -46,32 +50,39 @@ class TestLxd(t_help.CiTestCase): | |||
147 | 46 | '--storage-backend=zfs', | 50 | '--storage-backend=zfs', |
148 | 47 | '--storage-pool=poolname']) | 51 | '--storage-pool=poolname']) |
149 | 48 | 52 | ||
150 | 53 | @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default") | ||
151 | 49 | @mock.patch("cloudinit.config.cc_lxd.util") | 54 | @mock.patch("cloudinit.config.cc_lxd.util") |
153 | 50 | def test_lxd_install(self, mock_util): | 55 | def test_lxd_install(self, mock_util, m_maybe_clean): |
154 | 51 | cc = self._get_cloud('ubuntu') | 56 | cc = self._get_cloud('ubuntu') |
155 | 52 | cc.distro = mock.MagicMock() | 57 | cc.distro = mock.MagicMock() |
156 | 53 | mock_util.which.return_value = None | 58 | mock_util.which.return_value = None |
157 | 54 | cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, []) | 59 | cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, []) |
158 | 55 | self.assertNotIn('WARN', self.logs.getvalue()) | 60 | self.assertNotIn('WARN', self.logs.getvalue()) |
159 | 56 | self.assertTrue(cc.distro.install_packages.called) | 61 | self.assertTrue(cc.distro.install_packages.called) |
160 | 62 | cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, []) | ||
161 | 63 | self.assertFalse(m_maybe_clean.called) | ||
162 | 57 | install_pkg = cc.distro.install_packages.call_args_list[0][0][0] | 64 | install_pkg = cc.distro.install_packages.call_args_list[0][0][0] |
163 | 58 | self.assertEqual(sorted(install_pkg), ['lxd', 'zfs']) | 65 | self.assertEqual(sorted(install_pkg), ['lxd', 'zfs']) |
164 | 59 | 66 | ||
165 | 67 | @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default") | ||
166 | 60 | @mock.patch("cloudinit.config.cc_lxd.util") | 68 | @mock.patch("cloudinit.config.cc_lxd.util") |
168 | 61 | def test_no_init_does_nothing(self, mock_util): | 69 | def test_no_init_does_nothing(self, mock_util, m_maybe_clean): |
169 | 62 | cc = self._get_cloud('ubuntu') | 70 | cc = self._get_cloud('ubuntu') |
170 | 63 | cc.distro = mock.MagicMock() | 71 | cc.distro = mock.MagicMock() |
171 | 64 | cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, self.logger, []) | 72 | cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, self.logger, []) |
172 | 65 | self.assertFalse(cc.distro.install_packages.called) | 73 | self.assertFalse(cc.distro.install_packages.called) |
173 | 66 | self.assertFalse(mock_util.subp.called) | 74 | self.assertFalse(mock_util.subp.called) |
174 | 75 | self.assertFalse(m_maybe_clean.called) | ||
175 | 67 | 76 | ||
176 | 77 | @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default") | ||
177 | 68 | @mock.patch("cloudinit.config.cc_lxd.util") | 78 | @mock.patch("cloudinit.config.cc_lxd.util") |
179 | 69 | def test_no_lxd_does_nothing(self, mock_util): | 79 | def test_no_lxd_does_nothing(self, mock_util, m_maybe_clean): |
180 | 70 | cc = self._get_cloud('ubuntu') | 80 | cc = self._get_cloud('ubuntu') |
181 | 71 | cc.distro = mock.MagicMock() | 81 | cc.distro = mock.MagicMock() |
182 | 72 | cc_lxd.handle('cc_lxd', {'package_update': True}, cc, self.logger, []) | 82 | cc_lxd.handle('cc_lxd', {'package_update': True}, cc, self.logger, []) |
183 | 73 | self.assertFalse(cc.distro.install_packages.called) | 83 | self.assertFalse(cc.distro.install_packages.called) |
184 | 74 | self.assertFalse(mock_util.subp.called) | 84 | self.assertFalse(mock_util.subp.called) |
185 | 85 | self.assertFalse(m_maybe_clean.called) | ||
186 | 75 | 86 | ||
187 | 76 | def test_lxd_debconf_new_full(self): | 87 | def test_lxd_debconf_new_full(self): |
188 | 77 | data = {"mode": "new", | 88 | data = {"mode": "new", |
189 | @@ -147,14 +158,13 @@ class TestLxd(t_help.CiTestCase): | |||
190 | 147 | "domain": "lxd"} | 158 | "domain": "lxd"} |
191 | 148 | self.assertEqual( | 159 | self.assertEqual( |
192 | 149 | cc_lxd.bridge_to_cmd(data), | 160 | cc_lxd.bridge_to_cmd(data), |
194 | 150 | (["lxc", "network", "create", "testbr0", | 161 | (["network", "create", "testbr0", |
195 | 151 | "ipv4.address=10.0.8.1/24", "ipv4.nat=true", | 162 | "ipv4.address=10.0.8.1/24", "ipv4.nat=true", |
196 | 152 | "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254", | 163 | "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254", |
197 | 153 | "ipv6.address=fd98:9e0:3744::1/64", | 164 | "ipv6.address=fd98:9e0:3744::1/64", |
202 | 154 | "ipv6.nat=true", "dns.domain=lxd", | 165 | "ipv6.nat=true", "dns.domain=lxd"], |
203 | 155 | "--force-local"], | 166 | ["network", "attach-profile", |
204 | 156 | ["lxc", "network", "attach-profile", | 167 | "testbr0", "default", "eth0"])) |
201 | 157 | "testbr0", "default", "eth0", "--force-local"])) | ||
205 | 158 | 168 | ||
206 | 159 | def test_lxd_cmd_new_partial(self): | 169 | def test_lxd_cmd_new_partial(self): |
207 | 160 | data = {"mode": "new", | 170 | data = {"mode": "new", |
208 | @@ -163,19 +173,18 @@ class TestLxd(t_help.CiTestCase): | |||
209 | 163 | "ipv6_nat": "true"} | 173 | "ipv6_nat": "true"} |
210 | 164 | self.assertEqual( | 174 | self.assertEqual( |
211 | 165 | cc_lxd.bridge_to_cmd(data), | 175 | cc_lxd.bridge_to_cmd(data), |
217 | 166 | (["lxc", "network", "create", "lxdbr0", "ipv4.address=none", | 176 | (["network", "create", "lxdbr0", "ipv4.address=none", |
218 | 167 | "ipv6.address=fd98:9e0:3744::1/64", "ipv6.nat=true", | 177 | "ipv6.address=fd98:9e0:3744::1/64", "ipv6.nat=true"], |
219 | 168 | "--force-local"], | 178 | ["network", "attach-profile", |
220 | 169 | ["lxc", "network", "attach-profile", | 179 | "lxdbr0", "default", "eth0"])) |
216 | 170 | "lxdbr0", "default", "eth0", "--force-local"])) | ||
221 | 171 | 180 | ||
222 | 172 | def test_lxd_cmd_existing(self): | 181 | def test_lxd_cmd_existing(self): |
223 | 173 | data = {"mode": "existing", | 182 | data = {"mode": "existing", |
224 | 174 | "name": "testbr0"} | 183 | "name": "testbr0"} |
225 | 175 | self.assertEqual( | 184 | self.assertEqual( |
226 | 176 | cc_lxd.bridge_to_cmd(data), | 185 | cc_lxd.bridge_to_cmd(data), |
229 | 177 | (None, ["lxc", "network", "attach-profile", | 186 | (None, ["network", "attach-profile", |
230 | 178 | "testbr0", "default", "eth0", "--force-local"])) | 187 | "testbr0", "default", "eth0"])) |
231 | 179 | 188 | ||
232 | 180 | def test_lxd_cmd_none(self): | 189 | def test_lxd_cmd_none(self): |
233 | 181 | data = {"mode": "none"} | 190 | data = {"mode": "none"} |
234 | @@ -183,4 +192,43 @@ class TestLxd(t_help.CiTestCase): | |||
235 | 183 | cc_lxd.bridge_to_cmd(data), | 192 | cc_lxd.bridge_to_cmd(data), |
236 | 184 | (None, None)) | 193 | (None, None)) |
237 | 185 | 194 | ||
238 | 195 | |||
239 | 196 | class TestLxdMaybeCleanupDefault(t_help.CiTestCase): | ||
240 | 197 | """Test the implementation of maybe_cleanup_default.""" | ||
241 | 198 | |||
242 | 199 | defnet = cc_lxd._DEFAULT_NETWORK_NAME | ||
243 | 200 | |||
244 | 201 | @mock.patch("cloudinit.config.cc_lxd._lxc") | ||
245 | 202 | def test_network_other_than_default_not_deleted(self, m_lxc): | ||
246 | 203 | """deletion or removal should only occur if bridge is default.""" | ||
247 | 204 | cc_lxd.maybe_cleanup_default( | ||
248 | 205 | net_name="lxdbr1", did_init=True, create=True, attach=True) | ||
249 | 206 | m_lxc.assert_not_called() | ||
250 | 207 | |||
251 | 208 | @mock.patch("cloudinit.config.cc_lxd._lxc") | ||
252 | 209 | def test_did_init_false_does_not_delete(self, m_lxc): | ||
253 | 210 | """deletion or removal should only occur if did_init is True.""" | ||
254 | 211 | cc_lxd.maybe_cleanup_default( | ||
255 | 212 | net_name=self.defnet, did_init=False, create=True, attach=True) | ||
256 | 213 | m_lxc.assert_not_called() | ||
257 | 214 | |||
258 | 215 | @mock.patch("cloudinit.config.cc_lxd._lxc") | ||
259 | 216 | def test_network_deleted_if_create_true(self, m_lxc): | ||
260 | 217 | """deletion of network should occur if create is True.""" | ||
261 | 218 | cc_lxd.maybe_cleanup_default( | ||
262 | 219 | net_name=self.defnet, did_init=True, create=True, attach=False) | ||
263 | 220 | m_lxc.assert_called_once_with(["network", "delete", self.defnet]) | ||
264 | 221 | |||
265 | 222 | @mock.patch("cloudinit.config.cc_lxd._lxc") | ||
266 | 223 | def test_device_removed_if_attach_true(self, m_lxc): | ||
267 | 224 | """deletion of network should occur if create is True.""" | ||
268 | 225 | nic_name = "my_nic" | ||
269 | 226 | profile = "my_profile" | ||
270 | 227 | cc_lxd.maybe_cleanup_default( | ||
271 | 228 | net_name=self.defnet, did_init=True, create=False, attach=True, | ||
272 | 229 | profile=profile, nic_name=nic_name) | ||
273 | 230 | m_lxc.assert_called_once_with( | ||
274 | 231 | ["profile", "device", "remove", profile, nic_name]) | ||
275 | 232 | |||
276 | 233 | |||
277 | 186 | # vi: ts=4 expandtab | 234 | # vi: ts=4 expandtab |
PASSED: Continuous integration, rev:c16f9104673 e1e8a1fdaa024cc 3511d5ad147c17 /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 85/
https:/
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: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 85/rebuild
https:/