module OVSImager
class DotWriter
def initialize(fname)
@fname = fname
@dot = File.open(fname, 'w')
@dot.puts 'graph interfaces {'
@dot.puts ' compound=true'
@dot.puts ' node [shape=rect,margin=0.1]'
@dot_peers = []
end
def finish(pngname)
@dot.puts @dot_peers.join "\n"
@dot.puts '}'
@dot.close
@dot = nil
unless system("dot -Tpng \"#{@fname}\" -o \"#{pngname}\"")
puts "Failed to execute dot command: #$?"
end
end
# Draw OVSVS & LinuxBridge
def bridge(name, br_type)
@dot.puts " subgraph cluster_br__#{escape(name)} {"
@dot.puts " label = \"#{br_type}Bridge #{name}\""
yield BridgeWriter.new(@dot, @dot_peers)
@dot.puts " }"
end
# Draw IPNetNS
def namespace(name)
@dot.puts " subgraph cluster_ns__#{escape(name)} {"
@dot.puts " label = \"Namespace\\n#{name}\""
@dot.puts " style = \"filled\""
@dot.puts " fillcolor = \"#eeeeee\""
@dot.puts " ns__#{escape(name)} " +
"[label=\"\",style=invis,width=0,height=0,margin=0]"
yield NSWriter.new(@dot, @dot_peers, name)
@dot.puts ' }'
end
private
def escape(name)
Utils.escape_nodename(name)
end
class BridgeWriter
def initialize(dot, dot_peers)
@dot = dot
@dot_peers = dot_peers
end
def add_iface(name, mark, dump, inet, tag, peer, remote=nil, ns=:root)
fill = mark ? "fillcolor=#{mark2color(mark)},style=filled," : ''
label = "#{name}
#{inet.join('
')}"
if tag or remote
label += "
#{tag}#{remote && remote.gsub('>','>')}"
end
if dump
label += " "
if dump[0] && dump[2] && dump[0] == dump[3] && dump[1] == dump[2]
label += "
[#{dump[0]} <-> #{dump[1]}]"
else
label += "
[#{dump[0]} --> #{dump[1]}]" if dump[0]
label += "
[#{dump[3]} <-- #{dump[2]}]" if dump[2]
end
if dump[4] && dump[4][:cap]
cap = dump[4][:cap]
label += "
(#{cap[2]} #{cap[3]} " +
"#{cap[0]}<=>#{cap[1]})"
end
end
label += " "
ename = escape(name) + (ns == :root ? '' : "___" + escape(ns.to_s))
@dot.puts " #{ename} [#{fill}label=<#{label}>]"
if peer
if peer[0] == ' '
@dot_peers << " #{escape(peer.strip)} -- #{ename}"
elsif name <= peer
@dot_peers << " #{ename} -- #{escape(peer)}"
end
end
end
private
def mark2color(mark)
{'<' => 'red', '>' => 'pink', '*' => 'yellow'}[mark]
end
def escape(name)
Utils.escape_nodename(name)
end
end
# Draw namespace
class NSWriter < BridgeWriter
def initialize(dot, dot_peers, nsname)
@dot = dot
@dot_peers = dot_peers
@nsname = nsname
end
def add_br_iface(name, ns=:root)
ename = escape(name) + (ns == :root ? '' : "___" + escape(ns.to_s))
@dot_peers << " #{ename} -- ns__#{escape(@nsname)} " +
"[style=dashed,lhead=cluster_ns__#{escape(@nsname)}]"
end
end
end
end