From 89d179e8477fba85297443bdda024c4275cdda15 Mon Sep 17 00:00:00 2001 From: Simon Delamare <simon.delamare@ens-lyon.fr> Date: Mon, 12 May 2025 16:27:32 +0200 Subject: [PATCH] [lib] Support for describing several nodes connected to the same PDU/Wattmetre port (shared PSU case) --- .../templates/kwollect-wattmetre-mapping.erb | 9 ++++ lib/refrepo/input_loader.rb | 46 +++++++++++++------ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/lib/refrepo/gen/puppet/templates/kwollect-wattmetre-mapping.erb b/lib/refrepo/gen/puppet/templates/kwollect-wattmetre-mapping.erb index 0ec8a7132f3..eb5f582a890 100644 --- a/lib/refrepo/gen/puppet/templates/kwollect-wattmetre-mapping.erb +++ b/lib/refrepo/gen/puppet/templates/kwollect-wattmetre-mapping.erb @@ -4,6 +4,15 @@ # <%- + wattmetre_port_per_node_flat = {} + wattmetre_port_per_node.each do |nodes, ports| + nodes = [nodes] if nodes.is_a?(String) + nodes.each do |node| + wattmetre_port_per_node_flat[node] = ports + end + end + wattmetre_port_per_node = wattmetre_port_per_node_flat + # Sort by cluster and node number wattmetre_port_per_node.to_a.sort_by { |e| n = e[0].split('-') ; n[1] = n[1].to_i ; n }.each { |e| node, ports = e -%> diff --git a/lib/refrepo/input_loader.rb b/lib/refrepo/input_loader.rb index f96eb9375ef..8c99e9298cf 100644 --- a/lib/refrepo/input_loader.rb +++ b/lib/refrepo/input_loader.rb @@ -120,15 +120,18 @@ def add_node_pdu_mapping(h) end # Merge pdu information from pdus/ hierachy into node information - pdu.fetch("ports", {}).each do |port_uid, node_uid| - node_uid = node_uid["uid"] if node_uid.is_a?(Hash) - node = site["clusters"].fetch(node_uid.split("-")[0], {}).fetch("nodes", {}).fetch(node_uid, nil) - next if not node - node["pdu"] ||= [] - if node["pdu"].any?{|p| p["uid"] == pdu_uid && p["port"] == port_uid} - raise "ERROR: Node #{node_uid}.#{site_uid} has PDU #{pdu_uid} description defined both in clusters/ and pdus/ hierarchy" - end - node["pdu"].append({"uid" => pdu_uid, "port" => port_uid}) + pdu.fetch("ports", {}).each do |port_uid, nodes_uid| + nodes_uid = nodes_uid["uid"] if nodes_uid.is_a?(Hash) + nodes_uid = [nodes_uid] if nodes_uid.is_a?(String) + nodes_uid.each do |node_uid| + node = site["clusters"].fetch(node_uid.split("-")[0], {}).fetch("nodes", {}).fetch(node_uid, nil) + next if not node + node["pdu"] ||= [] + if node["pdu"].any?{|p| p["uid"] == pdu_uid && p["port"] == port_uid} + raise "ERROR: Node #{node_uid}.#{site_uid} has PDU #{pdu_uid} description defined both in clusters/ and pdus/ hierarchy" + end + node["pdu"].append({"uid" => pdu_uid, "port" => port_uid}) + end end # Merge pdu information from node description in pdus/ hierachy @@ -137,7 +140,13 @@ def add_node_pdu_mapping(h) raise "ERROR: Port #{port_uid} of #{pdu_uid}.#{site_uid} is defined both in PDU description and in node #{node_uid} description" end pdu["ports"] ||= {} - pdu["ports"][port_uid] = node_uid + if not pdu["ports"].key?(port_uid) + pdu["ports"][port_uid] = node_uid + elsif pdu["ports"].key?(port_uid) and pdu["ports"]["port_uid"].is_a?(String) + pdu["ports"][port_uid] = [pdu["ports"][port_uid], node_uid] + else + pdu["ports"][port_uid].append(node_uid) + end end end end @@ -182,12 +191,15 @@ def add_wattmetre_mapping(h) pdu["ports"][port_num] = node_uid # Add mapping to node description under clusters/ hierarchy - node = site["clusters"].fetch(node_uid.split("-")[0], {}).fetch("nodes", {}).fetch(node_uid, nil) - node["pdu"] ||= [] - if node["pdu"].any?{|p| p["uid"] == pdu_uid && p["port"] == port_num} - raise "ERROR: Node #{node_uid}.#{site_uid} has PDU #{pdu_num} description defined both in clusters/ and pdus/ hierarchy" + nodes_uid = node_uid.is_a?(String) ? [node_uid] : node_uid + nodes_uid.each do |nnode_uid| + node = site["clusters"].fetch(nnode_uid.split("-")[0], {}).fetch("nodes", {}).fetch(nnode_uid, nil) + node["pdu"] ||= [] + if node["pdu"].any?{|p| p["uid"] == pdu_uid && p["port"] == port_num} + raise "ERROR: Node #{nnode_uid}.#{site_uid} has PDU #{pdu_num} description defined both in clusters/ and pdus/ hierarchy" + end + node["pdu"].append({"uid" => pdu_uid, "port" => port_num, "kind" => "wattmetre-only"}) end - node["pdu"].append({"uid" => pdu_uid, "port" => port_num, "kind" => "wattmetre-only"}) end end end @@ -665,6 +677,10 @@ def add_pdu_metrics(h) # remove any PDU metrics defined in cluster cluster['metrics'] = cluster.fetch('metrics', []).reject {|m| m['name'] =~ /(wattmetre_power_watt|pdu_outlet_power_watt)/ } + # Do not add metric to cluster if PDU/wattmetre port is connected to several nodes at a time (shared PSU case) + nodes_pdu_ports = cluster['nodes'].select{|_, v| v['status'] != 'retired'}.each_value.map{|node| node["pdu"]}.flatten + next if nodes_pdu_ports.uniq.length != nodes_pdu_ports.length # nodes pdu_ports has duplicate, meaning the a port is shared by several nodes + # get the list of "wattmetre-only" used by the cluster cluster_wm = cluster['nodes'].each_value.map{|node| node.fetch('pdu', [])}.flatten.select{|p| p.fetch('kind', '') == 'wattmetre-only'}.map{|p| p['uid']}.uniq -- GitLab