Bug 1331798

Summary: Foreman hook host/managed/after_create runs before host has been created
Product: Red Hat Satellite Reporter: Göran Törnqvist <goran.tornqvist>
Component: Hooks and WebhooksAssignee: Lukas Zapletal <lzap>
Status: CLOSED NOTABUG QA Contact:
Severity: low Docs Contact:
Priority: unspecified    
Version: 6.1.8CC: amasolov, bbuckingham, hprakash
Target Milestone: UnspecifiedKeywords: Triaged
Target Release: Unused   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-06-15 10:42:05 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Göran Törnqvist 2016-04-29 14:22:07 UTC
Description of problem:

Im running a custom hook script in host/managed/after_create that does a:
hammer -u ****** -p ****** host set-parameter --host ${hostname} --name my_custom_parameter --value something
Problem is that I get a "Error: host not found" in return from hammer, the host doesn´t exist in foreman when the hook runs.

Tried forking out the command to a (sleep 10 ; hammer ...) & but forking doesn´t work for some reason in hooks.

Version-Release number of selected component (if applicable):
Satellite 6.1.8

How reproducible:
85% of the time. Sometimes the host exists and the parameter is added but mostly it doesn´t.

Steps to Reproduce:
1. Create hook /usr/share/foreman/config/hooks/host/managed/after_create/99_host_create.sh
2. Run hammer command as above in the script and log output to logfile

Actual results:
Logfile displays "Error: host not found"

Expected results:
Host exists when after_create is triggered.

Additional info:

Comment 2 Alexey Masolov 2017-06-13 23:53:04 UTC
Can reproduce the same problem with Satellite 6.2.9. 

# cat /usr/share/foreman/config/hooks/host/managed/after_create/10_fix_environment.sh 

#!/bin/sh

ACTION="$1"
FQDN="$2"

logger "foreman hook: executed $ACTION for $FQDN"

HOOK_OBJECT_FILE=$(mktemp -t foreman_hooks.XXXXXXXXXX)
cat > $HOOK_OBJECT_FILE

logger -t foreman-hook: $HOOK_OBJECT_FILE

ENV="` sed -e 's/^.*"environment_name":"\([^"]*\)".*/\1/g' <$HOOK_OBJECT_FILE`"
SOLLENV="` sed -e 's/^.*"hostgroup_title":"\([^"]*\)".*/\1/g' <$HOOK_OBJECT_FILE | awk -F/ '{ print $2}'`"
HOSTID="`sed -e 's/^.*"host":{[^{}]*"id":\([0-9]*\),.*$/\1/g' <$HOOK_OBJECT_FILE`"

logger -t foreman-hook: env $ENV sollenv $SOLLENV

if [ ! -z "$ENV" ]
then
    if [ "$ENV" != "$SOLLENV" ]
    then
       logger -t foreman-hook: "setting environment for $FQDN from $ENV to $SOLLENV"
       echo "hammer -u XXXXX -p XXXXX host update --id $HOSTID --environment $SOLLENV" 2>&1 | logger -t foreman-hook:
       hammer -u XXXXX -p XXXXX host update --id $HOSTID --environment $SOLLENV 2>&1 | logger -t foreman-hook:
    else
       logger "foreman-hook: $FQDN has correct Environment $ENV"
    fi
else
    which jgrep| logger -t foreman-hook:
fi


And the output is:
=================

May 19 13:32:07 satellite logger: foreman hook: executed after_create for host.example.com
May 19 13:32:07 satellite foreman-hook:: /tmp/foreman_hooks.RkPnann3v9
May 19 13:32:07 satellite foreman-hook:: env KT_Library_20160801_sles11_85 sollenv Library
May 19 13:32:07 satellite foreman-hook:: setting environment for host.example.com from KT_Library_20160801_sles11_85 to Library
May 19 13:32:09 satellite foreman-hook:: hammer -u XXXXX-p XXXXXhost update --id 2805 --environment Library
May 19 13:32:10 satellite foreman-hook:: Could not update the host:
May 19 13:32:10 satellite foreman-hook::  Resource host not found by id '2805'

Comment 3 Lukas Zapletal 2017-06-15 10:42:05 UTC
Hello, unfortunately you cannot use hammer command with hosts which are currently being processed by the hook itself. The database transaction is not yet complete. Foreman hooks executes the script in separate context, so it is not possible to directly modify the ActiveRecord objects yet. RFE is filed as https://github.com/theforeman/foreman_hooks/issues/4

You can experience random behaviour according to which worker process gets the request. Anyway, please avoid this completely. I suggest a workaround, create a separate script that will be spawned on the background and add sleep command there, or create a service or process that will do the required tasks and communicate the data via UNIX sockets.

Also an alternative is to create Foreman plugin in Ruby that can do anything you want during any transaction:

http://projects.theforeman.org/projects/foreman/wiki/How_to_Create_a_Plugin

Take foreman_hooks as an example but implement the required code as separate plugin. Then you can modify the host object as needed:

https://github.com/theforeman/foreman_hooks

Comment 4 hprakash 2017-07-14 06:33:24 UTC
@lzap, thanks for your input.