#!/usr/bin/env ruby # Do not buffer output STDOUT.sync = TRUE ############################################################################## # Environment Configuration ############################################################################## ONE_LOCATION=ENV["ONE_LOCATION"] USER=ENV["user"] RUNVMFILE="/var/lib/one/running.bck" TIMEOUT=20 # oneadmin user flag value USERFLAG=-2 if !ONE_LOCATION RUBY_LIB_LOCATION="/usr/lib/one/ruby" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" end $: << RUBY_LIB_LOCATION ############################################################################## # Required libraries ############################################################################## require 'opennebula' require 'optparse' include OpenNebula MAXWAIT=60 INTERVAL=1 # List of supported actions ACTIONS = [ 'status', # Get the status of all VMs in OpenNebula VM pool 'suspend', # Suspend all VMs in RUNNING state 'resume', # Resume all VMs in SUSPENDED or UNKNOWN state ] # Map each action with a target state EXPECTED_STATUS_MAP = { 'status' => nil, 'boot' => 'runn', 'suspend' => 'susp', 'resume' => 'runn' } def dump_running_vms_file() if File.exist?(RUNVMFILE) running_vms = File.readlines(RUNVMFILE).uniq else running_vms = [] end return running_vms end def CreoleGet(variable) begin value = `CreoleGet #{variable}` return value rescue return nil end end def _do_wait(vms, action, maxwait) if maxwait == 0 and action == 'resume' # User explicitely don't want to wait vms.clear return 0 end print "Wait #{maxwait}s for VMs to #{action}" for try in 0..maxwait vms.delete_if do |vm| vm.info vm.status == EXPECTED_STATUS_MAP[action] end break if vms.empty? print "." sleep(1) end if vms.empty? puts " OK" return 0 else puts " FAIL" return -1 end end # # NAME: _do_suspend # PARAM: OpenNebula::VirtualMachine object # AIM: Suspend a virtual machine # def _do_suspend(vm) fd = File.open(RUNVMFILE,'a') if vm.status == "runn" puts("Suspending #{vm.id} - #{vm.name}... ") fd.write("#{vm.id}\n") rc = vm.suspend if OpenNebula.is_error?(rc) puts rc.message else puts "scheduled" end end fd.close end # # NAME: _do_resume # PARAM: OpenNebula::VirtualMachine object # AIM: Resum a suspended virtual machines # def _do_resume(vm) print("Resume #{vm.id} - #{vm.name}... ") rc = vm.resume if OpenNebula.is_error?(rc) puts rc.message else puts "scheduled" end end options = {:creds => nil, :action => nil, :endpoint => nil, :timeout => nil} parser = OptionParser.new do|opts| opts.banner = "Usage: #{File.basename(__FILE__)} [options]" opts.on('-c', '--creds file', 'Crediential file') do |value| options[:creds] = value; end opts.on('-a', '--action action', 'Action to run') do |value| options[:action] = value; end opts.on('-e', '--end-point url', 'End point URL') do |value| options[:endpoint] = value; end opts.on('-t', '--timeout timeout', 'Timeout for opennebula connection') do |value| options[:timeout] = value.to_i; end opts.on('-w', '--wait timeout', 'Wait for action ends') do |value| options[:wait] = value.to_i end opts.on('-h', '--help', 'Displays Help') do puts opts exit end end parser.parse! # OpenNebula credentials if not options[:creds] options[:creds] = "/var/lib/one/.one/one_auth" end if not options[:action] options[:action] = "status" end if not options[:endpoint] ip = CreoleGet('adresse_ip_eth0').chomp options[:endpoint] = "http://#{ip}:2633/RPC2" end if not options[:timeout] options[:timeout] = TIMEOUT end if not options[:wait] options[:wait] = MAXWAIT end if not ACTIONS.include?(options[:action]) puts("Action : #{options[:action]}) is not supported") exit(-1) end begin File.readlines(options[:creds]).each do |line| CREDENTIALS = line end rescue puts("#{options[:creds]}: Problem loading credentials, check if file exists.") exit(-1) end exit_code = 0 begin client = Client.new(CREDENTIALS, options[:endpoint]) vm_pool = VirtualMachinePool.new(client, USERFLAG) # Try to load vm pool infos from OpenNebula until timeout expires rc = vm_pool.info cnt = 0 while OpenNebula.is_error?(rc) if cnt == options[:timeout] puts rc.message exit(-1) end rc = vm_pool.info sleep(1) cnt += 1 end if options[:action] == "resume" running_vms = dump_running_vms_file() running_vms.each do |vmid| vm = VirtualMachine.new_with_id(vmid, client) vm.info _do_resume(vm) end else vm_pool.each do |vm| case options[:action] when "status" puts "#{vm.name}\t#{vm.status}" when "suspend" _do_suspend(vm) end end # Update list of suspended VMs running_vms = dump_running_vms_file() end if options[:action] != 'status' vms = [] running_vms.each do |vmid| vm = VirtualMachine.new_with_id(vmid, client) vms.push(vm) end exit_code = _do_wait(vms, options[:action], options[:wait]) end if options[:action] == "resume" if vms.empty? File.truncate(RUNVMFILE, 0) if File.exists?(RUNVMFILE) else fd = File.open(RUNVMFILE,'w') vms.each do |vm| fd.write("#{vm.id}\n") end end end rescue Exception => e puts e.message puts e.backtrace exit(-1) end exit(exit_code) # Local Variables: # ruby-indent-level: 4 # End: