oar-properties.rb 5.05 KB
Newer Older
1 2
#!/usr/bin/ruby

3 4
# Generator for the OAR properties

5 6 7 8 9 10
require 'pp'
require 'erb'
require 'fileutils'
require 'pathname'
require 'json'
require 'time'
11 12 13 14
require 'yaml'
require 'hashdiff'
require 'optparse'
require 'net/ssh'
15

16
require '../oar-properties/lib/lib-oar-properties'
17 18
require '../lib/input_loader'

19
options = {}
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
20
options[:sites] = %w{grenoble lille luxembourg lyon nancy nantes reims rennes sophia}
21
options[:diff]  = false
22

23 24
OptionParser.new do |opts|
  opts.banner = "Usage: oar-properties.rb [options]"
25

26 27 28 29 30 31 32
  opts.separator ""
  opts.separator "Example: ruby oar-properties.rb -v -s nancy -d oarnodes-%s.yaml -o cmd-%s.sh"

  opts.separator ""
  opts.separator "Filters:"

  ###
33

34 35
  opts.on('-s', '--sites a,b,c', Array, 'Select site(s)',
                                        "Default: "+options[:sites].join(", ")) do |s|
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
36
    raise "Wrong argument for -s option." unless (s - options[:sites]).empty?
37
    options[:sites] = s
38
  end
39 40 41

  opts.on('-c', '--clusters a,b,c', Array, 'Select clusters(s). Default: all') do |s|
    options[:clusters] = s
42 43
  end

44 45
  opts.on('-n', '--nodes a,b,c', Array, 'Select nodes(s). Default: all') do |n|
    options[:nodes] = n
46 47
  end

48
  ###
49

50 51
  opts.separator ""
  opts.separator "Output options:"
52

53 54 55
  opts.on('-o', '--output', 'Output oarnodesetting command into a file. Default: stdout') do |o|
    options[:output] = o
  end
56

57 58 59 60 61 62 63 64 65 66 67 68 69
  opts.on('-e', '--exec', 'Directly apply the changes to the OAR server') do |e|
    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
70
    
71 72 73 74 75
  ###

  opts.separator ""
  opts.separator "Common options:"

Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
76 77 78
  opts.on("-v", "--[no-]verbose", "Run verbosely", "Multiple -v options increase the verbosity. The maximum is 3.") do |v|
    options[:verbose] ||= 0
    options[:verbose] = options[:verbose] + 1
79
  end
80 81 82 83 84 85 86 87
  
  # Print an options summary.
  opts.on_tail("-h", "--help", "Show this message") do
    puts opts
    exit
  end
end.parse!

Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
88
puts "Options: #{options}" if options[:verbose]
89

90 91 92
nodelist_properties = {} # ["ref"]  : properties from the reference-repo
                         # ["oar"]  : properties from the OAR server
                         # ["diff"] : diff between "ref" and "oar"
93 94

#
95
# Get the OAR properties from the reference-repo (["ref"])
96 97
#

98
nodelist_properties["ref"] = {}
99
global_hash = load_yaml_file_hierarchy('../../input/grid5000/')
100 101 102
options[:sites].each { |site_uid| 
  nodelist_properties["ref"][site_uid] = get_nodelist_properties(site_uid, global_hash["sites"][site_uid]) 
}
103 104

#
105
# Get the current OAR properties from the OAR scheduler (["oar"])
106 107 108
#

nodelist_properties["oar"] = {}
109 110
options[:sites].each { |site_uid| 
  nodelist_properties["oar"][site_uid] = {}
111

112 113 114 115 116 117
  # This is only needed for the -d option  
  if options[:diff]
    filename = options[:diff].is_a?(String) ? options[:diff].gsub("%s", site_uid) : nil
    nodelist_properties["oar"][site_uid] = oarcmd_get_nodelist_properties(site_uid, filename)
  end
}
118 119 120 121

#
# Diff
#
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
122 123
header ||= false
prev_diff = {}
124

125
nodelist_properties["to_be_updated"] = {}
126

127 128
nodelist_properties["ref"].each { |site_uid, site_properties| 
  
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
129
  site_properties.each_filtered_node_uid(options[:clusters], options[:nodes]) { |node_uid, node_properties_ref|
130
      
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
131
    node_properties_oar = nodelist_properties["oar"][site_uid][node_uid]
132
      
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
133
    diff      = diff_node_properties(node_properties_oar, node_properties_ref)
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
134 135 136 137
    diff_keys = diff.map{ |hashdiff_array| hashdiff_array[1] }
    
    nodelist_properties["to_be_updated"][node_uid] = node_properties_ref.select { |key, value| diff_keys.include?(key) }
    
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
138 139
    case options[:verbose]
    when 1
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
140
      puts "#{node_uid}: #{diff_keys}"
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
    when 2
      # Give more details
      # puts "#{node_uid}: #{diff}"
      if !header
        header=true
        puts "Output format: ['~', 'key', 'old value', 'new value']"
      end
      if diff.size==0
        puts "  #{node_uid}: OK"
      elsif diff == prev_diff
        puts "  #{node_uid}: as above"
      else
        puts "  #{node_uid}:"
        diff.each { |d| puts "    #{d}" } 
      end
      prev_diff = diff
    when 3
      # Even more details
      puts JSON.pretty_generate({node_uid => {"old values" => node_properties_oar, "new values" => node_properties_oar}})
160
    end
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
161
  }
162 163
  
}
164 165

#
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
166
# Output commands
167
#
Jérémie Gaidamour's avatar
Jérémie Gaidamour committed
168 169 170 171 172 173 174 175 176 177

# nodelist_properties["ref"].each { |site_uid, site_properties| 
  
#   site_properties.each_filtered_node_uid(options[:clusters], options[:nodes]) { |node_uid, node_properties_ref|
      
#     puts oarcmd_set_node_properties("graphene-1", node_properties["oar"])
#     puts oarcmd_set_node_properties("graphene-1", node_properties["to_be_updated"])

#   }
# }