Can't execute hook with the new Hook system // Autorestart VM

Hello,
I have OpenNebula 5.10.1 and I want to restart the VMs in case of a hardware reset or a server crash, and I have a hook created as follow:

ARGUMENTS="$ID"
COMMAND="/usr/bin/env onevm resume"
LCM_STATE=“UNKNOWN”
ON=“yes”
REMOTE=“YES”
RESOURCE=“VM”
STATE=“ACTIVE”

But I get this error:

$ onehook show 0 -e 15
HOOK 0 INFORMATION
ID : 0
NAME : autostart_hook
TYPE : state
LOCK : None

HOOK EXECUTION RECORD
EXECUTION ID : 15
TIMESTAMP : 01/20 17:41:10
COMMAND : /usr/bin/env onevm resume $ID
ARGUMENTS : $ID
EXIT CODE : 127

EXECUTION STDOUT

**EXECUTION STDERR **
/usr/bin/env: onevm: No such file or directory

With a OpenNebula 5.8 everything was working as expected and I can’t figure out what’s wrong.
Thanks for your help

Hello @Marco , didn’t you better want to run hook locally, on the frontend? See:

REMOTE=“NO”

Best regards,
Vlastimil

Hello @vholer
yes, that makes sense, thank you.
Anyway the problem is not solved and the error has changed:

 HOOK 1 INFORMATION                                                              
ID                : 1                   
NAME              : autostart_hook      
TYPE              : state               
LOCK              : None                

HOOK EXECUTION RECORD                                                           
EXECUTION ID      : 2                   
TIMESTAMP         : 01/21 16:36:10      
COMMAND           : /usr/bin/env onevm resume $ID 
ARGUMENTS         : $ID                 
EXIT CODE         : 255                 

EXECUTION STDOUT                                                                
Command resume requires one parameter to run
## USAGE
resume <range|vmid_list>
        Resumes the execution of the a saved VM
        
        States: STOPPED, SUSPENDED, UNDEPLOYED, POWEROFF, UNKNOWN
        valid options: schedule, weekly, monthly, yearly, hourly, end

## OPTIONS
     --schedule TIME           Schedules this action to be executed afterthe
                               given time. For example: onevm resume 0
                               --schedule "09/23 14:15"
     --weekly days             Repeats the schedule action the days of the week
                               specified, it can be a number between 0,6
                               separated with commas.For example: onevm resume
                               0 --schedule "09/23 14:15" --weekly 0,2,4
     --monthly days            Repeats the schedule action the days of the month
                               specified, it can be a number between 0,31
                               separated with commas.For example: onevm resume
                               0 --schedule "09/23 14:15" --monthly 0,14
     --yearly days             Repeats the schedule action the days of the year
                               specified, it can be a number between 0,365
                               separated with commas.For example: onevm resume
                               0 --schedule "09/23 14:15" --yearly 30,60
     --hourly hour             Repeats the schedule action each hours
                               specified,it can be a number between 0,168
                               separated with commas.For example: onevm resume
                               0 --schedule "09/23 14:15" --hourly 1,5
     --end number|TIME         ----
     -v, --verbose             Verbose mode
     -h, --help                Show this message
     -V, --version             Show version and copyright information
     --user name               User name used to connect to OpenNebula
     --password password       Password to authenticate with OpenNebula
     --endpoint endpoint       URL of OpenNebula xmlrpc frontend

EXECUTION STDERR                                                                

==============================================

$ onehook show 1
HOOK 1 INFORMATION                                                              
ID                : 1                   
NAME              : autostart_hook      
TYPE              : state               
LOCK              : None                

HOOK TEMPLATE                                                                   
ARGUMENTS="$ID"
COMMAND="/usr/bin/env onevm resume"
LCM_STATE="UNKNOWN"
RESOURCE="VM"
STATE="ACTIVE"

Hello @Marco

With new hooks system, there is no $ID, the argument is always $TEMPLATE, so you have to parse it to get the ID of the VM. You can find more information about state hooks here.

Ok @ahuertas, thanks
I will try to work it out.

Hi @ahuertas
I’m struggling again with this problem:
I looked the examples at the doc page you linked, and created a script like this:

# Hook template 
#
# NAME = autostart_hook_5.12
# TYPE = state
# STATE = ACTIVE
# LCM_STATE = UNKNOWN
# COMMAND = "autostart_hook_5.12.rb"
# ARGUMENTS = $TEMPLATE
# ON = CUSTOM
# RESOURCE = VM

