From 889712b3560cfc861e5a8d1ab72fade7f3edf632 Mon Sep 17 00:00:00 2001 From: Guillaume Raffy Date: Fri, 21 Jun 2019 15:17:13 +0000 Subject: [PATCH] =?UTF-8?q?Bug=202677=20-=20am=C3=A9liorer=20la=20lisibili?= =?UTF-8?q?t=C3=A9=20du=20powerdiagram=20en=20regroupant=20les=20noeuds=20?= =?UTF-8?q?par=20rack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- PowerDiagram.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- inventory.py | 5 +++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/PowerDiagram.py b/PowerDiagram.py index 9b19253..72b5a31 100644 --- a/PowerDiagram.py +++ b/PowerDiagram.py @@ -41,6 +41,7 @@ class Machine(object): self.current_capacity_constraint = None # the maximum amperes in this connection self.power_config = power_config self.power_consumption = 0.0 + self.rack_id = None def get_plug(self, plug_name): plugs = {'i': self.input_plugs, 'o': self.output_plugs}[plug_name[0]] @@ -199,6 +200,14 @@ class PowerConfig(object): 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): # 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) @@ -220,6 +229,7 @@ class PowerConfig(object): if power_consumption is not None: machine.power_consumption = power_consumption + def get_connection_to(self, to_plug): for connection in self.connections: if connection.to_plug == to_plug: @@ -261,6 +271,7 @@ def power_config_to_svg(power_config, svg_file_path): graph = pygraphviz.AGraph() graph.graph_attr['overlap'] = 'false' graph.graph_attr['splines'] = 'true' + graph.graph_attr['rankdir'] = 'LR' # to get hrizontal tree rather than vertical graph.edge_attr['colorscheme'] = 'rdylgn9' # 'brbg11' 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_edge(u'a',u'b',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: # 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 @@ -306,5 +342,19 @@ def power_config_to_svg(power_config, svg_file_path): # 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.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) diff --git a/inventory.py b/inventory.py index 0c96e5a..4d3a4e7 100644 --- a/inventory.py +++ b/inventory.py @@ -130,6 +130,11 @@ class Inventory(object): ordering_date = datetime.datetime.strptime(ordering_date_as_str, '%d/%m/%Y') 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): ''' returns the number of double precision operation per second this cpu can achieve