146 lines
2.8 KiB
Ruby
146 lines
2.8 KiB
Ruby
#!/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, :span
|
|
|
|
def initialize label, name
|
|
@label = label
|
|
@name = name
|
|
@span = 1
|
|
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 = []
|
|
x = 0
|
|
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
|
|
name = net ? net.desc : ""
|
|
if row.last and name != "" and row.last.name == name
|
|
row.last.span += 1
|
|
else
|
|
row << Block.new(label, name)
|
|
end
|
|
x += 1
|
|
if x >= TABLE_WIDTH
|
|
blocks << row
|
|
row = []
|
|
x = 0
|
|
end
|
|
end
|
|
blocks << row if row.size > 0
|
|
|
|
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
|
|
<html>
|
|
<head>
|
|
<title>Subnetwork Plan</title>
|
|
<style>
|
|
table {
|
|
margin: 3rem auto;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<table border="1">
|
|
<% groups.each do |group| %>
|
|
<tr>
|
|
<th colspan="<%= TABLE_WIDTH %>"><%= group.net.to_string %></th>
|
|
</tr>
|
|
<% group.blocks.each do |row| %>
|
|
<tr>
|
|
<% row.each do |block| %>
|
|
<td colspan="<%= block.span %>" style="background-color: <%= background_color(block.name) %>"><%= block.label %> <%= block.name %></td>
|
|
<% end %>
|
|
</tr>
|
|
<% end %>
|
|
<% end %>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
EOF
|
|
puts html.result
|