#!/usr/bin/ruby

require 'base64'
require 'nokogiri'

#vm_template = Nokogiri::XML(Base64::decode64(STDIN.gets.chomp)) for reading from     STDIN
vm_template = Nokogiri::XML(Base64::decode64(ARGV[0]))

vm_id = vm_template.xpath("//ID").text.to_i

command = "/usr/bin/env onevm resume #{vm_id}"
exec command

I’ve created the hook but the execution fails with this error:

[E]: Failure executing hook 5 for VM/ACTIVE/UNKNOWN

oneadmin$ onehoook 5 0
Wrong numbers of arguments
No argument is required


oneadmin$ onehook show 5 -e 0
[snip]
EXECUTION STDERR                                                                
/var/lib/one/remotes/hooks/autostart_hook_5.12.rb: line 13: require: command not found
/var/lib/one/remotes/hooks/autostart_hook_5.12.rb: line 14: require: command not found
/var/lib/one/remotes/hooks/autostart_hook_5.12.rb: line 17: syntax error near unexpected token `('
/var/lib/one/remotes/hooks/autostart_hook_5.12.rb: line 17: `vm_template = Nokogiri::XML(Base64::decode64(ARGV[0]))'

I see the error “require: command not found”, so i tried to launch irb:

irb(main):001:0> require 'nokogiri';
Traceback (most recent call last):
    4: from /bin/irb:11:in `<main>'
    3: from (irb):1
    2: from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:59:in `require'
    1: from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:59:in `require'
LoadError (cannot load such file -- nokogiri)

Please, can anyone help me to find out the problem?
Any help is very appreciated

Hi @Marco,

Did you look at the alias_ip hook.rb in the hooks folder for inspiration?

I’d put the shebang as a first line in the script and include the folloing common magic that will include the neeed rubygems provided by opennebula

#!/usr/bin/env ruby

ONE_LOCATION = ENV['ONE_LOCATION']

if !ONE_LOCATION
    RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
    GEMS_LOCATION     = '/usr/share/one/gems'
    LOG_FILE          = '/var/log/one/hook-alias_ip.log'
else
    RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
    GEMS_LOCATION     = ONE_LOCATION + '/share/gems'
    LOG_FILE          = ONE_LOCATION + '/var/hook-alias_ip.log'
end

if File.directory?(GEMS_LOCATION)
    $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
    require 'rubygems'
    Gem.use_paths(File.realpath(GEMS_LOCATION))
end

$LOAD_PATH << RUBY_LIB_LOCATION
`

It is better to provide the VM template via stdin because the VM’s metadata could become a huge…

Best Regards,
Anton Todorov

1 Like

Yes @atodorov_storpool
that part was missing and did the trick!
Thank you so much!

I take inspiration from the official documentation examples, that I think needs an update because the initial part about lib, gems and log file locations is missing.

Anyway, this is the script I use to autorestart the VMs on a host after a reboot
Note that the VMs are deployed locally on the host using tm_mad SSH (no shared storage)

#!/usr/bin/env ruby

# Hook template 
#
# NAME = autostart_hook_5.12
# TYPE = state
# STATE = ACTIVE
# LCM_STATE = UNKNOWN
# COMMAND = "autostart_hook_5.12.rb"
# ARGUMENTS = $TEMPLATE
# ON = CUSTOM
# RESOURCE = VM

ONE_LOCATION = ENV['ONE_LOCATION']

if !ONE_LOCATION
    RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
    GEMS_LOCATION     = '/usr/share/one/gems'
    LOG_FILE          = '/var/log/one/hook-autorestart.log'
else
    RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
    GEMS_LOCATION     = ONE_LOCATION + '/share/gems'
    LOG_FILE          = ONE_LOCATION + '/var/hook-autorestart.log'
end

if File.directory?(GEMS_LOCATION)
    $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
    require 'rubygems'
    Gem.use_paths(File.realpath(GEMS_LOCATION))
end

$LOAD_PATH << RUBY_LIB_LOCATION

require 'base64'
require 'nokogiri'

vm_template = Nokogiri::XML(Base64::decode64(ARGV[0]))

vm_id = vm_template.xpath("//ID").text.to_i

command = "/usr/bin/env onevm resume #{vm_id}"
exec command
1 Like