Bug 2680 - Améliorer le support des alimentation redondantes dans PowerDiagram
- amélioration du code pour que les alimentations redondantes soient gérées correctement. Il en ressort que plus de câbles sont en surcharge. - j'en ai profité pour afficher les alims secourues en vert et les non secourues en bleu.
This commit is contained in:
parent
9aaefd495f
commit
7c7d519eaf
|
@ -70,6 +70,10 @@ class Machine(object):
|
||||||
# print("machine %s : power_consumption += %f" % (self.name, conn.get_power_consumption()))
|
# print("machine %s : power_consumption += %f" % (self.name, conn.get_power_consumption()))
|
||||||
return power_consumption
|
return power_consumption
|
||||||
|
|
||||||
|
def is_power_provider(self):
|
||||||
|
return self.name == 'edf' or re.match('^ups[0-9]*$', self.name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Plug(object):
|
class Plug(object):
|
||||||
"""
|
"""
|
||||||
|
@ -99,20 +103,24 @@ class Plug(object):
|
||||||
def get_max_amperes(self):
|
def get_max_amperes(self):
|
||||||
capacity = None
|
capacity = None
|
||||||
|
|
||||||
|
debug = False
|
||||||
if self.is_input_plug():
|
if self.is_input_plug():
|
||||||
in_con = self.get_incoming_connection()
|
in_con = self.get_incoming_connection()
|
||||||
if in_con:
|
if in_con:
|
||||||
# apply incoming connection amperes limitation
|
# apply incoming connection amperes limitation
|
||||||
capacity = add_capacity_constraints(capacity, in_con.get_max_amperes())
|
capacity = add_capacity_constraints(capacity, in_con.get_max_amperes())
|
||||||
# print(str(self)+ 'after incoming connection amperes limitation, capacity = ' + str(capacity))
|
if debug:
|
||||||
|
print(str(self)+ 'after incoming connection amperes limitation, capacity = ' + str(capacity))
|
||||||
else:
|
else:
|
||||||
# apply the machine containing this plug's amperes limitation
|
# apply the machine containing this plug's amperes limitation
|
||||||
capacity = add_capacity_constraints(capacity, self.machine.get_max_amperes())
|
capacity = add_capacity_constraints(capacity, self.machine.get_max_amperes())
|
||||||
# print(str(self)+'apply the machine containing this plug s amperes limitation, capacity = ' + str(capacity))
|
if debug:
|
||||||
|
print(str(self)+'apply the machine containing this plug s amperes limitation, capacity = ' + str(capacity))
|
||||||
|
|
||||||
# apply this plug's amperes limitation
|
# apply this plug's amperes limitation
|
||||||
capacity = add_capacity_constraints(capacity, self.current_capacity_constraint)
|
capacity = add_capacity_constraints(capacity, self.current_capacity_constraint)
|
||||||
# print(str(self)+'after apply this plug s amperes limitation, capacity = ' + str(capacity))
|
if debug:
|
||||||
|
print(str(self)+'after apply this plug s amperes limitation, capacity = ' + str(capacity), self.current_capacity_constraint)
|
||||||
|
|
||||||
return capacity
|
return capacity
|
||||||
|
|
||||||
|
@ -135,7 +143,7 @@ class Connection(object):
|
||||||
self.current_capacity_constraint = None # the maximum amperes in this connection
|
self.current_capacity_constraint = None # the maximum amperes in this connection
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.from_plug) + ' -> ' + str(self.to_plug) + ' (' + str(self.from_plug.get_max_amperes()) + str(self.get_max_amperes()) + 'A)'
|
return str(self.from_plug) + ' -> ' + str(self.to_plug) + ' (' + str(self.from_plug.get_max_amperes()) + ' A, ' + str(self.get_max_amperes()) + ' A)'
|
||||||
|
|
||||||
def get_max_amperes(self):
|
def get_max_amperes(self):
|
||||||
# gLogger.debug('%s (%s A) -> %s (%s A): ' % (str(self.from_plug), str(self.from_plug.get_max_amperes()), str(self.to_plug), str(self.to_plug.current_capacity_constraint)))
|
# gLogger.debug('%s (%s A) -> %s (%s A): ' % (str(self.from_plug), str(self.from_plug.get_max_amperes()), str(self.to_plug), str(self.to_plug.current_capacity_constraint)))
|
||||||
|
@ -146,7 +154,32 @@ class Connection(object):
|
||||||
return capacity
|
return capacity
|
||||||
|
|
||||||
def is_redundancy_cable(self):
|
def is_redundancy_cable(self):
|
||||||
return not (self.to_plug.name == 'i' or self.to_plug.name == 'i1')
|
to_machine = self.to_plug.machine
|
||||||
|
my_power_provider = self.get_power_provider()
|
||||||
|
# find the first sibling cable that has the same provider as self
|
||||||
|
first_cable_with_same_provider = None
|
||||||
|
for input_plug in to_machine.input_plugs.itervalues():
|
||||||
|
sibling_cable = input_plug.get_incoming_connection()
|
||||||
|
if sibling_cable.get_power_provider() == my_power_provider:
|
||||||
|
first_cable_with_same_provider = sibling_cable
|
||||||
|
if first_cable_with_same_provider is None:
|
||||||
|
# no other connection with the same provider
|
||||||
|
return False
|
||||||
|
if first_cable_with_same_provider == self:
|
||||||
|
# for each provider, the 1st cable amongst the connectors using this provider is considered to be the original (not redundant)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# for each provider, all cable but the 1st one are considered as redundant
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_power_provider(self):
|
||||||
|
from_machine = self.from_plug.machine
|
||||||
|
if from_machine.is_power_provider():
|
||||||
|
return from_machine
|
||||||
|
input_plug_names = from_machine.input_plugs.keys()
|
||||||
|
assert len(input_plug_names) == 1, "from_machine is supposed to be a power strip (which is expected to only have one input)"
|
||||||
|
input_plug = from_machine.input_plugs[input_plug_names[0]]
|
||||||
|
return input_plug.get_incoming_connection().get_power_provider()
|
||||||
|
|
||||||
def get_power_consumption(self):
|
def get_power_consumption(self):
|
||||||
# at the moment, this program doesn't handle redundant power supplies properly:
|
# at the moment, this program doesn't handle redundant power supplies properly:
|
||||||
|
@ -263,12 +296,21 @@ class PowerConfig(object):
|
||||||
|
|
||||||
class CableColorer(object):
|
class CableColorer(object):
|
||||||
|
|
||||||
def get_cable_color(self, amperes, capacity):
|
def get_cable_color(self, cable):
|
||||||
|
"""
|
||||||
|
:param Connection cable:
|
||||||
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
class SimpleColorer(CableColorer):
|
class SimpleColorer(CableColorer):
|
||||||
|
|
||||||
def get_cable_color(self, amperes, capacity):
|
def get_cable_color(self, cable):
|
||||||
|
"""
|
||||||
|
:param Connection cable:
|
||||||
|
"""
|
||||||
|
power_consumption = cable.get_power_consumption()
|
||||||
|
amperes = power_consumption / 220.0
|
||||||
|
capacity = cable.get_max_amperes()
|
||||||
saturation = amperes / capacity
|
saturation = amperes / capacity
|
||||||
if saturation > 1.0:
|
if saturation > 1.0:
|
||||||
color = '/svg/red'
|
color = '/svg/red'
|
||||||
|
@ -288,18 +330,31 @@ class RampColorer(CableColorer):
|
||||||
:param float hotness: temperature of the wire ratio (0.0 : cold -> 1.0 : hot)
|
:param float hotness: temperature of the wire ratio (0.0 : cold -> 1.0 : hot)
|
||||||
"""
|
"""
|
||||||
clamped_hotness = max(min(hotness, 1.0), 0.0)
|
clamped_hotness = max(min(hotness, 1.0), 0.0)
|
||||||
return "%f, 1.0, 0.8" % ((clamped_hotness) * 0.33 + 0.33)
|
return "%f, 1.0, 0.8" % ((clamped_hotness) * 0.1 + 0.23)
|
||||||
|
|
||||||
def get_cable_color(self, amperes, capacity):
|
def get_cable_color(self, cable):
|
||||||
|
"""
|
||||||
|
:param Connection cable:
|
||||||
|
"""
|
||||||
|
power_consumption = cable.get_power_consumption()
|
||||||
|
amperes = power_consumption / 220.0
|
||||||
|
capacity = cable.get_max_amperes()
|
||||||
saturation = amperes / capacity
|
saturation = amperes / capacity
|
||||||
# color = RampColorer.hotness_to_hsv_color(pow(saturation, 4.0))
|
color = None
|
||||||
|
# print(cable.from_plug.machine.name, cable.to_plug.machine.name, cable.get_power_provider().name)
|
||||||
|
power_is_backed_up = cable.get_power_provider().name == 'ups3'
|
||||||
|
if power_is_backed_up:
|
||||||
|
# greenish colors
|
||||||
|
color = RampColorer.hotness_to_hsv_color(pow(saturation, 4.0))
|
||||||
|
else:
|
||||||
|
# blueish colors using the pretty ylgnbu9 color palette
|
||||||
clamped_saturation = max(min(saturation, 1.0), 0.0)
|
clamped_saturation = max(min(saturation, 1.0), 0.0)
|
||||||
color = '/ylgnbu9/%d' % (int(clamped_saturation * 5) + 4)
|
color = '/ylgnbu9/%d' % (int(clamped_saturation * 5) + 4)
|
||||||
|
|
||||||
if saturation < 0.001:
|
if saturation < 0.001:
|
||||||
color = '/svg/black' # probably an error
|
color = '/svg/black' # probably an error
|
||||||
elif saturation > 1.0:
|
elif saturation > 1.0:
|
||||||
color = '/svg/red'
|
color = '/svg/red' # draw overloaded cables in red
|
||||||
return color
|
return color
|
||||||
|
|
||||||
def power_config_to_svg(power_config, svg_file_path):
|
def power_config_to_svg(power_config, svg_file_path):
|
||||||
|
@ -347,7 +402,7 @@ def power_config_to_svg(power_config, svg_file_path):
|
||||||
y = 0.0
|
y = 0.0
|
||||||
for machine in rack['machines']:
|
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
|
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)
|
# print(machine.name, x, y)
|
||||||
y += 1.0
|
y += 1.0
|
||||||
x += 1.0
|
x += 1.0
|
||||||
|
|
||||||
|
@ -358,16 +413,16 @@ def power_config_to_svg(power_config, svg_file_path):
|
||||||
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
|
||||||
power_consumption = con.get_power_consumption()
|
power_consumption = con.get_power_consumption()
|
||||||
amperes = power_consumption / 220.0
|
amperes = power_consumption / 220.0
|
||||||
color = 'green'
|
color = '/svg/green'
|
||||||
capacity = con.get_max_amperes()
|
capacity = con.get_max_amperes()
|
||||||
penwidth_scaler = 0.25
|
penwidth_scaler = 0.25
|
||||||
if capacity is None:
|
if capacity is None:
|
||||||
max_amp = '? A'
|
max_amp = '? A'
|
||||||
color = 'red'
|
color = '/svg/red'
|
||||||
penwidth = 100.0 * penwidth_scaler # make the problem clearly visible
|
penwidth = 100.0 * penwidth_scaler # make the problem clearly visible
|
||||||
else:
|
else:
|
||||||
max_amp = str(capacity) + 'A'
|
max_amp = str(capacity) + 'A'
|
||||||
color = cable_colorer.get_cable_color(amperes, capacity)
|
color = cable_colorer.get_cable_color(con)
|
||||||
penwidth = capacity * penwidth_scaler
|
penwidth = capacity * penwidth_scaler
|
||||||
label = "%.1f/%s" % (amperes, max_amp)
|
label = "%.1f/%s" % (amperes, max_amp)
|
||||||
# color='//%d' % int(9.0-amperes/capacity*8)
|
# color='//%d' % int(9.0-amperes/capacity*8)
|
||||||
|
|
Loading…
Reference in New Issue