Bug 2677 - améliorer la lisibilité du powerdiagram en regroupant les noeuds par rack

désormais, le powerdiagram est plus lisible car les noeuds sont regroupés par rack. J'aurais bien aimé que les serveurs soient ordonnés comme dans les racks mais graphviz ne sait pas bien mixer des positions forcées avec des positions libres (lorsque j'ai essayé de le faire, les positions fixées ne l'étaient plus)
This commit is contained in:
Guillaume Raffy 2019-06-21 15:17:13 +00:00
parent e102d33a9d
commit 889712b356
2 changed files with 56 additions and 1 deletions

View File

@ -41,6 +41,7 @@ class Machine(object):
self.current_capacity_constraint = None # the maximum amperes in this connection self.current_capacity_constraint = None # the maximum amperes in this connection
self.power_config = power_config self.power_config = power_config
self.power_consumption = 0.0 self.power_consumption = 0.0
self.rack_id = None
def get_plug(self, plug_name): def get_plug(self, plug_name):
plugs = {'i': self.input_plugs, 'o': self.output_plugs}[plug_name[0]] plugs = {'i': self.input_plugs, 'o': self.output_plugs}[plug_name[0]]
@ -199,6 +200,14 @@ class PowerConfig(object):
machine_name = machine.name machine_name = machine.name
# find its rack location
try:
rack_id, rack_slot_index = inventory.get_machine_rack_location(machine_name)
machine.rack_id = rack_id
machine.rack_slot_index = rack_slot_index
except SimpaDbUtil.TableAttrNotFound:
pass
if re.match('[a-z]+.._..', machine_name): if re.match('[a-z]+.._..', machine_name):
# machine_name is a group of machines such as physix80_83 # machine_name is a group of machines such as physix80_83
# in this case, we use a hack : the type and power consumption is based on the first machine of this group (in this example physix80) # in this case, we use a hack : the type and power consumption is based on the first machine of this group (in this example physix80)
@ -220,6 +229,7 @@ class PowerConfig(object):
if power_consumption is not None: if power_consumption is not None:
machine.power_consumption = power_consumption machine.power_consumption = power_consumption
def get_connection_to(self, to_plug): def get_connection_to(self, to_plug):
for connection in self.connections: for connection in self.connections:
if connection.to_plug == to_plug: if connection.to_plug == to_plug:
@ -261,6 +271,7 @@ def power_config_to_svg(power_config, svg_file_path):
graph = pygraphviz.AGraph() graph = pygraphviz.AGraph()
graph.graph_attr['overlap'] = 'false' graph.graph_attr['overlap'] = 'false'
graph.graph_attr['splines'] = 'true' graph.graph_attr['splines'] = 'true'
graph.graph_attr['rankdir'] = 'LR' # to get hrizontal tree rather than vertical
graph.edge_attr['colorscheme'] = 'rdylgn9' # 'brbg11' graph.edge_attr['colorscheme'] = 'rdylgn9' # 'brbg11'
graph.node_attr['shape'] = 'box' graph.node_attr['shape'] = 'box'
@ -280,6 +291,31 @@ def power_config_to_svg(power_config, svg_file_path):
# graph.add_node('b') # graph.add_node('b')
# graph.add_edge(u'a',u'b',color='blue') # graph.add_edge(u'a',u'b',color='blue')
# graph.add_edge(u'b',u'a',color='blue') # graph.add_edge(u'b',u'a',color='blue')
racks = {}
for con in power_config.connections:
for machine in [con.from_plug.machine, con.to_plug.machine]:
rack_id = machine.rack_id
if rack_id is not None:
if rack_id not in racks.keys():
rack = {}
rack['name'] = rack_id
rack['machines'] = []
racks[rack_id] = rack
rack = racks[rack_id]
if machine.name not in rack['machines']:
rack['machines'].append(machine)
if False:
x = 0.0
for rack in racks.itervalues():
y = 0.0
for machine in rack['machines']:
graph.add_node(machine.name, pos='%f,%f!' % (x, y)) # https://observablehq.com/@magjac/placing-graphviz-nodes-in-fixed-positions
print(machine.name, x, y)
y += 1.0
x += 1.0
for con in power_config.connections: for con in power_config.connections:
# print(con.from_plug.machine.name, con.to_plug.machine.name) # print(con.from_plug.machine.name, con.to_plug.machine.name)
if not con.is_redundancy_cable(): # don't display redundancy cables, as they might overlap and hide the main one if not con.is_redundancy_cable(): # don't display redundancy cables, as they might overlap and hide the main one
@ -306,5 +342,19 @@ def power_config_to_svg(power_config, svg_file_path):
# color='//%d' % int(9.0-amperes/capacity*8) # color='//%d' % int(9.0-amperes/capacity*8)
graph.add_edge(con.from_plug.machine.name, con.to_plug.machine.name, color=color, label=label, penwidth=penwidth) graph.add_edge(con.from_plug.machine.name, con.to_plug.machine.name, color=color, label=label, penwidth=penwidth)
graph.layout(prog='twopi')
if True:
for rack_id, rack in racks.iteritems():
# sub = graph.add_subgraph(rack, name='cluster_%s' % rack_id, rank='same')
machine_names = list(machine.name for machine in rack['machines'])
sub = graph.add_subgraph(machine_names, name='cluster_%s' % rack_id)
sub.graph_attr['label'] = rack_id
# sub.graph_attr['rank']='same'
# assert False
#graph.layout(prog='twopi')
with open('./toto.dot', 'w') as f:
f.write(graph.string())
graph.layout(prog='dot')
graph.draw(svg_file_path) graph.draw(svg_file_path)

View File

@ -130,6 +130,11 @@ class Inventory(object):
ordering_date = datetime.datetime.strptime(ordering_date_as_str, '%d/%m/%Y') ordering_date = datetime.datetime.strptime(ordering_date_as_str, '%d/%m/%Y')
return ordering_date return ordering_date
def get_machine_rack_location(self, machine_id):
rack_id = self._sql_reader.get_table_attr('rackable_machine_to_location', 'machine_id', machine_id, 'rack_id')
slot_index = self._sql_reader.get_table_attr('rackable_machine_to_location', 'machine_id', machine_id, 'slot_index')
return rack_id, slot_index
def get_cpu_dflops(self, cpu_model): def get_cpu_dflops(self, cpu_model):
''' '''
returns the number of double precision operation per second this cpu can achieve returns the number of double precision operation per second this cpu can achieve