#!/usr/bin/env ruby require 'ipaddress_2' require 'erb' TABLE_WIDTH = 8 class Subnet attr_reader :addr, :desc attr_accessor :addr_visible def initialize addr, desc @addr = addr @desc = desc @addr_visible = false end end class Group attr_accessor :net, :blocks def initialize net, blocks @net = net @blocks = blocks end end class Block attr_accessor :label, :name def initialize label, name @label = label @name = name end end nets = [] while line = gets a, desc = line.split(/ /, 2) addr = IPAddress.parse a desc.chomp! nets << Subnet.new(addr, desc) end nets.sort_by! { |net| net.addr } collisions = 0 prev = nil nets.each do |net| if prev and (net.addr.include?(prev.addr) or prev.addr.include?(net.addr)) STDERR.puts "#{prev.addr} and #{net.addr} overlap" collisions += 1 end prev = net end exit 1 if collisions > 0 GROUP_PREFIX = 16 groups = {} nets.each do |net| group = net.addr.supernet(GROUP_PREFIX).to_s (groups[group] ||= []) << net end max_prefix = [groups.collect { nets.collect { |net| net.addr.prefix }.max }.max, 64].min groups = groups.collect do |group, nets| allnet = nets[0].addr.clone while allnet.prefix > 0 and not allnet.include?(nets[nets.size - 1].addr) allnet = allnet.supernet(allnet.prefix - 1) end blocks = [] row = [] allnet.subnet(max_prefix).each do |addr| net = nets.select { |net| net.addr.include? addr }[0] label = net ? "#{addr}/#{net.addr.prefix}" : addr.to_s row << Block.new(label, net ? net.desc : "") if row.size >= TABLE_WIDTH blocks << row row = [] end end blocks << row if row.size > 0 blocks.each do |row| prev_name = nil row.each_with_index do |block| block.label = "" if prev_name == block.name prev_name = block.name end end Group.new(allnet, blocks) end def background_color desc case desc when "core" "#9F9F9F" when "mgmt" "#FF3F3F" when "c3d2" "yellow" when "serv", "cluster" "orange" when "pub" "#7FFF7F" when /priv(\d+)/ "hsl(240, 80%, #{60 + 5 * ($1.to_i % 8)}%)" else "white" end end html = ERB::new <<~EOF Subnetwork Plan <% groups.each do |group| %> <% group.blocks.each do |row| %> <% row.each do |block| %> <% end %> <% end %> <% end %>
<%= group.net.to_string %>
<%= block.label %> <%= block.name %>
EOF puts html.result