Benutzer-Werkzeuge

Webseiten-Werkzeuge


linux:ansible_local_facts

Oracle System Umgebung für die Parametrisierung von Ansible Automatisierungen lokal hinterlegen

Aufgabe: In einer Oracle Umgebung mit zig Server soll auf jeden Server lokal die Oracle System Umgebung hinterlegt werden.

Mit diesen Informationen können dann später Oracle Aufgaben wie das Patchen der DB Umgebung in Ansible parametrisiert werden.

Lösung:

Verwendung von Local/Custum Ansible Facts

Diese Oracle Parameter wie Oracle Home etc. könnten als Host_vars auf dem Tower Server hinterlegt werden, müssten aber dann auch von Hand gepflegt oder mit Dynamischen Inventory Plugins etc. erzeugt werden.

Hier ist es einfacher lokal auf den Zielrechner diese Information als „Local Fact“ zu hinterlegen.

Zumal sich diese auch dynamisch während der Laufzeit erzeugen lassen.


Verbreitung

Das Asible Fact Verzeichnis als root anlegen:

#als root
 
mkdir -p /etc/ansible/facts.d/

Alle *.fact Dateien werden aus diesem Verzeichnis eingelesen.

Die *.fact Dateien können im ini. oder im Json Format hinterlegt werden.

Ist die Datei ausführbar, kann auch dynamisch ein Ergebnis in Json Format zurückgegeben werden.

Darauf achten das der Ansible Service-User die Datei auch lesen und ausführen können muss!

Test der Grundfunktion

Facts als im ini Format: vi /etc/ansible/facts.d/oracle.fact

[BASE]
ORACLE_BASE=/app/oracle
[HOME]
ORACLE_HOME=/app/oracle/19
[SID]
ORACLE_SID=gpi

Erster Test mit:

 ansible gpidb01 -m setup -a "filter=ansible_local"
 
