From a7de90b2ebdd097bb98fef72f970354973982e81 Mon Sep 17 00:00:00 2001 From: Stéphane Graber Date: Mon, 11 Apr 2016 00:09:44 -0400 Subject: Add support for lxd-bridge configuration --- cloudinit/config/cc_lxd.py | 111 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 15 deletions(-) (limited to 'cloudinit') diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py index 63b8fb63..7d90b606 100644 --- a/cloudinit/config/cc_lxd.py +++ b/cloudinit/config/cc_lxd.py @@ -30,9 +30,23 @@ Example config: storage_create_loop: storage_pool: trust_password: + bridge: + mode: + name: + ipv4_address: + ipv4_netmask: + ipv4_dhcp_first: + ipv4_dhcp_last: + ipv4_dhcp_leases: + ipv4_nat: + ipv6_address: + ipv6_netmask: + ipv6_nat: + domain: """ from cloudinit import util +import os def handle(name, cfg, cloud, log, args): @@ -46,22 +60,24 @@ def handle(name, cfg, cloud, log, args): type(lxd_cfg)) return + # Grab the configuration init_cfg = lxd_cfg.get('init') if not isinstance(init_cfg, dict): log.warn("lxd/init config must be a dictionary. found a '%s'", type(init_cfg)) init_cfg = {} - if not init_cfg: - log.debug("no lxd/init config. disabled.") - return + bridge_cfg = lxd_cfg.get('bridge') + if not isinstance(bridge_cfg, dict): + log.warn("lxd/bridge config must be a dictionary. found a '%s'", + type(bridge_cfg)) + bridge_cfg = {} + # Install the needed packages packages = [] - # Ensure lxd is installed if not util.which("lxd"): packages.append('lxd') - # if using zfs, get the utils if init_cfg.get("storage_backend") == "zfs" and not util.which('zfs'): packages.append('zfs') @@ -73,13 +89,78 @@ def handle(name, cfg, cloud, log, args): 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') - cmd = ['lxd', 'init', '--auto'] - for k in init_keys: - if init_cfg.get(k): - cmd.extend(["--%s=%s" % - (k.replace('_', '-'), str(init_cfg[k]))]) - util.subp(cmd) + if init_cfg: + init_keys = ( + 'network_address', 'network_port', 'storage_backend', + 'storage_create_device', 'storage_create_loop', + 'storage_pool', 'trust_password') + cmd = ['lxd', 'init', '--auto'] + for k in init_keys: + if init_cfg.get(k): + cmd.extend(["--%s=%s" % + (k.replace('_', '-'), str(init_cfg[k]))]) + util.subp(cmd) + + # Set up lxd-bridge if bridge config is given + if bridge_cfg: + debconf = {} + + if bridge_cfg.get("mode") == "none": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/bridge-name"] = "" + + elif bridge_cfg.get("mode") == "existing": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/use-existing-bridge"] = "true" + debconf["lxd/bridge-name"] = bridge_cfg.get("name") + + elif bridge_cfg.get("mode") == "new": + debconf["lxd/setup-bridge"] = "true" + debconf["lxd/bridge-name"] = bridge_cfg.get("name", "lxdbr0") + if bridge_cfg.get("ipv4_address"): + debconf["lxd/bridge-ipv4"] = "true" + debconf["lxd/bridge-ipv4-address"] = \ + bridge_cfg.get("ipv4_address") + debconf["lxd/bridge-ipv4-netmask"] = \ + bridge_cfg.get("ipv4_netmask") + debconf["lxd/bridge-ipv4-dhcp-first"] = \ + bridge_cfg.get("ipv4_dhcp_first") + debconf["lxd/bridge-ipv4-dhcp-last"] = \ + bridge_cfg.get("ipv4_dhcp_last") + debconf["lxd/bridge-ipv4-dhcp-leases"] = \ + bridge_cfg.get("ipv4_dhcp_leases") + debconf["lxd/bridge-ipv4-nat"] = \ + bridge_cfg.get("ipv4_nat", "true") + + if bridge_cfg.get("ipv6_address"): + debconf["lxd/bridge-ipv6"] = "true" + debconf["lxd/bridge-ipv6-address"] = \ + bridge_cfg.get("ipv6_address") + debconf["lxd/bridge-ipv6-netmask"] = \ + bridge_cfg.get("ipv6_netmask") + debconf["lxd/bridge-ipv6-nat"] = \ + bridge_cfg.get("ipv6_nat", "false") + + else: + log.warn("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) + return + + # Update debconf database + try: + log.debug("Setting lxd debconf-set-selections") + for k, v in debconf.items(): + util.subp(['debconf-communicate'], "set %s %s\n" % (k, v)) + except: + util.logexc(log, "Failed to run debconf-communicate for lxd") + + # Remove the existing configuration file (forces re-generation) + if os.path.exists("/etc/default/lxd-bridge"): + os.remove("/etc/default/lxd-bridge") + + # Run reconfigure + try: + log.debug("Running dpkg-reconfigure for lxd") + util.subp(['dpkg-reconfigure', 'lxd', + '--frontend=noninteractive']) + except: + util.logexc(log, "Failed to run dpkg-reconfigure for lxd") -- cgit v1.2.3 From 072510d7251653701c23ded9be38832044fb42b8 Mon Sep 17 00:00:00 2001 From: Stéphane Graber Date: Mon, 11 Apr 2016 11:58:28 -0400 Subject: Update lxd-bridge code to do a single debconf-communicate run and split debconf logic to a function --- cloudinit/config/cc_lxd.py | 101 +++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 49 deletions(-) (limited to 'cloudinit') diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py index 7d90b606..b467df20 100644 --- a/cloudinit/config/cc_lxd.py +++ b/cloudinit/config/cc_lxd.py @@ -103,53 +103,14 @@ def handle(name, cfg, cloud, log, args): # Set up lxd-bridge if bridge config is given if bridge_cfg: - debconf = {} - - if bridge_cfg.get("mode") == "none": - debconf["lxd/setup-bridge"] = "false" - debconf["lxd/bridge-name"] = "" - - elif bridge_cfg.get("mode") == "existing": - debconf["lxd/setup-bridge"] = "false" - debconf["lxd/use-existing-bridge"] = "true" - debconf["lxd/bridge-name"] = bridge_cfg.get("name") - - elif bridge_cfg.get("mode") == "new": - debconf["lxd/setup-bridge"] = "true" - debconf["lxd/bridge-name"] = bridge_cfg.get("name", "lxdbr0") - if bridge_cfg.get("ipv4_address"): - debconf["lxd/bridge-ipv4"] = "true" - debconf["lxd/bridge-ipv4-address"] = \ - bridge_cfg.get("ipv4_address") - debconf["lxd/bridge-ipv4-netmask"] = \ - bridge_cfg.get("ipv4_netmask") - debconf["lxd/bridge-ipv4-dhcp-first"] = \ - bridge_cfg.get("ipv4_dhcp_first") - debconf["lxd/bridge-ipv4-dhcp-last"] = \ - bridge_cfg.get("ipv4_dhcp_last") - debconf["lxd/bridge-ipv4-dhcp-leases"] = \ - bridge_cfg.get("ipv4_dhcp_leases") - debconf["lxd/bridge-ipv4-nat"] = \ - bridge_cfg.get("ipv4_nat", "true") - - if bridge_cfg.get("ipv6_address"): - debconf["lxd/bridge-ipv6"] = "true" - debconf["lxd/bridge-ipv6-address"] = \ - bridge_cfg.get("ipv6_address") - debconf["lxd/bridge-ipv6-netmask"] = \ - bridge_cfg.get("ipv6_netmask") - debconf["lxd/bridge-ipv6-nat"] = \ - bridge_cfg.get("ipv6_nat", "false") - - else: - log.warn("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) - return + debconf = bridge_to_debconf(bridge_cfg) # Update debconf database try: log.debug("Setting lxd debconf-set-selections") - for k, v in debconf.items(): - util.subp(['debconf-communicate'], "set %s %s\n" % (k, v)) + data = "\n".join(["set %s %s" % (k, v) + for k, v in debconf.items()]) + util.subp(['debconf-communicate'], data) except: util.logexc(log, "Failed to run debconf-communicate for lxd") @@ -158,9 +119,51 @@ def handle(name, cfg, cloud, log, args): os.remove("/etc/default/lxd-bridge") # Run reconfigure - try: - log.debug("Running dpkg-reconfigure for lxd") - util.subp(['dpkg-reconfigure', 'lxd', - '--frontend=noninteractive']) - except: - util.logexc(log, "Failed to run dpkg-reconfigure for lxd") + log.debug("Running dpkg-reconfigure for lxd") + util.subp(['dpkg-reconfigure', 'lxd', + '--frontend=noninteractive']) + + +def bridge_to_debconf(bridge_cfg): + debconf = {} + + if bridge_cfg.get("mode") == "none": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/bridge-name"] = "" + + elif bridge_cfg.get("mode") == "existing": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/use-existing-bridge"] = "true" + debconf["lxd/bridge-name"] = bridge_cfg.get("name") + + elif bridge_cfg.get("mode") == "new": + debconf["lxd/setup-bridge"] = "true" + debconf["lxd/bridge-name"] = bridge_cfg.get("name", "lxdbr0") + if bridge_cfg.get("ipv4_address"): + debconf["lxd/bridge-ipv4"] = "true" + debconf["lxd/bridge-ipv4-address"] = \ + bridge_cfg.get("ipv4_address") + debconf["lxd/bridge-ipv4-netmask"] = \ + bridge_cfg.get("ipv4_netmask") + debconf["lxd/bridge-ipv4-dhcp-first"] = \ + bridge_cfg.get("ipv4_dhcp_first") + debconf["lxd/bridge-ipv4-dhcp-last"] = \ + bridge_cfg.get("ipv4_dhcp_last") + debconf["lxd/bridge-ipv4-dhcp-leases"] = \ + bridge_cfg.get("ipv4_dhcp_leases") + debconf["lxd/bridge-ipv4-nat"] = \ + bridge_cfg.get("ipv4_nat", "true") + + if bridge_cfg.get("ipv6_address"): + debconf["lxd/bridge-ipv6"] = "true" + debconf["lxd/bridge-ipv6-address"] = \ + bridge_cfg.get("ipv6_address") + debconf["lxd/bridge-ipv6-netmask"] = \ + bridge_cfg.get("ipv6_netmask") + debconf["lxd/bridge-ipv6-nat"] = \ + bridge_cfg.get("ipv6_nat", "false") + + else: + raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) + + return debconf -- cgit v1.2.3 From dcc2c894b9f12527ce0254fd7a0306e0d41af5bf Mon Sep 17 00:00:00 2001 From: Stéphane Graber Date: Mon, 11 Apr 2016 12:57:26 -0400 Subject: lxd-bridge: Don't require a bridge name and implement support for domain name --- cloudinit/config/cc_lxd.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'cloudinit') diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py index b467df20..0b10077a 100644 --- a/cloudinit/config/cc_lxd.py +++ b/cloudinit/config/cc_lxd.py @@ -138,7 +138,9 @@ def bridge_to_debconf(bridge_cfg): elif bridge_cfg.get("mode") == "new": debconf["lxd/setup-bridge"] = "true" - debconf["lxd/bridge-name"] = bridge_cfg.get("name", "lxdbr0") + if bridge_cfg.get("name"): + debconf["lxd/bridge-name"] = bridge_cfg.get("name") + if bridge_cfg.get("ipv4_address"): debconf["lxd/bridge-ipv4"] = "true" debconf["lxd/bridge-ipv4-address"] = \ @@ -163,6 +165,9 @@ def bridge_to_debconf(bridge_cfg): debconf["lxd/bridge-ipv6-nat"] = \ bridge_cfg.get("ipv6_nat", "false") + if bridge_cfg.get("domain"): + debconf["lxd/bridge-domain"] = bridge_cfg.get("domain") + else: raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) -- cgit v1.2.3 From 860d98bce4b607a513dc94d96335e8f105a36294 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 11 Apr 2016 15:08:08 -0400 Subject: minor cleanups - use util.del_file rather than os.remove - raise exception if debconf-communicate is not present - add a trailing newline into debconf-communicate input --- cloudinit/config/cc_lxd.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'cloudinit') diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py index 0b10077a..bf735648 100644 --- a/cloudinit/config/cc_lxd.py +++ b/cloudinit/config/cc_lxd.py @@ -46,7 +46,6 @@ Example config: """ from cloudinit import util -import os def handle(name, cfg, cloud, log, args): @@ -102,26 +101,29 @@ def handle(name, cfg, cloud, log, args): util.subp(cmd) # Set up lxd-bridge if bridge config is given - if bridge_cfg: + dconf_comm = "debconf-communicate" + if bridge_cfg and util.which(dconf_comm): debconf = bridge_to_debconf(bridge_cfg) # Update debconf database try: - log.debug("Setting lxd debconf-set-selections") + log.debug("Setting lxd debconf via " + dconf_comm) data = "\n".join(["set %s %s" % (k, v) - for k, v in debconf.items()]) + for k, v in debconf.items()]) + "\n" util.subp(['debconf-communicate'], data) except: - util.logexc(log, "Failed to run debconf-communicate for lxd") + util.logexc(log, "Failed to run '%s' for lxd with" % dconf_comm) # Remove the existing configuration file (forces re-generation) - if os.path.exists("/etc/default/lxd-bridge"): - os.remove("/etc/default/lxd-bridge") + util.del_file("/etc/default/lxd-bridge") # Run reconfigure log.debug("Running dpkg-reconfigure for lxd") util.subp(['dpkg-reconfigure', 'lxd', '--frontend=noninteractive']) + elif bridge_cfg: + raise RuntimeError( + "Unable to configure lxd bridge without %s." + dconf_comm) def bridge_to_debconf(bridge_cfg): -- cgit v1.2.3