check-cluster-homogeneity.rb 5.28 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/ruby

# This script checks the cluster homogeneity

if RUBY_VERSION < "2.1"
  puts "This script requires ruby >= 2.1"
  exit
end

require 'pp'
require 'fileutils'
require 'pathname'
require 'hashdiff'

dir = Pathname(__FILE__).parent

require "#{dir}/../lib/input_loader"

def cluster_homogeneity(refapi_hash, verbose=false)

  ignore_keys = %w(
    chassis.serial
  
    network_adapters.bmc.ip
    network_adapters.bmc.mac
    network_adapters.bmc.network_address
    network_adapters.bmc.switch
    network_adapters.bmc.switch_port
  
    network_adapters.ib0.guid
    network_adapters.ib0.hwid
    network_adapters.ib0.ip
    network_adapters.ib0.ip6
    network_adapters.ib0.line_card
    network_adapters.ib0.position
    network_adapters.ib1.guid
  
    network_adapters.myri0.ip
    network_adapters.myri0.ip6
    network_adapters.myri0.mac
    network_adapters.myri0.network_address
  
    pdu
    pdu.port
    pdu.uid
46
47
48
    pdu[0]
    pdu[1]

49
    supported_job_types.max_walltime
50
51
52
53
54

    mic.ip
    mic.mac

    status
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  )

  ignore_netkeys = <<-eos
    network_adapters.eth.ip
    network_adapters.eth.ip6
    network_adapters.eth.mac
    network_adapters.eth.network_address
    network_adapters.eth.switch
    network_adapters.eth.switch_port
    network_adapters.eth.ip
    network_adapters.eth.ip6
    network_adapters.eth.mac
    network_adapters.eth.switch_port
    network_adapters.eth.ip
    network_adapters.eth.ip6
    network_adapters.eth.mac
    network_adapters.eth.switch_port
    network_adapters.eth.ip
    network_adapters.eth.mac
    network_adapters.eth.mac
    network_adapters.eth.mac
eos

  ignore_stokeys = <<-eos
    storage_devices.sd.model
    storage_devices.sd.rev
    storage_devices.sd.size
    storage_devices.sd.timeread
    storage_devices.sd.timewrite
    storage_devices.sd.vendor
eos

  (0..5).each { |eth| 
    keys = ignore_netkeys.gsub('.eth.', ".eth#{eth}.").gsub("\n", " ").split(" ")
    ignore_keys.push(* keys)

    (1..21).each { |kavlan|
      ignore_keys << "kavlan.eth#{eth}.kavlan-#{kavlan}"
    }
  }

  ('a'..'d').each { |sd| 
    keys = ignore_stokeys.gsub('.sd.', ".sd#{sd}.").gsub("\n", " ").split(" ")
    ignore_keys.push(* keys)
  }

  refapi_hash = load_yaml_file_hierarchy("../../input/grid5000/")
  count = {}
  
  refapi_hash["sites"].sort.each do |site_uid, site|
    count[site_uid] = {}

    site["clusters"].sort.each do |cluster_uid, cluster|
      count[site_uid][cluster_uid] = 0

      refnode_uid = cluster['nodes'].keys.sort.first
      refnode = cluster['nodes'][refnode_uid]
      
      cluster["nodes"].each_sort_by_node_uid do |node_uid, node|
        #next if node_uid != 'graphene-2'
        
        diffs = HashDiff.diff(refnode, node)
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

        # Hack HashDiff output for arrays:
        #[["-", "pdu[1]", {"uid"=>"graphene-pdu9", "port"=>24}],
        # ["-", "pdu[0]", {"uid"=>"graphene-pdu9", "port"=>23}],
        # ["+", "pdu[0]", {"uid"=>"graphene-pdu9", "port"=>21}],
        # ["+", "pdu[1]", {"uid"=>"graphene-pdu9", "port"=>22}]]
        # => should be something like this:
        # [["~", "pdu[0]", {"uid"=>"graphene-pdu9", "port"=>23}, {"uid"=>"graphene-pdu9", "port"=>22},
        #  ["~", "pdu[1]", {"uid"=>"graphene-pdu9", "port"=>24}, {"uid"=>"graphene-pdu9", "port"=>23}}
        d = diffs.select{|x| x[0] != '~' }.group_by{ |x| x[1] }
        d.each { |k, v|
          d[k] = v.group_by{ |x| x[0] }
        }
        d.each { |k,v|
          if v.key?('-') && v.key?('+')
            #puts "Warning: #{node_uid}: convert +/- -> ~ for #{k}"
            diffs.delete(["-", k, v['-'][0][2]])
            diffs.delete(["+", k, v['+'][0][2]])
            diffs << ["~", k, v['-'][0][2], v['+'][0][2] ]
          end
        }
        # end of hack

140
141
        # Remove keys that are specific to each nodes (ip, mac etc.)
        diffs.clone.each { |diff|
142
          diffs.delete(diff) if diff[0] == '~' && ignore_keys.include?(diff[1])         
143
144
145
        }

        if verbose && !diffs.empty?
146
147
          puts "Differences between #{refnode_uid} and #{node_uid}:"
          pp diffs
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
        end

        count[site_uid][cluster_uid] += diffs.size

        # Remove the following line if you want to compare each nodes to the first cluster node
        refnode_uid = node_uid
        refnode = node

      end
      
    end
  end

  return count
end

def check_cluster_homogeneity(refapi_hash, verbose=false)
  puts "Differences found between successive nodes, per cluster:\n\n"

  count = cluster_homogeneity(refapi_hash, verbose)
  puts "\n" if verbose

  puts count.to_yaml unless verbose

  puts "\nUse '../input-validators/check-cluster-homogeneity.rb -v' for details." unless verbose
  
  return count
end

if __FILE__ == $0
  require 'optparse'

  options = {}

  OptionParser.new do |opts|
    opts.banner = "Usage: check-cluster-homogeneity.rb [options]"

    opts.separator ""
    opts.separator "Example: ruby check-cluster-homogeneity.rb -v"
    opts.separator ""

    opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
      options[:verbose] ||= 0
      options[:verbose] = options[:verbose] + 1
    end
  
    # Print an options summary.
    opts.on_tail("-h", "--help", "Show this message") do
      puts opts
      exit
    end
  end.parse!

  refapi_hash = load_yaml_file_hierarchy("#{dir}/../../input/grid5000/")
  check_cluster_homogeneity(refapi_hash, options.key?(:verbose))
end