..
 "ansible_facts": {
        "ansible_local": {
            "oracle": {
                "BASE": {
                    "oracle_base": "/app/oracle"
                },
                "HOME": {
                    "oracle_home": "/app/oracle/19"
                },
                "SID": {
                    "oracle_sid": "gpi"
 
..

YAML Format

Wie aber nun im YAML Format?

Problem : „ „oracle“: „error loading fact - please check content“

Wird wohl so nicht unterstützt? Scheint so zu sein.

Json Format testen

/etc/ansible/facts.d/oracle.fact

{
	"base": "/app/oracle",
	"homes": [{
			"sid": ["GPI", "PROD"],
			"home": "/app/oracle/19c",
			"owner": "oracle",
			"version": "19"
		},
		{
			"sid": [],
			"home": "/app/oracle/12c",
			"owner": "oracle",
			"version": "12"
		}
	]
}
ansible gpidb01 -m setup -a "filter=ansible_local"
 
gpidb01 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "oracle": {
                "base": "/app/oracle",
                "homes": [
                    {
                        "home": "/app/oracle/19c",
                        "owner": "oracle",
                        "sid": [
                            "GPI",
                            "PROD"
                        ],
                        "version": "19"
                    },
                    {
                        "home": "/app/oracle/12c",
                        "owner": "oracle",
                        "sid": [],
                        "version": "12"
                    }
                ]
            }
        },
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

Dynamisch erzeugen

Beim Dynamischen Erzeugen ist die Herausforderung das der Ansible Service User (der die Ansible Jobs ausführt) auch die Rechte benötigt um die Meta Daten aus dem OS zu lesen!

D.h. bei Bedarf muss zusätzlich noch über einen Sudo Komanndo Aufruf auf den Oracle User umgeschaltet werden, da sonst nicht alle Informationen erreichbar sind!

Datei rechte auf der Fact Datei:

chmod 777 oracle.fact

Das erste Skript mit etwas dynamischen Inhalt:

#!/bin/sh
 
time_stamp=`date`
 
cat <<EOF
{
        "time": "${time_stamp}",
        "base": "/app/oracle",
        "homes": [{
                        "sid": ["GPI", "PROD"],
                        "home": "/app/oracle/19c",
                        "owner": "oracle",
                        "version": "19"
                },
                {
                        "sid": [],
                        "home": "/app/oracle/12c",
                        "owner": "oracle",
                        "version": "12"
                }
        ]
}
EOF

Nun kann in Folge ein Bash Skript geschrieben werden das Json erzeugt.

Oder auch nicht .. Fehler : „oracle“: „error loading fact - please check content“ zeigt das irgendein Fehler passiert ist …

Glück hat wer auf der Maschine schon ein Programm für json wie „jo“ in der Schell hat ⇒ siehe https://jpmens.net/2016/03/05/a-shell-command-to-create-json-jo/ , ansonsten eben Json zu Fuß erzeugen.


Wie wird nun aber auf diese Facts in Ansible zugegriffen?

Ausgeben:

---
- name: List Oracle Parameter
  hosts: gpidb01

  pre_tasks:

   - set_fact:
      ORACLE_HOME:  "{{ ansible_local.oracle.homes[0].home  }}"
   - debug:
      var: ORACLE_HOME

  tasks:

   - debug:
       msg:
          - "Oracle Base is {{ ansible_local.oracle.base  }}"
          - "First Oracle Home is {{ ansible_local.oracle.homes[0]  }}"
          - "First Oracle Home path is {{ ansible_local.oracle.homes[0].home  }}"
          - "Global Oracle Home for this run is set to {{ ORACLE_HOME }}"

   - name : get Size of the oracle Folder
     command: "du -sk {{ ORACLE_HOME }}"
     become: yes
     become_user: oracle
     register: oracle_folder_size

   - set_fact:
      ora_size : "{{ oracle_folder_size.stdout.split()[0] }}"

   - debug:
      msg: "{{  ora_size }}"
ansible-playbook  getOracleHome.yml
 
 
TASK [debug] ******************************************************************************************************************************************
ok: [gpidb01] => {
    "msg": [
        "Oracle Base is /app/oracle",
        "First Oracle Home is {u'owner': u'oracle', u'home': u'/app/oracle/19c', u'version': u'19', u'sid': [u'GPI', u'PROD']}",
        "First Oracle Home path is /app/oracle/19c",
        "Global Oracle Home for this run is set to /app/oracle/19c"
    ]
}
 
TASK [get Size of the oracle Folder] 
********************
changed: [gpidb01]
 
TASK [set_fact] 
******************
ok: [gpidb01]
 
TASK [debug] 
*******************
ok: [gpidb01] => {
    "msg": "10290988"
}

Playbook um das Fact Skript dann am Ende auch auf alle Maschinen auszurollen

Nachdem alle Komponenten klar sind, kann auf den anderen Maschinen das per Ansible automatisch erstellt werden.

Mit den folgenden Playbook Beispiel wird dann das Skript um den lokalen Json Output zu erstellen verteilt:

---
- name:  Copy the Create Local Facts Script to the hosts
  hosts: all
  become: yes
  become_user: root

  vars:
    fact_dir: "/etc/ansible/facts.d"
    fact_filename: "oracle.fact"

  tasks:

  - name: create fact directory if not exits
     ansible.builtin.file:
      path: "{{ fact_dir  }}"
      state: directory

  - name: Copy Check Script
     ansible.builtin.template:
       src:  templates/setLocalDBFacts.sh.j2
       dest: "{{ fact_dir }}/{{ fact_filename }}
       owner: root
       group: root
       mode: '0777'

Das Fact Script liegt dabei unter „templates/setLocalDBFacts.sh.j2“.

Am Ende reicht aber diese Demo nicht aus, da ja der Ansible User nicht genug Rechte hat, daher wird nun über ein „oracle.fact“ nur ein weiters Schell Script mit Sudo aufgerufen um das eigentliche Schell Skript als Oracle User laufen lassen zu können.

Optimierte Lösung mit zwei Skripts

---
- name:  Copy the Create Local Facts Script to the hosts
  hosts: all
  become: yes
  become_user: root

  vars:
    fact_dir: "/etc/ansible/facts.d"
    fact_filename: "oracle.fact"
    fact_script:   "get_oracle_facts.sh"

  tasks:

  - name: create fact directory if not exits
    ansible.builtin.file:
      path: "{{ fact_dir  }}"
      state: directory

  - name: Copy Check Script
    ansible.builtin.template:
      src:  templates/setLocalDBFacts.sh.j2
      dest: "{{ fact_dir }}/{{ fact_script }}"
      owner: root
      group: root
      mode: '0777'

  - name: copy Fact Script oracle.fact.j2
    ansible.builtin.template:
      src:  templates/oracle.fact.j2
      dest: "{{ fact_dir }}/{{ fact_filename }}"
      owner: root
      group: root
      mode: '0777'

Das oracle.fact Skript:

#!/bin/sh
sudo -u oracle /etc/ansible/facts.d/get_oracle_facts.sh

Das eigentliche Skript um die Umgebung zu analysieren, optimiert für Datenbank und Weblogic Umgebungen:

#!/bin/bash
#
# get the local configuration of all oracle products on this server
#
# Version: gpi 02.2021
#
 
# ###############################################
# guess oracle base
if [ -d "/opt/oracle" ]; then
        ORACLE_BASE="/opt/oracle"
elif [ -d "/u01/app/oracle" ]; then
        ORACLE_BASE="/u01/app/oracle"
elif [ -d "/var/oracle" ]; then
        ORACLE_BASE="/var/oracle"
elif [ -d "/u00/app/oracle" ]; then
        ORACLE_BASE="/u00/app/oracle"
 
elif [ -d "/app/oracle" ]; then
        ORACLE_BASE="/app/oracle"
else
        ORACLE_BASE="~"
fi
 
export ORACLE_BASE
 
##############################################
 
 
if [ -f "/etc/oraInst.loc" ]; then
        # Read the Oracle Inventory if exists
        . /etc/oraInst.loc
        ORACLE_INVENTORY_HOME=${inventory_loc}
elif    [ -f "/var/opt/oracle/oraInst.loc" ]; then
        # Read the Oracle Inventory if exists
        . /var/opt/oracle/oraInst.loc
        ORACLE_INVENTORY_HOME=${inventory_loc}
else
  if [ -d "${ORACLE_BASE}/oraInventory" ]; then
        ORACLE_INVENTORY_HOME=${ORACLE_BASE}/oraInventory
  fi
fi
 
export ORACLE_INVENTORY_HOME
 
#######################################################
# preare json
FACT_STRING={\"base\":\"${ORACLE_BASE}\",\"inst_loc\":\"${ORACLE_INVENTORY_HOME}\",\"homes\":[
 
########################################################
 
 
## check for oracle homes
## search over inventory
##
 
if [ -d "${ORACLE_INVENTORY_HOME}/ContentsXML" ]; then
   # analyse the inventory
   ORAINVENTORY_LIST=`grep "HOME NAME" ${ORACLE_INVENTORY_HOME}/ContentsXML/inventory.xml | awk '{ print($2 "#" $3);}' | sed 's/"//g'`
 
 #echo ${ORAINVENTORY_LIST}
 
   ORA_HOME_COUNTER=0
 
   for  ORA_HOME_STRING in $ORAINVENTORY_LIST
     do
        ORA_PROD_TYPE=MW
 
        #echo ${ORA_HOME_STRING}
 
         ## subtract the string
        LOC_POS=`expr ${ORA_HOME_STRING} : '.*LOC'`
 
        let "LOC_POS=${LOC_POS}+1"
        ##printLine "LOC POS" "$LOC_POS"
        LOC_PATH=${ORA_HOME_STRING:$LOC_POS}
        ##printLine "PATH" ${LOC_PATH}
        let "LOC_POS=${LOC_POS}-10"
        ##printLine "LOC POS" "$LOC_POS"
        LOC_NAME=${ORA_HOME_STRING:5:$LOC_POS}
        ##printLine "LOC" ${LOC_NAME}
        ##printLine
 
        if [[ "${ORA_HOME_COUNTER}" -gt 0 ]]; then
          FACT_STRING=${FACT_STRING},
        fi
 
        FACT_STRING=${FACT_STRING}{\"home\":\"${LOC_PATH}\",\"sid\":[
 
        if [ -d "${LOC_PATH}/dbs" ]; then
 
          ORADB_LIST=`ls ${LOC_PATH}/dbs | grep -e spfile | sed 's/spfile//g' | sed 's/.ora//g' `
 
          ORA_SID_COUNTER=0
 
          ORA_PROD_TYPE=DB
 
          if [ "${ORADB_LIST}" != "" ]; then
              for ORAHOMESID in $ORADB_LIST
                do
 
                    if [[ "${ORA_SID_COUNTER}" -gt 0 ]]; then
                      FACT_STRING=${FACT_STRING},
                    fi
 
                    FACT_STRING=${FACT_STRING}\"${ORAHOMESID}\"
 
                    #debug
                    #echo DATABASE_ENV ${ORA_SID_COUNTER}] ${LOC_PATH} ${ORAHOMESID}
 
                    let "ORA_SID_COUNTER=${ORA_SID_COUNTER}+1"
                done
           fi
        else
           ORA_PROD_TYPE=MW
        fi
 
 
        if [ -d "${LOC_PATH}/user_projects" ];
        then
          ORA_PROD_TYPE=MW
        fi
 
 
        FACT_STRING=${FACT_STRING}],
 
 
        if [[ "${ORA_PROD_TYPE}" == "DB" ]]; then
 
           if [ -f "${LOC_PATH}/bin/oraversion" ]; then
              ORACLE_BASE_VER=`${LOC_PATH}/bin/oraversion -majorVersion`
              ORACLE_VERSION=`${LOC_PATH}/bin/oraversion -compositeVersion`
           else
               # get ver
               if [ -f "${LOC_PATH}/OPatch/opatch" ]; then
                 ORACLE_VERSION=`${LOC_PATH}/OPatch/opatch lsinventory -oh  ${LOC_PATH}  |  awk '/^Oracle Database/ {print $NF}'`
                 ORACLE_BASE_VER=${ORACLE_VERSION:0:2}
               else
                   # get ver middleware
                  ORACLE_BASE_VER=0.0
                  ORACLE_VERSION=0.0
              fi
          fi
 
        else
          if [ -f "${LOC_PATH}/bin/oraversion" ]; then
              ORACLE_BASE_VER=`${LOC_PATH}/bin/oraversion -majorVersion`
              ORACLE_VERSION=`${LOC_PATH}/bin/oraversion -compositeVersion`
           else
 
              if [ -f "${LOC_PATH}/wlserver/server/lib/build-versions.properties" ]; then
                 ORACLE_VERSION=`cat ${LOC_PATH}/wlserver/server/lib/build-versions.properties | grep version.fmwgenerictoken `
                 # normal version.fmwgenerictoken=12.2.1.4.0-190725.1822.0231
                 ORACLE_VERSION=$(echo $ORACLE_VERSION | cut -d'=' -f 2)
                 ORACLE_VERSION=${ORACLE_VERSION:0:8}
                 ORACLE_BASE_VER=${ORACLE_VERSION:0:2}
              else
                # get ver middleware
                ORACLE_BASE_VER=0.0
                ORACLE_VERSION=0.0
              fi
           fi
        fi
 
        FACT_STRING=${FACT_STRING}\"base_version\":\"${ORACLE_BASE_VER}\",
        FACT_STRING=${FACT_STRING}\"version\":\"${ORACLE_VERSION}\",
 
        # prod typ
        FACT_STRING=${FACT_STRING}\"type\":\"${ORA_PROD_TYPE}\"
 
        #close Oracle Home
        FACT_STRING=${FACT_STRING}}
 
 
        let "ORA_HOME_COUNTER=${ORA_HOME_COUNTER}+1"
 
   done
#else
#  echo "No ${ORACLE_INVENTORY_HOME}/ContentsXML/inventory.xml found"
fi
 
 
time_stamp=`date`
 
#######################################################
# preare json
FACT_STRING=${FACT_STRING}],\"time\":\"${time_stamp}\"}
 
#######################################################
 
echo ${FACT_STRING}

Quellen

Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
"Autor: Gunther Pipperr"
linux/ansible_local_facts.txt · Zuletzt geändert: 2022/02/11 16:11 von gpipperr