eole-one-master/scripts/onevm-all
Daniel Dehennin 340dd409e2 The VMs are not always resumes on reboot
The “libvirt-guests” service can conflict with “onevm-all” and we
don't need to wait for each VM to boot during start.

* posttemplate/10-libvirt-guests: disable the “libvirt-guests” service.

* init/onenode.service (ExecStart): use default wait timeout (60s).
  (TimeoutStartSec): wait for longer than the default timeout.
  (ExecReload): just try to resume any remaining VMs.
  (ExecStop): wait longer for VM to suspend.
  (TimeoutStopSec): wait for longer than the stop timeout.

* scripts/onevm-all: schedule actions in parallel and wait globally
  for their executions.

Ref: #22155
2017-12-20 16:32:13 +01:00

280 lines
5.9 KiB
Ruby
Executable File

#!/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: