Merge lp:~wesley-wiedenmeier/cloud-init/lxd-init into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Scott Moser
Status: Merged
Merged at revision: 1163
Proposed branch: lp:~wesley-wiedenmeier/cloud-init/lxd-init
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 183 lines (+147/-0)
5 files modified
ChangeLog (+1/-0)
cloudinit/config/cc_lxd.py (+66/-0)
config/cloud.cfg (+1/-0)
doc/examples/cloud-config-lxd.txt (+21/-0)
tests/unittests/test_handler/test_handler_lxd.py (+58/-0)
To merge this branch: bzr merge lp:~wesley-wiedenmeier/cloud-init/lxd-init
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+285018@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Wesley,

Thanks.

Please add a 'doc' in
 doc/examples/cloud-config-lxd.txt

like the other files there.

see inline comments

1159. By Wesley Wiedenmeier

Added example cc_lxd config

1160. By Wesley Wiedenmeier

 - Ensure that lxd is installed before running lxd init.
 - Handle init cfg separately from main cfg to allow multiple sections under lxd
   config to be handled independantly.
 - Check for properly formatted lxd init cfg

1161. By Wesley Wiedenmeier

Use mock in test_handler_lxd.py and add test for lxd installation

1162. By Wesley Wiedenmeier

Merge from trunk and resolve text conflict in ChangeLog

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ChangeLog'
--- ChangeLog 2016-02-04 22:11:13 +0000
+++ ChangeLog 2016-02-05 01:21:21 +0000
@@ -72,6 +72,7 @@
72 - systemd/power_state: fix power_state to work even if cloud-final72 - systemd/power_state: fix power_state to work even if cloud-final
73 exited non-zero (LP: #1449318)73 exited non-zero (LP: #1449318)
74 - SmartOS: Add support for Joyent LX-Brand Zones (LP: #1540965)74 - SmartOS: Add support for Joyent LX-Brand Zones (LP: #1540965)
75 - lxd: add support for setting up lxd using 'lxd init' (LP: #1522879)
75 [Robert C Jennings]76 [Robert C Jennings]
76 - systemd: support using systemd-detect-virt to detect container77 - systemd: support using systemd-detect-virt to detect container
77 (LP: #1539016) [Martin Pitt]78 (LP: #1539016) [Martin Pitt]
7879
=== added file 'cloudinit/config/cc_lxd.py'
--- cloudinit/config/cc_lxd.py 1970-01-01 00:00:00 +0000
+++ cloudinit/config/cc_lxd.py 2016-02-05 01:21:21 +0000
@@ -0,0 +1,66 @@
1# vi: ts=4 expandtab
2#
3# Copyright (C) 2016 Canonical Ltd.
4#
5# Author: Wesley Wiedenmeier <wesley.wiedenmeier@canonical.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3, as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""
20This module initializes lxd using 'lxd init'
21
22Example config:
23 #cloud-config
24 lxd:
25 init:
26 network_address: <ip addr>
27 network_port: <port>
28 storage_backend: <zfs/dir>
29 storage_create_device: <dev>
30 storage_create_loop: <size>
31 storage_pool: <name>
32 trust_password: <password>
33"""
34
35from cloudinit import util
36
37
38def handle(name, cfg, cloud, log, args):
39 # Get config
40 lxd_cfg = cfg.get('lxd')
41 if not lxd_cfg and isinstance(lxd_cfg, dict):
42 log.debug("Skipping module named %s, not present or disabled by cfg")
43 return
44
45 # Ensure lxd is installed
46 if not util.which("lxd"):
47 try:
48 cloud.distro.install_packages(("lxd",))
49 except util.ProcessExecutionError as e:
50 log.warn("no lxd executable and could not install lxd: '%s'" % e)
51 return
52
53 # Set up lxd if init config is given
54 init_cfg = lxd_cfg.get('init')
55 if init_cfg:
56 if not isinstance(init_cfg, dict):
57 log.warn("lxd init config must be a dict of flag: val pairs")
58 return
59 init_keys = ('network_address', 'network_port', 'storage_backend',
60 'storage_create_device', 'storage_create_loop',
61 'storage_pool', 'trust_password')
62 cmd = ['lxd', 'init', '--auto']
63 for k in init_keys:
64 if init_cfg.get(k):
65 cmd.extend(["--%s" % k.replace('_', '-'), init_cfg[k]])
66 util.subp(cmd)
067
=== modified file 'config/cloud.cfg'
--- config/cloud.cfg 2015-10-09 16:39:23 +0000
+++ config/cloud.cfg 2016-02-05 01:21:21 +0000
@@ -56,6 +56,7 @@
56 - fan56 - fan
57 - landscape57 - landscape
58 - timezone58 - timezone
59 - lxd
59 - puppet60 - puppet
60 - chef61 - chef
61 - salt-minion62 - salt-minion
6263
=== added file 'doc/examples/cloud-config-lxd.txt'
--- doc/examples/cloud-config-lxd.txt 1970-01-01 00:00:00 +0000
+++ doc/examples/cloud-config-lxd.txt 2016-02-05 01:21:21 +0000
@@ -0,0 +1,21 @@
1#cloud-config
2
3# configure lxd
4# default: none
5# all options default to none if not specified
6# lxd: config sections for lxd
7# init: dict of options for lxd init, see 'man lxd'
8# network_address: address for lxd to listen on
9# network_port: port for lxd to listen on
10# storage_backend: either 'zfs' or 'dir'
11# storage_create_device: device based storage using specified device
12# storage_create_loop: set up loop based storage with size in GB
13# storage_pool: name of storage pool to use or create
14# trust_password: password required to add new clients
15
16lxd:
17 init:
18 network_address: 0.0.0.0
19 network_port: 8443
20 storage_backend: zfs
21 storage_pool: datapool
022
=== added file 'tests/unittests/test_handler/test_handler_lxd.py'
--- tests/unittests/test_handler/test_handler_lxd.py 1970-01-01 00:00:00 +0000
+++ tests/unittests/test_handler/test_handler_lxd.py 2016-02-05 01:21:21 +0000
@@ -0,0 +1,58 @@
1from cloudinit.config import cc_lxd
2from cloudinit import (distros, helpers, cloud)
3from cloudinit.sources import DataSourceNoCloud
4from .. import helpers as t_help
5
6import logging
7
8try:
9 from unittest import mock
10except ImportError:
11 import mock
12
13LOG = logging.getLogger(__name__)
14
15
16class TestLxd(t_help.TestCase):
17 lxd_cfg = {
18 'lxd': {
19 'init': {
20 'network_address': '0.0.0.0',
21 'storage_backend': 'zfs',
22 'storage_pool': 'poolname',
23 }
24 }
25 }
26
27 def setUp(self):
28 super(TestLxd, self).setUp()
29
30 def _get_cloud(self, distro):
31 cls = distros.fetch(distro)
32 paths = helpers.Paths({})
33 d = cls(distro, {}, paths)
34 ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
35 cc = cloud.Cloud(ds, paths, {}, d, None)
36 return cc
37
38 @mock.patch("cloudinit.config.cc_lxd.util")
39 def test_lxd_init(self, mock_util):
40 cc = self._get_cloud('ubuntu')
41 mock_util.which.return_value = True
42 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
43 self.assertTrue(mock_util.which.called)
44 init_call = mock_util.subp.call_args_list[0][0][0]
45 self.assertEquals(init_call,
46 ['lxd', 'init', '--auto', '--network-address',
47 '0.0.0.0', '--storage-backend', 'zfs',
48 '--storage-pool', 'poolname'])
49
50 @mock.patch("cloudinit.config.cc_lxd.util")
51 def test_lxd_install(self, mock_util):
52 cc = self._get_cloud('ubuntu')
53 cc.distro = mock.MagicMock()
54 mock_util.which.return_value = None
55 cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
56 self.assertTrue(cc.distro.install_packages.called)
57 install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
58 self.assertEquals(install_pkg, ('lxd',))