How correctly get variables from Template in hook?

Hello.
How can get variables from a xml template in a hook?
I have the hook:

ARGUMENTS = "$TEMPLATE"
ARGUMENTS_STDIN = yes
COMMAND   = "test/test.sh"
NAME      = "test"
ON        = "CUSTOM"
STATE     = "ACTIVE"
LCM_STATE = "RUNNING"
REMOTE    = "no"
RESOURCE  = VM
TYPE      = state

And i need get ETH0_IP and NAME from xml.
How correctly do it?

Hello.

I personally did like in the examples provided in sources, for example, from the autostart hook:

raw_vm_template = Base64.decode64(ARGV[0])
xml_vm_template = Nokogiri::XML(raw_vm_template)

VM_ID = xml_vm_template.xpath('VM/ID').text

So, you only need to know the XPATH you need /VM/NAME and /VM/TEMPLATE/CONTEXT/ETH0_IP in your case, this should do the job:

raw_vm_template = Base64.decode64(ARGV[0])
xml_vm_template = Nokogiri::XML(raw_vm_template)

VM_NAME = xml_vm_template.xpath('/VM/NAME').text
VM_ETH0_IP = xml_vm_template.xpath('/VM/TEMPLATE/CONTEXT/ETH0_IP').text

Regards.

1 Like

Hello.
Thank you for reply.
Can i use the same, but in shell, without ruby?

For shell usage, you should look at how it’s done in some MAD like the kvm MAD scripts.

1 Like

I’ve created the hook:

ARGUMENTS       = "$TEMPLATE"
ARGUMENTS_STDIN = "yes"
COMMAND         = "test.sh"
NAME            = "test"
ON              = "CUSTOM"
STATE           = "ACTIVE"
LCM_STATE       = "RUNNING"
REMOTE          = "no"
RESOURCE        = "VM"
TYPE            = "state"

And the test.sh script:

#!/bin/bash

XPATH="/var/lib/one/remotes/datastore/xpath.rb --stdin"

TEMPLATE="$1"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH -b $TEMPLATE '/VM/ID')

VM_ID="${XPATH_ELEMENTS[j++]}"

echo "$VM_ID" > /tmp/test.txt

Hook runs correctly, but the file /tmp/test.txt is empty.

Did you check that $1 got the template, I think it should be base64 -d before being used or something like that.

Try:

#!/bin/bash

XPATH="/var/lib/one/remotes/datastore/xpath.rb --stdin"

TEMPLATE="$1"
echo "$TEMPLATE" > /tmp/template-test.txt
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH -b $TEMPLATE '/VM/ID')

VM_ID="${XPATH_ELEMENTS[j++]}"

echo "$VM_ID" > /tmp/test.txt
1 Like

I’ve added this lines to my script:

TEMPLATE=`base64 -d $1`
echo "$TEMPLATE" > /tmp/template-test.txt

And the file /tmp/template-test.txt contains a full template)

But the script doesn’t work correctly and i get the error:

base64: invalid input
/var/lib/one/remotes/datastore/xpath.rb:70:in `block in <main>': undefined method `elements' for nil:NilClass (NoMethodError)
        from /var/lib/one/remotes/datastore/xpath.rb:64:in `each'
        from /var/lib/one/remotes/datastore/xpath.rb:64:in `<main>'

Ok, just to be sure:

# Be sure input is base64 encoded
echo "$1" > /tmp/first-arg.txt

# First argument is a filename, so read standard input
TEMPLATE=$(echo -n $1 | base64 -d)
echo "$TEMPLATE" > /tmp/template-test.txt
1 Like

The file /tmp/first-arg.txt is empty.
And the file /tmp/template-test.txt empty too.((

You configured your hook with ARGUMENTS_STDIN = "yes", so “$1” is not defined, in this case you must read the data from STDIN

1 Like

How read data from STDIN in my case?

I think the mistake can be in this construction:

XPATH="/var/lib/one/remotes/datastore/xpath.rb --stdin"

TEMPLATE="base64 -d $1"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH -b $TEMPLATE '/VM/ID')

VM_ID="${XPATH_ELEMENTS[j++]}"

echo "$VM_ID" > /tmp/test.txt

For example, you could take a look at how to handle the stdin from vmm/kvm/restore script one/restore at master · OpenNebula/one · GitHub

In your case, if the stdin stream is base64 encoded, you need to just read it with cat and use xpath.rb to do the decode to raw XML the following sample should work

XPATH="/var/lib/one/remotes/datastore/xpath.rb --stdin"

TEMPLATE="$(cat)"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH -b $TEMPLATE '/VM/ID')
VM_ID="${XPATH_ELEMENTS[j++]}"

Hope this helps.

Best Regards,
Anton Todorov

1 Like

Works fine.
Thank you so much

Thank you for reply.

Thanks For this solution Its really helped me alot I was facing since many days

Hello @atodorov_storpool @ahuertas @amarti
I am facing some issues with API Hook for VM actions.
Can we create hook on adding actions to VM? like I want to run script as soon as I have added action on VM such as poweroff or terminate.
I am using below hook tmpl but not working.

NAME = hook-API
TYPE = api
COMMAND = “log_new_action.rb”
ARGUMENTS = $API
CALL = “one.user.action”
ARGUMENTS_STDIN = yes

Could you please suggest if possible.

Thanks!

Thanks For this solution..