80 lines
2.8 KiB
Ruby
80 lines
2.8 KiB
Ruby
require "erb"
|
|
require "netaddr"
|
|
require "pathname"
|
|
require "fileutils"
|
|
|
|
module Lxc
|
|
class Container
|
|
def initialize(data, name:, ipv4: nil, ipv6: nil, ula: nil, **options)
|
|
@data = data
|
|
@data["network"] ||= {}
|
|
@data["network"][name] = {}
|
|
|
|
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")
|
|
@ula_subnet = NetAddr::CIDR.create(zone["ula_subnet"] || "fdc5:bdb8:b81::/48")
|
|
|
|
@container_root = Pathname.new(zone["lxc_root"]).join(name)
|
|
|
|
network = data["network"]
|
|
@name = name
|
|
@ipv4 = ipv4 || find_address(@ipv4_subnet, collect_subnets(network, "ipv4"))
|
|
@ipv6 = ipv6 || find_address(@ipv6_subnet, collect_subnets(network, "ipv6"))
|
|
@ula = ula || find_address(@ula_subnet, collect_subnets(network, "ula"))
|
|
@options = options
|
|
end
|
|
|
|
def write_config(config_path)
|
|
c = @data["network"][@name] || {}
|
|
c["ipv4"] = NetAddr::CIDR.create(@ipv4).to_s(Short: true)
|
|
c["ipv6"] = NetAddr::CIDR.create(@ipv6).to_s(Short: true)
|
|
c["ula"] = NetAddr::CIDR.create(@ula).to_s(Short: true)
|
|
c["group"] = @options[:group] if @options[:group]
|
|
c["vars"] = @options[:vars] if @options[:vars]
|
|
|
|
opts = @options.merge(name: @name,
|
|
ipv4: format_address(@ipv4, @ipv4_subnet.to_i(:netmask)),
|
|
ipv6: format_address(@ipv6, @ipv6_subnet.to_i(:netmask)),
|
|
ula: format_address(@ula, @ula_subnet.to_i(:netmask)))
|
|
|
|
config_dir = File.dirname(config_path)
|
|
local_conf = File.join(config_dir, "local.conf")
|
|
unless File.exists?(local_conf)
|
|
FileUtils.touch(local_conf)
|
|
end
|
|
opts[:local_conf] = local_conf
|
|
opts[:global_conf] = @data["zone"]["lxc-config"]
|
|
|
|
fstab = @container_root.join("fstab")
|
|
opts[:fstab] = fstab if File.exists?(fstab)
|
|
opts[:rootfs] = @data["zone"]["shared_rootfs"] || opts[:rootfs] || @container_root.join("rootfs")
|
|
|
|
templ = Template.new(CONFIG_ROOT.join("hooks", "templates", "config.erb"))
|
|
templ.write(config_path, opts)
|
|
end
|
|
|
|
private
|
|
def format_address(address, netmask)
|
|
NetAddr::CIDR.create(address, Mask: netmask).desc(IP: true, Short: true)
|
|
end
|
|
|
|
def collect_subnets(network, type)
|
|
addrs = []
|
|
network.each do |k,v|
|
|
if v[type]
|
|
addrs << NetAddr::CIDR.create(v[type])
|
|
end
|
|
end
|
|
addrs
|
|
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
|
|
end
|