#!/usr/bin/env ruby require 'json' require 'erb' require 'netaddr' require 'fileutils' require 'pathname' LXC_ROOT = Pathname.new("/etc/lxc") ZONE_PATH = LXC_ROOT.join("zones") TEMPLATE_PATH = LXC_ROOT.join("templates") CONTAINER_DATA = LXC_ROOT.join("container.json") LXC_ZONE = ZONE_PATH.join("lxc.zone") DNS_CONTAINER = "dns" def atomic_write(path, content) temp_path = path.to_s + ".tmp" File.open(temp_path, 'w+') do |f| f.write(content) end FileUtils.mv(temp_path, path) end class ZoneData def initialize(data) @data = data end attr_reader :data def get_binding binding end def ip(subnet) NetAddr::CIDR.create(subnet).ip(Short: true) end end class RdnsData def initialize(data, subnet) @data = data @subnet = subnet end attr_reader :data, :subnet def get_binding binding end def pointers(&block) subnet_arpa = @subnet.arpa version = @subnet.version data["network"].each do |name, data| next unless data["ipv#{version}"] arpa = NetAddr::CIDR.create(data["ipv#{version}"]).arpa addr = arpa[0, arpa.size - subnet_arpa.size - 1] yield addr, name end end end json = JSON.load(File.open(CONTAINER_DATA)) json["zone"]["serial"] += 1 rdns_zone_template = File.read(TEMPLATE_PATH.join("rdns-zone.erb")) zone_data = ZoneData.new(json) lxc_zone_template = File.read(TEMPLATE_PATH.join("lxc-zone.erb")) zone = ERB.new(lxc_zone_template, nil, '-').result(zone_data.get_binding) v4_subnet = NetAddr::CIDR.create(json["zone"]["v4_subnet"]) v4_rdns_path = ZONE_PATH.join(v4_subnet.arpa.gsub(/\.$/, "")) v4_rdns_zone = ERB.new(rdns_zone_template, nil, '-').result(RdnsData.new(json, v4_subnet).get_binding) v6_subnet = NetAddr::CIDR.create(json["zone"]["v6_subnet"]) v6_rdns_path = ZONE_PATH.join(v6_subnet.arpa.gsub(/\.$/, "")) v6_rdns_zone = ERB.new(rdns_zone_template, nil, '-').result(RdnsData.new(json, v6_subnet).get_binding) atomic_write(LXC_ZONE, zone) atomic_write(v4_rdns_path, v4_rdns_zone) atomic_write(v6_rdns_path, v6_rdns_zone) atomic_write(CONTAINER_DATA, JSON.pretty_generate(json)) system("lxc-attach", "-e", "-n", DNS_CONTAINER, "--", "rec_control", "reload-zones")