How to obtain a value from one host in a play, and apply the value on another host.

102 views
Skip to first unread message

Frits Hoogland

unread,
Dec 24, 2014, 8:59:04 AM12/24/14
to ansible...@googlegroups.com
I am trying to orchestrate a database replication setup. This means I need to read configuration details from the master node, and apply this on the slave to facilitate the replication setup.

I try to read a configuration value, which works (master has 'primary' set to true):

  - name: get audit file dest from database
    action: "shell export ORACLE_SID={{ oracle_sid }}; export ORACLE_HOME={{ oracle_home }}; printf \"set head off\nselect value from v\\$parameter where name = 'audit_file_dest';\" | $ORACLE_HOME/bin/sqlplus -S / as sysdba | grep -v ^$"
    when: primary
    register: audit_file_dest

Then I try to apply the value on the slave (slave has 'standby' set to true):

  - name: create audit file dest on standby
    file: path={{ audit_file_dest.stdout }} state=directory
    when: standby

This is how the execution looks like:

TASK: [get audit file dest from database] *************************************
skipping: [192.168.39.142]
changed: [192.168.39.139]

TASK: [create audit file dest on standby] *************************************
skipping: [192.168.39.139]
fatal: [192.168.39.142] => One or more undefined variables: 'dict object' has no attribute 'stdout'

When using the debug module, I see the problem:

TASK: [debug var=audit_file_dest] *********************************************
ok: [192.168.39.142] => {
    "audit_file_dest": {
        "changed": false,
        "skipped": true
    }
}
ok: [192.168.39.139] => {
    "audit_file_dest": {
        "changed": true,
        "cmd": "export ORACLE_SID=test; export ORACLE_HOME=/u01/app/oracle/product/11.2.0.4/dbhome_1; printf \"set head off\nselect value from v\\$parameter where name = 'audit_file_dest';\" | $ORACLE_HOME/bin/sqlplus -S / as sysdba | grep -v ^$",
        "delta": "0:00:00.035030",
        "end": "2014-12-24 15:54:41.230344",
        "invocation": {
            "module_args": "export ORACLE_SID=test; export ORACLE_HOME=/u01/app/oracle/product/11.2.0.4/dbhome_1; printf \"set head off\nselect value from v\\$parameter where name = 'audit_file_dest';\" | $ORACLE_HOME/bin/sqlplus -S / as sysdba | grep -v ^$",
            "module_name": "shell"
        },
        "rc": 0,
        "start": "2014-12-24 15:54:41.195314",
        "stderr": "",
        "stdout": "/u01/app/oracle/admin/test/adump",
        "stdout_lines": [
            "/u01/app/oracle/admin/test/adump"
        ],
        "warnings": []
    }
}

Because I try to use the variable on an host on which the variable was not filled, there is not stdout for it.
How can I simply obtain a value on one host for use on another? In this case I would love to make the registered variable contents global.
It can't be that this is a unique situation? Or is there another way that I should do this?

Thanks


Brian Coca

unread,
Dec 24, 2014, 9:04:36 AM12/24/14
to ansible...@googlegroups.com
register stays on the host and gets reset in the loop to reflect the
task was skipped, you might want to use a subsequent set_fact and then
access the variable thourgh hostvars[<primary_host_name>].

--
Brian Coca

Frits Hoogland

unread,
Dec 24, 2014, 9:14:08 AM12/24/14
to ansible...@googlegroups.com
Thank you Brian!

Can you help me a bit with that?

Please mind I created a group of one called 'primary' and a group of one called 'standby' in the hosts file, not sure if that can be used.
I used that to have specific per node variables declared.

It would really help in this specific case to have a value/status obtained on one node to configure the other or others. How is that normally done with Ansible?

Cheers, 
Frits

Brian Coca

unread,
Dec 24, 2014, 9:21:53 AM12/24/14
to ansible...@googlegroups.com
you can access the data from other nodes through hostvars:

hostvars[<hostname>][<varname>]
> --
> You received this message because you are subscribed to the Google Groups
> "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ansible-project/b83afdb7-fa71-4d82-84d5-07f99beaed87%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Brian Coca

Frits Hoogland

unread,
Dec 24, 2014, 9:33:44 AM12/24/14
to ansible...@googlegroups.com
Thank you again Brian, for all your help.

As I've stated in the explanation of the problem, I've declared groups in the host file. It's a group of one, but still a group.
I solved this in the following way:

1. get the value 

  - name: get audit file dest from database
    action: "shell export ORACLE_SID={{ oracle_sid }}; export ORACLE_HOME={{ oracle_home }}; printf \"set head off\nselect value from v\\$parameter where name = 'audit_file_dest';\" | $ORACLE_HOME/bin/sqlplus -S / as sysdba | grep -v ^$"
    when: primary
    register: audit_file_dest

2. set the registered variable as fact

  - name: register audit file dest
    set_fact: audit_file_dest="{{ audit_file_dest.stdout }}"
    when: primary

3. call the fact from another host via the group name and (mandatory, as far as I can see) host group number:

  - name: create audit file dest on standby
    file: path={{ hostvars[groups['primary'][0]]['audit_file_dest'] }} state=directory
    when: standby

Cheers,
Frits
Reply all
Reply to author
Forward
0 new messages