#!/usr/bin/env ruby

##############################################################################
# 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

def _wait(vm, st)
    wait = 0
    while vm.status != st
        vm.info
        if vm.status == 'unkn'
          break
        end
        wait += INTERVAL
        sleep(INTERVAL)
        if wait >= MAXWAIT
            break
        end
    end
end

def CreoleGet(variable)
    begin
        value = `CreoleGet #{variable}`
        return value
    rescue
        return nil
    end
end

#
# NAME: _do_suspend
# PARAM: OpenNebula::VirtualMachine object
# AIM: Suspend a virtual machine
#
def _do_suspend(vm, wait)
    fd = File.open(RUNVMFILE,'a')
    if vm.status == "runn"
        puts("Suspending #{vm.name} ...")
        fd.write("#{vm.id}\n")
        vm.suspend
        if wait
            _wait(vm, "susp")
        end
    end
    fd.close
end

#
# NAME: _do_resume
# PARAM: OpenNebula::VirtualMachine object
# AIM: Resum a suspended virtual machines
#
def _do_resume(vm, wait, force=FALSE)
    if force
      vm.resume
    else
      if vm.status == "susp"
        puts("Resume on #{vm.name}")
        vm.resume
        #    elsif vm.status == 'save'
        #      puts("Recover on #{vm.name}")
        #      # Try to recover VM with retry action
        #      vm.recover(2)
        #      vm.resume
      elsif vm.status == 'unkn'
        puts("Resume on #{vm.name}")
        vm.resume
      else
        return -1
      end
    end

    if wait
      _wait(vm, "runn")
    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', 'Wait for action ends') do |w|
      options[:wait] = w
  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

# Actions
SUPPORTED = ['status', 'boot', 'resume', 'shutdown', 'suspend']


if not SUPPORTED.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

begin
  client = Client.new(CREDENTIALS, options[:endpoint])

  vm_pool = VirtualMachinePool.new(client, USERFLAG)

  if File.exist?(RUNVMFILE)
    running_vms = File.readlines(RUNVMFILE)
  else
    running_vms = []
  end

  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

  vm_pool.each do |vm|
    case options[:action]
    when "status"
      puts("#{vm.name}\t#{vm.status}")
    when "boot"
      puts("DEBUG #{vm.status}")
      if vm.status == "unkn"
        puts("Booting #{vm.name} ...")
        vm.boot
      end
    when "suspend"
        _do_suspend(vm, options[:wait])
    when "resume"
      if running_vms.include?("#{vm.id}\n")
        _do_resume(vm, options[:wait], TRUE)
      end
    else
      puts("#{vm.name}\t#{vm.status}")
    end
  end
  if options[:action] == "resume"
    File.truncate(RUNVMFILE, 0) if File.exists?(RUNVMFILE)
  end
rescue Exception => e
  puts e.message
  exit(-1)
end
exit 0
