diff --git a/default.conf b/default.conf index 0938712..58262c0 100644 --- a/default.conf +++ b/default.conf @@ -30,7 +30,7 @@ lxc.cgroup.memory.limit_in_bytes = 2000M lxc.cgroup.cpu.shares = 256 lxc.cgroup.blkio.weight = 500 -lxc.mount.entry = /data/pacman-pkg-cache var/cache/pacman/pkg none bind 0 0 +lxc.mount.entry = /data/pacman-cache var/cache/pacman/pkg none bind 0 0 lxc.mount.entry = /data/repo srv/repo none bind,ro,create=dir 0 0 lxc.mount.entry = /run/systemd/journal mnt/journal none bind,ro,create=dir 0 0 diff --git a/evenet.conf b/evenet.conf new file mode 100644 index 0000000..50f74bc --- /dev/null +++ b/evenet.conf @@ -0,0 +1,5 @@ +lxc.network.type = veth +lxc.network.link = evenet +lxc.network.flags = up +lxc.network.name = eth1 +lxc.network.mtu = 1500 diff --git a/hooks/ansible b/hooks/ansible index 4a2015d..180c785 100755 --- a/hooks/ansible +++ b/hooks/ansible @@ -1,6 +1,5 @@ #!/bin/bash -set -x if [ -z "$LXC_NAME" ]; then echo "LXC_NAME not set" 2>&1 exit 1 diff --git a/hooks/create-lxc-config b/hooks/create-lxc-config index 0efd733..38f923b 100755 --- a/hooks/create-lxc-config +++ b/hooks/create-lxc-config @@ -1,21 +1,14 @@ #!/usr/bin/env ruby - -require "erb" +require "json" require "pathname" require 'ostruct' require 'optparse' require 'json' require 'netaddr' +require_relative 'lib/container' def try_env(key) - ENV[key] or abort("enviroment variable '#{key}' not set") -end - -def find_address(subnet, assigned_subnets) - subnet.enumerate(Limit: 1E4, Short: true)[1..1E4].each do |cidr| - assigned = assigned_subnets.find { |s| s.contains?(cidr) || s == cidr } - return cidr unless assigned - end + ENV[key] or abort("environment variable '#{key}' not set") end options = OpenStruct.new @@ -32,6 +25,12 @@ OptionParser.new do |opts| opts.on("-6", "--ipv6", "public Ipv6 subnet") do |v| options.ipv6 = v end + opts.on("--dn42-ipv4", String, "dn42 ipv4") do |v| + options.dn42_ipv4 = v + end + opts.on("--dn42-ipv6", String, "dn42 ipv6") do |v| + options.dn42_ipv6 = v + end opts.on("--group GROUP", String, "set ansible group (default NONE)") do |group| options.group = group end @@ -57,64 +56,23 @@ data = if File.exists?(container_data) {} end -zone = data["zone"] || {} -IPV4_SUBNET = NetAddr::CIDR.create(zone["v4_subnet"] || "192.168.10.0/24") -IPV6_SUBNET = NetAddr::CIDR.create(zone["v6_subnet"] || "fd7d:aed0:18aa::/48") - data["network"] ||= {} - -#if data["network"][options.container_name] -# abort "container name '#{options.container_name}' in '#{container_data}' already in use!" -#end data["network"][options.container_name] = {} - -ipv4_subnets = data["network"].map {|k,v| NetAddr::CIDR.create(v["ipv4"]) if v["ipv4"]}.compact! -ipv6_subnets = data["network"].map {|k,v| NetAddr::CIDR.create(v["ipv6"]) if v["ipv6"]}.compact! - -ipv4_address = if options.ipv4.nil? - find_address(IPV4_SUBNET, ipv4_subnets) - elsif address_free?(ipv4_subnets, options.ipv4) - abort "The address #{ipv4} is already assigned" - else - options.ipv4 - end - -ipv6_address = if options.ipv6.nil? - find_address(IPV6_SUBNET, ipv6_subnets) - elsif address_free?(ipv6_subnets, options.ipv6) - abort "The address #{ipv4} is already assigned" - else - options.ipv6 - end - -network_config = data["network"][options.container_name] -network_config["ipv4"] = NetAddr::CIDR.create(ipv4_address).to_s(Short: true) -network_config["ipv6"] = NetAddr::CIDR.create(ipv6_address).to_s(Short: true) -network_config["group"] = options.group -network_config["vars"] = options.vars +network = data["network"][options.container_name] +network["ipv4"] = NetAddr::CIDR.create(ipv4_address).to_s(Short: true) +network["ipv6"] = NetAddr::CIDR.create(ipv6_address).to_s(Short: true) +network["group"] = options.group +network["vars"] = options.vars open(container_data, File::CREAT|File::TRUNC|File::RDWR) do |f| f.write(JSON.pretty_generate(data)) end -class TemplateContext - def initialize(hash) - hash.each do |key, value| - singleton_class.send(:define_method, key) { value } - end - end - - def get_binding - binding - end -end - -context = TemplateContext.new(container_name: options.container_name, - ipv4: NetAddr::CIDR.create(ipv4_address, Mask: IPV4_SUBNET.to_i(:netmask)).desc(IP: true, Short: true), - ipv6: NetAddr::CIDR.create(ipv6_address, Mask: IPV6_SUBNET.to_i(:netmask)).desc(IP: true, Short: true), - rootfs: options.rootfs) - -erb = ERB.new(File.read(CONFIG_PATH.join("templates", "config.erb"))) -open(options.container_config, "w+") do |f| - f.write(erb.result(context.get_binding)) -end +container = Container.new(data, + name: options.container_name, + ipv4: ipv4_address, + ipv6: ipv6_address, + rootfs: options.rootfs, + dn42_ipv4: options.dn42_ipv4, + dn42_ipv6: options.dn42_ipv4) +container.write_config(options.container_config) diff --git a/hooks/dn42-routes b/hooks/dn42-routes index 6ea730b..00d6927 100755 --- a/hooks/dn42-routes +++ b/hooks/dn42-routes @@ -1,5 +1,5 @@ #!/bin/bash -/usr/bin/ip route add 172.16.0.0/12 via 172.16.75.1 proto static -/usr/bin/ip route add 10.0.0.0/8 via 172.16.75.1 proto static +/usr/bin/ip route add 172.16.0.0/12 via 172.16.75.1 proto static metric 200 +/usr/bin/ip route add 10.0.0.0/8 via 172.16.75.1 proto static metric 200 exit 0 diff --git a/hooks/evenet-routes b/hooks/evenet-routes new file mode 100755 index 0000000..67343ff --- /dev/null +++ b/hooks/evenet-routes @@ -0,0 +1,5 @@ +#!/bin/bash + +/usr/bin/ip route add 172.16.0.0/12 via 172.16.75.1 proto static metric 100 +/usr/bin/ip route add 10.0.0.0/8 via 172.16.75.1 proto static metric 100 +exit 0 diff --git a/hooks/lib/container.rb b/hooks/lib/container.rb new file mode 100644 index 0000000..77e3979 --- /dev/null +++ b/hooks/lib/container.rb @@ -0,0 +1,69 @@ +require "erb" +ROOT_PATH = Pathname.new(File.expand_path("../../..", __FILE__)) + +class TemplateContext + def initialize(hash) + hash.each do |key, value| + singleton_class.send(:define_method, key) { value } + end + end + + def get_binding + binding + end +end + +class Container + def initialize(data, ip4:, ip6:, dn42_ipv4:, dn42_ipv6:, **options) + network = @data["network"] || {} + zone = data["zone"] || {} + + ipv4_subnet = NetAddr::CIDR.create(zone["v4_subnet"] || "192.168.10.0/24") + ipv6_subnet = NetAddr::CIDR.create(zone["v6_subnet"] || "fd7d:aed0:18aa::/48") + + if subnet = zone["dn42_ipv4_subnet"] + dn42_ipv4_netmask = NetAddr::CIDR.create(subnet).to_i(:netmask) + else + dn42_ipv4_netmask = 24 + end + + if subnet = zone["dn42_ipv6_subnet"] + dn42_ipv6_netmask = NetAddr::CIDR.create(subnet).to_i(:netmask) + else + dn42_ipv6_netmask = 48 + end + + ip4 ||= find_address(ipv4_subnet, collect_subnets(network, "ipv4")) + ip6 ||= find_address(ipv6_subnet, collect_subnets(network, "ipv6")) + @opts = options.merge(ipv4: format_address(ip4, ipv4_subnet.to_i(:netmask)), + ipv6: format_address(ip6, ipv6_subnet.to_i(:netmask))) + @opts[:dn42_ipv4] = format_address(dn42_ipv6, dn42_ipv4_netmask) + @opts[:dn42_ipv6] = format_address(dn42_ipv4, dn42_ipv6_netmask) + end + + def write_config(config_path) + context = TemplateContext.new(@opts) + erb = ERB.new(File.read(ROOT_PATH.join("templates", "config.erb"))) + open(config_path, "w+") do |f| + f.write(erb.result(context.get_binding)) + end + end + + private + def format_address(address, netmask) + NetAddr::CIDR.create(address, Mask: netmask).desc(IP: true, Short: true) + end + + def collect_subnets(network, type) + network.map do |k,v| + NetAddr::CIDR.create(v[type]) if v[type] + end.compact! + end + + def find_address(subnet, assigned_subnets) + subnet.enumerate(Limit: 1E4, Short: true)[1..1E4].each do |cidr| + assigned = assigned_subnets.find { |s| s.contains?(cidr) || s == cidr } + return cidr unless assigned + end + end +end diff --git a/hooks/remove-journal b/hooks/remove-journal index abb8614..4dde974 100755 --- a/hooks/remove-journal +++ b/hooks/remove-journal @@ -1,6 +1,6 @@ #!/bin/bash -set -xeu +set -eu JOURNAL="$LXC_ROOTFS_PATH/var/log/journal" diff --git a/hooks/setup-machine-id b/hooks/setup-machine-id index 4e5d900..a9bf213 100755 --- a/hooks/setup-machine-id +++ b/hooks/setup-machine-id @@ -1,6 +1,6 @@ #!/bin/bash -set -eux +set -eu MACHINE_ID="${LXC_ROOTFS_PATH}/etc/machine-id" diff --git a/hooks/update-zone b/hooks/update-zone index 772d35a..6bb604e 100755 --- a/hooks/update-zone +++ b/hooks/update-zone @@ -14,6 +14,10 @@ LXC_ZONE = ZONE_PATH.join("eve.higgsboson.tk.zone") DNS_CONTAINER = "dns" def atomic_write(path, content) + dir = File.dirname(path) + unless Dir.exist?(dir) + FileUtils.mkdir_p(dir) + end temp_path = path.to_s + ".tmp" File.open(temp_path, 'w+') do |f| f.write(content) diff --git a/templates/config.erb b/templates/config.erb index cd23a10..95301e5 100644 --- a/templates/config.erb +++ b/templates/config.erb @@ -1,6 +1,6 @@ lxc.include = /etc/lxc/default.conf -lxc.utsname = <%= container_name %> +lxc.utsname = <%= name %> lxc.rootfs = <%= rootfs %> lxc.network.ipv4 = <%= ipv4 %> lxc.network.ipv6 = <%= ipv6 %> -lxc.network.veth.pair = lxc_<%= container_name[0..(16-4)] %> +lxc.network.veth.pair = lxc_<%= name[0..(16-4)] %>