Merge ~smoser/cloud-init:fix/lxd-only-create-network-if-noexist into cloud-init:master

Proposed by Scott Moser
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)
Reviewer Review Type Date Requested Status
Chad Smith Approve
Server Team CI bot continuous-integration Approve
Ryan Harper Approve
Review via email: mp+348005@code.launchpad.net

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

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

PASSED: Continuous integration, rev:c16f9104673e1e8a1fdaa024cc3511d5ad147c17
https://jenkins.ubuntu.com/server/job/cloud-init-ci/85/
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/85/rebuild

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

PASSED: Continuous integration, rev:0cede0e8ee836f150b6382fddc551735fbae52c2
https://jenkins.ubuntu.com/server/job/cloud-init-ci/86/
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/86/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) :
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Ryan Harper (raharper) :
review: Approve
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:3df8f0f56e8cabff262cb696ab20b7db79967bfa
https://jenkins.ubuntu.com/server/job/cloud-init-ci/94/
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/94/rebuild

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

just a nit

review: Approve
Revision history for this message
Chad Smith (chad.smith) :
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:5de7fc34c8e429941cac84267d6ef5a604cddcaf
https://jenkins.ubuntu.com/server/job/cloud-init-ci/96/
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/96/rebuild

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

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Ryan Harper (raharper) :
Revision history for this message
Scott Moser (smoser) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

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

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

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

PASSED: Continuous integration, rev:63dc423b222fd53a14938597c91c8ba52a8bbecf
https://jenkins.ubuntu.com/server/job/cloud-init-ci/102/
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/102/rebuild

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

PASSED: Continuous integration, rev:01ce34e069827aa4cd0bac732acab119df90a901
https://jenkins.ubuntu.com/server/job/cloud-init-ci/103/
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/103/rebuild

