Commit d37dcb74 authored by Jérémie Gaidamour's avatar Jérémie Gaidamour
Browse files

[dev] Manage Dead node + check nodes that are missing from the reference-repository

parent 27e7f2bb
......@@ -93,7 +93,7 @@ class ::Hash
# Custom iterator. Same as "each" but it sorts keys by node_uid (ie. graphene-10 after graphene-9)
def each_sort_by_node_uid
self.sort_by { |item| item.to_s.split(/(\d+)/).map { |e| [e.to_i, e] } }.each { |key, value|
yield key, value
yield key, value if key != nil
}
end
......
......@@ -18,6 +18,11 @@ MiB = 1024**2
def get_node_properties(cluster_uid, cluster, node_uid, node)
h = {} # ouput
if node['status'] == 'retired'
h['state'] = 'Dead'
return h if node.size == 1 # for dead nodes, additional information is most likely missing from the ref-repository.
end
main_network_adapter = node['network_interfaces'].values.find{ |na| na['enabled'] && na['mounted'] && na['interface'] =~ /ethernet/i && !na['management'] }
main_network_adapter = node['network_interfaces'].values.find{ |na| na['enabled'] && na['mounted'] }
raise MissingProperty, "Node #{node_uid} does not have a main network_adapter" unless main_network_adapter
......@@ -106,9 +111,9 @@ def get_nodelist_properties(site_uid, site)
begin
properties[node_uid] = get_node_properties(cluster_uid, cluster, node_uid, node)
rescue MissingProperty => e
# puts "Error while processing node #{node_uid}: #{e}"
# TODO
#puts "Error while processing node #{node_uid}: #{e}"
end
end
......@@ -117,9 +122,9 @@ def get_nodelist_properties(site_uid, site)
return properties
end
def diff_node_properties(a, b)
a ||= {}
b ||= {}
def diff_node_properties(node_properties_oar, node_properties_ref)
node_properties_oar ||= {}
node_properties_ref ||= {}
# default OAR at resource creation:
# available_upto: '2147483647'
......@@ -176,7 +181,6 @@ def diff_node_properties(a, b)
"rconsole", # TODO
"resource_id",
"scheduler_priority",
"state",
"state_num",
"switch", # TODO
"subnet_address",
......@@ -187,11 +191,22 @@ def diff_node_properties(a, b)
"vlan",
"wattmeter" # TODO
]
ignore_keys.each { |key| a.delete(key) }
ignore_keys.each { |key| b.delete(key) }
return HashDiff.diff(a, b)
ignore_keys.each { |key| node_properties_oar.delete(key) }
ignore_keys.each { |key| node_properties_ref.delete(key) }
# Ignore the 'state' property only if the node is not 'Dead' according to the reference-repo.
# Otherwise, we must enforce that the node state is also 'Dead' on the OAR server.
# On the OAR server, the 'state' property can be modified by phoenix. We ignore that.
if node_properties_ref['state'] != 'Dead'
node_properties_oar.delete('state')
node_properties_ref.delete('state')
elsif node_properties_ref.size == 1
# For dead nodes, when information is missing from the reference-repo, only enforce the 'state' property and ignore other differences.
return HashDiff.diff({'state' => node_properties_oar['state']}, {'state' => node_properties_ref['state']})
end
return HashDiff.diff(node_properties_oar, node_properties_ref)
end
......
......@@ -58,6 +58,21 @@ OptionParser.new do |opts|
options[:exec] = e
end
opts.on("-d", "--diff [YAML filename]",
"Only generates the minimal list of commands needed to update the site configuration",
"The optional YAML file is suppose to be the output of the 'oarnodes -Y' command.",
"If the file does not exist, the script will get the data from the OAR server and save the result on disk for future use.",
"If no filename is specified, the script will simply connect to the OAR server.",
"You can use the '%s' placeholder for 'site'. Ex: oarnodes-%s.yaml") do |d|
d = true if d == nil
options[:diff] = d
end
###
opts.separator ""
opts.separator "SSH options:"
opts.on('--ssh-keys k1,k2,k3', Array, 'SSH keys') do |k|
options[:ssh] ||= {}
options[:ssh][:params] ||= {}
......@@ -75,16 +90,16 @@ OptionParser.new do |opts|
options[:ssh][:params][:port] = 2222 unless options[:ssh][:params][:port]
end
opts.on("-d", "--diff [YAML filename]",
"Only generates the minimal list of commands needed to update the site configuration",
"The optional YAML file is suppose to be the output of the 'oarnodes -Y' command.",
"If the file does not exist, the script will get the data from the OAR server and save the result on disk for future use.",
"If no filename is specified, the script will simply connect to the OAR server.",
"You can use the '%s' placeholder for 'site'. Ex: oarnodes-%s.yaml") do |d|
d = true if d == nil
options[:diff] = d
###
opts.separator ''
opts.separator 'Misc:'
opts.on('--check', 'Perform extra checks.', 'Compare the node list of the OAR server with the reference-repo.') do |c|
puts "*** Warning: --check requires --diff." unless options[:diff]
options[:check] = c
end
###
opts.separator ""
......@@ -103,8 +118,9 @@ OptionParser.new do |opts|
end.parse!
options[:ssh] ||= {}
options[:ssh][:host] = 'oar.%s.g5kadmin' unless options[:ssh][:host]
options[:ssh][:user] = 'g5kadmin' unless options[:ssh][:user]
options[:ssh][:host] = 'oar.%s.g5kadmin' unless options[:ssh][:host]
options[:ssh][:params] ||= {}
options[:diff] = false unless options[:diff]
puts "Options: #{options}" if options[:verbose]
......@@ -137,10 +153,28 @@ if options[:diff]
}
end
#
# Checks
#
if options[:check]
# Build the list of nodes that are listed in nodelist_properties["oar"] but does not exist in nodelist_properties["ref"]
missings = []
nodelist_properties["oar"].each { |site_uid, site_properties|
site_properties.each_filtered_node_uid(options[:clusters], options[:nodes]) { |node_uid, node_properties_oar|
missings << node_uid unless nodelist_properties["ref"][site_uid][node_uid]
}
}
puts "*** Warning: The following nodes are missing in the reference-repo: #{missings.join(', ')}.\nThose nodes should be marked as 'retired' is the reference-repo." if missings.size > 0
end # if options[:check]
#
# Diff (-d option)
#
if options[:diff]
#
# Diff OAR properties between reference-repo and OAR servers
#
header = false
prev_diff = {}
......@@ -150,19 +184,20 @@ if options[:diff]
nodelist_properties["diff"][site_uid] = {}
site_properties.each_filtered_node_uid(options[:clusters], options[:nodes]) { |node_uid, node_properties_ref|
node_properties_oar = nodelist_properties["oar"][site_uid][node_uid]
diff = diff_node_properties(node_properties_oar, node_properties_ref)
diff = diff_node_properties(node_properties_oar, node_properties_ref)
diff_keys = diff.map{ |hashdiff_array| hashdiff_array[1] }
nodelist_properties["diff"][site_uid][node_uid] = node_properties_ref.select { |key, value| diff_keys.include?(key) }
# Verbose output
info = (nodelist_properties["oar"][site_uid][node_uid] == nil ? " new node !" : "")
case options[:verbose]
when 1
puts "#{node_uid}:#{info}" if info != ""
puts "#{node_uid}: #{diff_keys}"
puts "#{node_uid}: #{diff_keys}" if diff.size != 0
when 2
# Give more details
# puts "#{node_uid}: #{diff}"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment