summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-02-25 14:37:04 -0500
committerScott Moser <smoser@ubuntu.com>2016-02-25 14:37:04 -0500
commit3b773f7919c86a58956e2fc493512bb2c1ce31a8 (patch)
tree6ab76ff494ceeb75b567b7c247791d1b6dac03a3
parentdf6af3e1433b9e5564bec7cd452cfb3a0fb403e9 (diff)
parent4d8e7324c7242e1c969c8561462def6c1cda747c (diff)
downloadvyos-cloud-init-3b773f7919c86a58956e2fc493512bb2c1ce31a8.tar.gz
vyos-cloud-init-3b773f7919c86a58956e2fc493512bb2c1ce31a8.zip
lxd: add support for setting up lxd using 'lxd init'
If lxd key is present in cfg, then run 'lxd init' with values from the 'init' entry in lxd configuration as flags.
-rw-r--r--ChangeLog1
-rw-r--r--cloudinit/config/cc_lxd.py68
-rw-r--r--config/cloud.cfg1
-rw-r--r--doc/examples/cloud-config-lxd.txt21
-rw-r--r--tests/unittests/test_handler/test_handler_lxd.py58
5 files changed, 149 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 9659764e..6b58f1d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -78,6 +78,7 @@
- docs: fix lock_passwd documentation [Robert C Jennings]
- Azure: Handle escaped quotes in WALinuxAgentShim.find_endpoint.
(LP: #1488891) [Dan Watkins]
+ - lxd: add support for setting up lxd using 'lxd init' (LP: #1522879)
0.7.6:
- open 0.7.6
diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py
new file mode 100644
index 00000000..aaafb643
--- /dev/null
+++ b/cloudinit/config/cc_lxd.py
@@ -0,0 +1,68 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2016 Canonical Ltd.
+#
+# Author: Wesley Wiedenmeier <wesley.wiedenmeier@canonical.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This module initializes lxd using 'lxd init'
+
+Example config:
+ #cloud-config
+ lxd:
+ init:
+ network_address: <ip addr>
+ network_port: <port>
+ storage_backend: <zfs/dir>
+ storage_create_device: <dev>
+ storage_create_loop: <size>
+ storage_pool: <name>
+ trust_password: <password>
+"""
+
+from cloudinit import util
+
+
+def handle(name, cfg, cloud, log, args):
+ # Get config
+ lxd_cfg = cfg.get('lxd')
+ if not lxd_cfg and isinstance(lxd_cfg, dict):
+ log.debug("Skipping module named %s, not present or disabled by cfg")
+ return
+
+ # Ensure lxd is installed
+ if not util.which("lxd"):
+ try:
+ cloud.distro.install_packages(("lxd",))
+ except util.ProcessExecutionError as e:
+ log.warn("no lxd executable and could not install lxd:", e)
+ return
+
+ # Set up lxd if init config is given
+ init_keys = (
+ 'network_address', 'network_port', 'storage_backend',
+ 'storage_create_device', 'storage_create_loop',
+ 'storage_pool', 'trust_password')
+ init_cfg = lxd_cfg.get('init')
+ if init_cfg:
+ if not isinstance(init_cfg, dict):
+ log.warn("lxd/init config must be a dictionary. found a '%s'",
+ type(f))
+ return
+ cmd = ['lxd', 'init', '--auto']
+ for k in init_keys:
+ if init_cfg.get(k):
+ cmd.extend(["--%s" % k.replace('_', '-'), init_cfg[k]])
+ util.subp(cmd)
diff --git a/config/cloud.cfg b/config/cloud.cfg
index 74794ab0..795df19f 100644
--- a/config/cloud.cfg
+++ b/config/cloud.cfg
@@ -56,6 +56,7 @@ cloud_config_modules:
- fan
- landscape
- timezone
+ - lxd
- puppet
- chef
- salt-minion
diff --git a/doc/examples/cloud-config-lxd.txt b/doc/examples/cloud-config-lxd.txt
new file mode 100644
index 00000000..f66da4c3
--- /dev/null
+++ b/doc/examples/cloud-config-lxd.txt
@@ -0,0 +1,21 @@
+#cloud-config
+
+# configure lxd
+# default: none
+# all options default to none if not specified
+# lxd: config sections for lxd
+# init: dict of options for lxd init, see 'man lxd'
+# network_address: address for lxd to listen on
+# network_port: port for lxd to listen on
+# storage_backend: either 'zfs' or 'dir'
+# storage_create_device: device based storage using specified device
+# storage_create_loop: set up loop based storage with size in GB
+# storage_pool: name of storage pool to use or create
+# trust_password: password required to add new clients
+
+lxd:
+ init:
+ network_address: 0.0.0.0
+ network_port: 8443
+ storage_backend: zfs
+ storage_pool: datapool
diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py
new file mode 100644
index 00000000..4d858b8f
--- /dev/null
+++ b/tests/unittests/test_handler/test_handler_lxd.py
@@ -0,0 +1,58 @@
+from cloudinit.config import cc_lxd
+from cloudinit import (distros, helpers, cloud)
+from cloudinit.sources import DataSourceNoCloud
+from .. import helpers as t_help
+
+import logging
+
+try:
+ from unittest import mock
+except ImportError:
+ import mock
+
+LOG = logging.getLogger(__name__)
+
+
+class TestLxd(t_help.TestCase):
+ lxd_cfg = {
+ 'lxd': {
+ 'init': {
+ 'network_address': '0.0.0.0',
+ 'storage_backend': 'zfs',
+ 'storage_pool': 'poolname',
+ }
+ }
+ }
+
+ def setUp(self):
+ super(TestLxd, self).setUp()
+
+ def _get_cloud(self, distro):
+ cls = distros.fetch(distro)
+ paths = helpers.Paths({})
+ d = cls(distro, {}, paths)
+ ds = DataSourceNoCloud.DataSourceNoCloud({}, d, paths)
+ cc = cloud.Cloud(ds, paths, {}, d, None)
+ return cc
+
+ @mock.patch("cloudinit.config.cc_lxd.util")
+ def test_lxd_init(self, mock_util):
+ cc = self._get_cloud('ubuntu')
+ mock_util.which.return_value = True
+ cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
+ self.assertTrue(mock_util.which.called)
+ init_call = mock_util.subp.call_args_list[0][0][0]
+ self.assertEquals(init_call,
+ ['lxd', 'init', '--auto', '--network-address',
+ '0.0.0.0', '--storage-backend', 'zfs',
+ '--storage-pool', 'poolname'])
+
+ @mock.patch("cloudinit.config.cc_lxd.util")
+ def test_lxd_install(self, mock_util):
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ mock_util.which.return_value = None
+ cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, LOG, [])
+ self.assertTrue(cc.distro.install_packages.called)
+ install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
+ self.assertEquals(install_pkg, ('lxd',))