review: Approve (continuous-integration)
Revision history for this message
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_18.2-83-g01ce34e0-1~bddeb_all.deb --test modules/lxd_bridge

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

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=4ce67201

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
diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py
index 09374d2..ac72ac4 100644
--- a/cloudinit/config/cc_lxd.py
+++ b/cloudinit/config/cc_lxd.py
@@ -47,11 +47,16 @@ lxd-bridge will be configured accordingly.
47 domain: <domain>47 domain: <domain>
48"""48"""
4949
50from cloudinit import log as logging
50from cloudinit import util51from cloudinit import util
51import os52import os
5253
53distros = ['ubuntu']54distros = ['ubuntu']
5455
56LOG = logging.getLogger(__name__)
57
58_DEFAULT_NETWORK_NAME = "lxdbr0"
59
5560
56def handle(name, cfg, cloud, log, args):61def handle(name, cfg, cloud, log, args):
57 # Get config62 # Get config
@@ -109,6 +114,7 @@ def handle(name, cfg, cloud, log, args):
109 # Set up lxd-bridge if bridge config is given114 # Set up lxd-bridge if bridge config is given
110 dconf_comm = "debconf-communicate"115 dconf_comm = "debconf-communicate"
111 if bridge_cfg:116 if bridge_cfg:
117 net_name = bridge_cfg.get("name", _DEFAULT_NETWORK_NAME)
112 if os.path.exists("/etc/default/lxd-bridge") \118 if os.path.exists("/etc/default/lxd-bridge") \
113 and util.which(dconf_comm):119 and util.which(dconf_comm):
114 # Bridge configured through packaging120 # Bridge configured through packaging
@@ -135,15 +141,18 @@ def handle(name, cfg, cloud, log, args):
135 else:141 else:
136 # Built-in LXD bridge support142 # Built-in LXD bridge support
137 cmd_create, cmd_attach = bridge_to_cmd(bridge_cfg)143 cmd_create, cmd_attach = bridge_to_cmd(bridge_cfg)
144 maybe_cleanup_default(
145 net_name=net_name, did_init=bool(init_cfg),
146 create=bool(cmd_create), attach=bool(cmd_attach))
138 if cmd_create:147 if cmd_create:
139 log.debug("Creating lxd bridge: %s" %148 log.debug("Creating lxd bridge: %s" %
140 " ".join(cmd_create))149 " ".join(cmd_create))
141 util.subp(cmd_create)150 _lxc(cmd_create)
142151
143 if cmd_attach:152 if cmd_attach:
144 log.debug("Setting up default lxd bridge: %s" %153 log.debug("Setting up default lxd bridge: %s" %
145 " ".join(cmd_create))154 " ".join(cmd_create))
146 util.subp(cmd_attach)155 _lxc(cmd_attach)
147156
148 elif bridge_cfg:157 elif bridge_cfg:
149 raise RuntimeError(158 raise RuntimeError(
@@ -204,10 +213,10 @@ def bridge_to_cmd(bridge_cfg):
204 if bridge_cfg.get("mode") == "none":213 if bridge_cfg.get("mode") == "none":
205 return None, None214 return None, None
206215
207 bridge_name = bridge_cfg.get("name", "lxdbr0")216 bridge_name = bridge_cfg.get("name", _DEFAULT_NETWORK_NAME)
208 cmd_create = []217 cmd_create = []
209 cmd_attach = ["lxc", "network", "attach-profile", bridge_name,218 cmd_attach = ["network", "attach-profile", bridge_name,
210 "default", "eth0", "--force-local"]219 "default", "eth0"]
211220
212 if bridge_cfg.get("mode") == "existing":221 if bridge_cfg.get("mode") == "existing":
213 return None, cmd_attach222 return None, cmd_attach
@@ -215,7 +224,7 @@ def bridge_to_cmd(bridge_cfg):
215 if bridge_cfg.get("mode") != "new":224 if bridge_cfg.get("mode") != "new":
216 raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode"))225 raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode"))
217226
218 cmd_create = ["lxc", "network", "create", bridge_name]227 cmd_create = ["network", "create", bridge_name]
219228
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"):
221 cmd_create.append("ipv4.address=%s/%s" %230 cmd_create.append("ipv4.address=%s/%s" %
@@ -247,8 +256,47 @@ def bridge_to_cmd(bridge_cfg):
247 if bridge_cfg.get("domain"):256 if bridge_cfg.get("domain"):
248 cmd_create.append("dns.domain=%s" % bridge_cfg.get("domain"))257 cmd_create.append("dns.domain=%s" % bridge_cfg.get("domain"))
249258
250 cmd_create.append("--force-local")
251
252 return cmd_create, cmd_attach259 return cmd_create, cmd_attach
253260
261
262def _lxc(cmd):
263 env = {'LC_ALL': 'C'}
264 util.subp(['lxc'] + list(cmd) + ["--force-local"], update_env=env)
265
266
267def maybe_cleanup_default(net_name, did_init, create, attach,
268 profile="default", nic_name="eth0"):
269 """Newer versions of lxc (3.0.1+) create a lxdbr0 network when
270 'lxd init --auto' is run. Older versions did not.
271
272 By removing ay that lxd-init created, we simply leave the add/attach
273 code in-tact.
274
275 https://github.com/lxc/lxd/issues/4649"""
276 if net_name != _DEFAULT_NETWORK_NAME or not did_init:
277 return
278
279 fail_assume_enoent = " failed. Assuming it did not exist."
280 succeeded = " succeeded."
281 if create:
282 msg = "Deletion of lxd network '%s'" % net_name
283 try:
284 _lxc(["network", "delete", net_name])
285 LOG.debug(msg + succeeded)
286 except util.ProcessExecutionError as e:
287 if e.exit_code != 1:
288 raise e
289 LOG.debug(msg + fail_assume_enoent)
290
291 if attach:
292 msg = "Removal of device '%s' from profile '%s'" % (nic_name, profile)
293 try:
294 _lxc(["profile", "device", "remove", profile, nic_name])
295 LOG.debug(msg + succeeded)
296 except util.ProcessExecutionError as e:
297 if e.exit_code != 1:
298 raise e
299 LOG.debug(msg + fail_assume_enoent)
300
301
254# vi: ts=4 expandtab302# vi: ts=4 expandtab
diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py
index a205498..4dd7e09 100644
--- a/tests/unittests/test_handler/test_handler_lxd.py
+++ b/tests/unittests/test_handler/test_handler_lxd.py
@@ -33,12 +33,16 @@ class TestLxd(t_help.CiTestCase):
33 cc = cloud.Cloud(ds, paths, {}, d, None)33 cc = cloud.Cloud(ds, paths, {}, d, None)
34 return cc34 return cc
3535
36 @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
36 @mock.patch("cloudinit.config.cc_lxd.util")37 @mock.patch("cloudinit.config.cc_lxd.util")
37 def test_lxd_init(self, mock_util):38 def test_lxd_init(self, mock_util, m_maybe_clean):
38 cc = self._get_cloud('ubuntu')39 cc = self._get_cloud('ubuntu')
39 mock_util.which.return_value = True40 mock_util.which.return_value = True
41 m_maybe_clean.return_value = None
40 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])42 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
41 self.assertTrue(mock_util.which.called)43 self.assertTrue(mock_util.which.called)
44 # no bridge config, so maybe_cleanup should not be called.
45 self.assertFalse(m_maybe_clean.called)
42 init_call = mock_util.subp.call_args_list[0][0][0]46 init_call = mock_util.subp.call_args_list[0][0][0]
43 self.assertEqual(init_call,47 self.assertEqual(init_call,
44 ['lxd', 'init', '--auto',48 ['lxd', 'init', '--auto',
@@ -46,32 +50,39 @@ class TestLxd(t_help.CiTestCase):
46 '--storage-backend=zfs',50 '--storage-backend=zfs',
47 '--storage-pool=poolname'])51 '--storage-pool=poolname'])
4852
53 @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
49 @mock.patch("cloudinit.config.cc_lxd.util")54 @mock.patch("cloudinit.config.cc_lxd.util")
50 def test_lxd_install(self, mock_util):55 def test_lxd_install(self, mock_util, m_maybe_clean):
51 cc = self._get_cloud('ubuntu')56 cc = self._get_cloud('ubuntu')
52 cc.distro = mock.MagicMock()57 cc.distro = mock.MagicMock()
53 mock_util.which.return_value = None58 mock_util.which.return_value = None
54 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])59 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
55 self.assertNotIn('WARN', self.logs.getvalue())60 self.assertNotIn('WARN', self.logs.getvalue())
56 self.assertTrue(cc.distro.install_packages.called)61 self.assertTrue(cc.distro.install_packages.called)
62 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
63 self.assertFalse(m_maybe_clean.called)
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]
58 self.assertEqual(sorted(install_pkg), ['lxd', 'zfs'])65 self.assertEqual(sorted(install_pkg), ['lxd', 'zfs'])
5966
67 @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
60 @mock.patch("cloudinit.config.cc_lxd.util")68 @mock.patch("cloudinit.config.cc_lxd.util")
61 def test_no_init_does_nothing(self, mock_util):69 def test_no_init_does_nothing(self, mock_util, m_maybe_clean):
62 cc = self._get_cloud('ubuntu')70 cc = self._get_cloud('ubuntu')
63 cc.distro = mock.MagicMock()71 cc.distro = mock.MagicMock()
64 cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, self.logger, [])72 cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, self.logger, [])
65 self.assertFalse(cc.distro.install_packages.called)73 self.assertFalse(cc.distro.install_packages.called)
66 self.assertFalse(mock_util.subp.called)74 self.assertFalse(mock_util.subp.called)
75 self.assertFalse(m_maybe_clean.called)
6776
77 @mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
68 @mock.patch("cloudinit.config.cc_lxd.util")78 @mock.patch("cloudinit.config.cc_lxd.util")
69 def test_no_lxd_does_nothing(self, mock_util):79 def test_no_lxd_does_nothing(self, mock_util, m_maybe_clean):
70 cc = self._get_cloud('ubuntu')80 cc = self._get_cloud('ubuntu')
71 cc.distro = mock.MagicMock()81 cc.distro = mock.MagicMock()
72 cc_lxd.handle('cc_lxd', {'package_update': True}, cc, self.logger, [])82 cc_lxd.handle('cc_lxd', {'package_update': True}, cc, self.logger, [])
73 self.assertFalse(cc.distro.install_packages.called)83 self.assertFalse(cc.distro.install_packages.called)
74 self.assertFalse(mock_util.subp.called)84 self.assertFalse(mock_util.subp.called)
85 self.assertFalse(m_maybe_clean.called)
7586
76 def test_lxd_debconf_new_full(self):87 def test_lxd_debconf_new_full(self):
77 data = {"mode": "new",88 data = {"mode": "new",
@@ -147,14 +158,13 @@ class TestLxd(t_help.CiTestCase):
147 "domain": "lxd"}158 "domain": "lxd"}
148 self.assertEqual(159 self.assertEqual(
149 cc_lxd.bridge_to_cmd(data),160 cc_lxd.bridge_to_cmd(data),
150 (["lxc", "network", "create", "testbr0",161 (["network", "create", "testbr0",
151 "ipv4.address=10.0.8.1/24", "ipv4.nat=true",162 "ipv4.address=10.0.8.1/24", "ipv4.nat=true",
152 "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254",163 "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254",
153 "ipv6.address=fd98:9e0:3744::1/64",164 "ipv6.address=fd98:9e0:3744::1/64",
154 "ipv6.nat=true", "dns.domain=lxd",165 "ipv6.nat=true", "dns.domain=lxd"],
155 "--force-local"],166 ["network", "attach-profile",
156 ["lxc", "network", "attach-profile",167 "testbr0", "default", "eth0"]))
157 "testbr0", "default", "eth0", "--force-local"]))
158168
159 def test_lxd_cmd_new_partial(self):169 def test_lxd_cmd_new_partial(self):
160 data = {"mode": "new",170 data = {"mode": "new",
@@ -163,19 +173,18 @@ class TestLxd(t_help.CiTestCase):
163 "ipv6_nat": "true"}173 "ipv6_nat": "true"}
164 self.assertEqual(174 self.assertEqual(
165 cc_lxd.bridge_to_cmd(data),175 cc_lxd.bridge_to_cmd(data),
166 (["lxc", "network", "create", "lxdbr0", "ipv4.address=none",176 (["network", "create", "lxdbr0", "ipv4.address=none",
167 "ipv6.address=fd98:9e0:3744::1/64", "ipv6.nat=true",177 "ipv6.address=fd98:9e0:3744::1/64", "ipv6.nat=true"],
168 "--force-local"],178 ["network", "attach-profile",
169 ["lxc", "network", "attach-profile",179 "lxdbr0", "default", "eth0"]))
170 "lxdbr0", "default", "eth0", "--force-local"]))
171180
172 def test_lxd_cmd_existing(self):181 def test_lxd_cmd_existing(self):
173 data = {"mode": "existing",182 data = {"mode": "existing",
174 "name": "testbr0"}183 "name": "testbr0"}
175 self.assertEqual(184 self.assertEqual(
176 cc_lxd.bridge_to_cmd(data),185 cc_lxd.bridge_to_cmd(data),
177 (None, ["lxc", "network", "attach-profile",186 (None, ["network", "attach-profile",
178 "testbr0", "default", "eth0", "--force-local"]))187 "testbr0", "default", "eth0"]))
179188
180 def test_lxd_cmd_none(self):189 def test_lxd_cmd_none(self):
181 data = {"mode": "none"}190 data = {"mode": "none"}
@@ -183,4 +192,43 @@ class TestLxd(t_help.CiTestCase):
183 cc_lxd.bridge_to_cmd(data),192 cc_lxd.bridge_to_cmd(data),
184 (None, None))193 (None, None))
185194
195
196class TestLxdMaybeCleanupDefault(t_help.CiTestCase):
197 """Test the implementation of maybe_cleanup_default."""
198
199 defnet = cc_lxd._DEFAULT_NETWORK_NAME
200
201 @mock.patch("cloudinit.config.cc_lxd._lxc")
202 def test_network_other_than_default_not_deleted(self, m_lxc):
203 """deletion or removal should only occur if bridge is default."""
204 cc_lxd.maybe_cleanup_default(
205 net_name="lxdbr1", did_init=True, create=True, attach=True)
206 m_lxc.assert_not_called()
207
208 @mock.patch("cloudinit.config.cc_lxd._lxc")
209 def test_did_init_false_does_not_delete(self, m_lxc):
210 """deletion or removal should only occur if did_init is True."""
211 cc_lxd.maybe_cleanup_default(
212 net_name=self.defnet, did_init=False, create=True, attach=True)
213 m_lxc.assert_not_called()
214
215 @mock.patch("cloudinit.config.cc_lxd._lxc")
216 def test_network_deleted_if_create_true(self, m_lxc):
217 """deletion of network should occur if create is True."""
218 cc_lxd.maybe_cleanup_default(
219 net_name=self.defnet, did_init=True, create=True, attach=False)
220 m_lxc.assert_called_once_with(["network", "delete", self.defnet])
221
222 @mock.patch("cloudinit.config.cc_lxd._lxc")
223 def test_device_removed_if_attach_true(self, m_lxc):
224 """deletion of network should occur if create is True."""
225 nic_name = "my_nic"
226 profile = "my_profile"
227 cc_lxd.maybe_cleanup_default(
228 net_name=self.defnet, did_init=True, create=False, attach=True,
229 profile=profile, nic_name=nic_name)
230 m_lxc.assert_called_once_with(
231 ["profile", "device", "remove", profile, nic_name])
232
233
186# vi: ts=4 expandtab234# vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches