Cloning Oracle Grid Infrastructure Using Ansible

Posted in: DBA Lounge, Oracle, Technical Track

Sometimes your organization may decide to move to new hardware, to new data center and you, as an Oracle DBA, would need to be involved in preparation and configuration of new servers at new location. It is very often that such rare opportunity can be considered as possibility to upgrade OS, Grid infrastructure, standardize environment.

If there are several servers and a lot of time for preparation and execution it can be done manually without any automation.

However it is a rare case and if you are dealing with dozens of servers and timeline is strict then you need to plan and automate routine tasks which you would perform for new installations.

Ansible is a great tool for it. It connects to servers and simplifies routine tasks with great flexibility and enhancement allowing to code different conditions.

My colleague Fred Denis already blogged about it recently here and you can see it is a tool that’s very easy to manage.

So certainly it can be a good choice to simplify and repeat routine DBA tasks like cloning of oracle software during preparation for the migration to new environment.

Considering the case I described before, it’s likely that there are system administrators in the organization who would perform OS installation for you and might even perform prerequisites such as installing packages, changing kernel parameters, etc.

There is high chance they use automation tools like Chef, Puppet, etc. even Ansible, but can be busy with other tasks. You also definitely want to keep something for yourself and shine as well to see how easy and quick an environment can be configured when it is automated.

Going further close to the task, let’s automate Grid Infrastructure 12.1 cloning for standalone server configured with ASM. Ansible operates by tasks, so software cloning can be presented as list of actions:

  • Copy (make available) prepared a clone image to a new server
  • Unpack the image
  • Perform clone operation
  • Execute root.sh
  • Configure Grid Infrastructure
  • Configure disk devices
  • Configure listener
  • Configure ASM
  • Create disk group

These actions can be presented as tasks in Ansible with following modules usage and conditions given a playbook like this:

---
  - hosts: all
    become: true
    tasks:
    - name: create directory for GI
      file:
        path: "{{ gi_home_path }}"
        state: directory
        owner: "{{ oracle_user }}"
        group: "{{ oracle_group }}"
        mode: 0755

    - name: unpack GI image
      unarchive:
        extra_opts: ['--strip-components=1', '--show-stored-names']
        src: "{{ image_path }}/gi_{{ ver }}.tar.gz"
        dest: "{{ gi_home_path }}"
        owner: "{{ oracle_user }}"
        group: "{{ oracle_group }}"

    - name: clone GI
      become_user: "{{ oracle_user }}"
      shell: "{{ gi_home_path }}/oui/bin/runInstaller -silent -clone -defaultHomeName -waitforcompletion \\
            ORACLE_BASE=\"{{ gi_base_path }}\" ORACLE_HOME=\"{{ gi_home_path }}\" "

    - name: execute orainstRoot.sh
      shell: "{{ oracle_inventory }}/orainstRoot.sh"

    - name: change rootmacro script to receive output to screen
      lineinfile: dest="{{ gi_home_path }}/install/utl/rootmacro.sh" regexp='^OUI_SILENT=true$' line='OUI_SILENT=false' create=no

    - name: execute root.sh
      shell: "{{ gi_home_path }}/root.sh"

    - name: configure GI
      shell: "{{ gi_home_path }}/perl/bin/perl -I{{ gi_home_path }}/perl/lib -I{{ gi_home_path }}/crs/install {{ gi_home_path }}/crs/install/roothas.pl"

    - name: add listener.ora to GI home
      template:
        src: listener.ora.j2
        dest: "{{ gi_home_path }}/network/admin/listener.ora"
        owner: "{{ oracle_user }}"
        group: "{{ oracle_group }}"
        mode: 0644

    - name: add listener
      become_user: "{{ oracle_user }}"
      shell: "{{ gi_home_path }}/bin/srvctl add listener -endpoints \"TCP:{{ lsnr_port }}\""

    - name: start listener
      become_user: "{{ oracle_user }}"
      shell: "{{ gi_home_path }}/bin/srvctl start listener"

    - name: create UDEV rules
      script: templates/setup_disk.sh.j2 {{ udev_file }} {{ asm_disk }} {{ oracle_user }} {{ oracle_group }}

    - name: load UDEV rules
      shell: partprobe; udevadm control --reload-rules

    - name: copy init ASM file
      template:
        src: init+ASM.ora.j2
        dest: "{{ gi_home_path }}/dbs/init+ASM.ora"
        owner: "{{ oracle_user }}"
        group: "{{ oracle_group }}"

    - name: add asm
      shell: "{{ gi_home_path }}/bin/srvctl add asm -spfile '{{ gi_home_path }}/dbs/init+ASM.ora' -d {{ asm_disk }}"

    - name: start asm
      shell: "{{ gi_home_path }}/bin/srvctl start asm"

    - name: create dg
      become_user: "{{ oracle_user }}"
      shell: "cd {{ gi_home_path }}/bin;
              ./asmca -silent -createDiskGroup -diskGroupName {{ asm_dg_name }} -diskList {{ asm_disk }} -redundancy EXTERNAL -sysAsmPassword {{ asm_pass }}"

There are variables coming for playbook that can be defined like that:

---
ver: "12.1.0.2"
image_path: /software/oracle/image
oracle_user: oracle
oracle_group: oinstall

asm_instance: +ASM
asm_start: Y
asm_disk: /dev/asm-disk1
asm_pass: sys_pwd
asm_dg_name: DATA

udev_file: /etc/udev/rules.d/99-asm-devices.rules

oracle_inventory: /u01/app/oraInventory

gi_base_path: "/u01/app/oracle"
gi_home_path: "{{ gi_base_path }}/product/{{ ver | regex_replace('^(.*)\\.(.*)\\.(.*)\\.(.*)$', '\\1.\\2.\\3') }}/grid"

lsnr_port: 1521

In the playbook also templates are used for listener.ora, init+ASM.ora and to setup UDEV rules:

— listener.ora.j2

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = {{ ansible_nodename }})(PORT = {{ lsnr_port }}))
    )
  )
ADR_BASE_LISTENER = {{ gi_base_path }}
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON

— init+ASM.ora.j2

*.asm_diskstring={{ asm_disk }}
*.instance_type='asm'

— setup_disk.sh.j2

#!/bin/bash
UDEV_FILE=$1
device="/dev/sdb1"
label="$2"
scsi_id_bin="/sbin/scsi_id"
scsiid=`$scsi_id_bin -g -u -d $device`
echo "KERNEL==\"sd?1\", BUS==\"scsi\", PROGRAM==\"$scsi_id_bin -g -u -d /dev/\$parent\", RESULT==\"$scsiid\", NAME=\"$label\", OWNER=\"$3\", GROUP=\"$4\", MODE=\"0660\"" > $UDEV_FILE

Execution of the playbook on the Oracle Enterprise Linux 6 server with satisfied prerequisites will lead to results:

ansible-playbook example.yml -l oel6803

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [oel6803]

TASK [create directory for GI] *************************************************
changed: [oel6803]

TASK [unpack GI image] *********************************************************
changed: [oel6803]

TASK [clone GI] ****************************************************************
changed: [oel6803]

TASK [execute orainstRoot.sh] **************************************************
changed: [oel6803]

TASK [change rootmacro script to receive output to screen] *********************
changed: [oel6803]

TASK [execute root.sh] *********************************************************
changed: [oel6803]

TASK [configure GI] ************************************************************
changed: [oel6803]

TASK [add listener.ora to GI home] *********************************************
changed: [oel6803]

TASK [add listener] ************************************************************
changed: [oel6803]

TASK [start listener] **********************************************************
changed: [oel6803]

TASK [create UDEV rules] *******************************************************
changed: [oel6803]

TASK [load UDEV rules] *********************************************************
changed: [oel6803]

TASK [copy init ASM file] ******************************************************
changed: [oel6803]

TASK [add asm] *****************************************************************
changed: [oel6803]

TASK [start asm] ***************************************************************
changed: [oel6803]

TASK [create dg] ***************************************************************
changed: [oel6803]

PLAY RECAP *********************************************************************
oel6803                    : ok=17   changed=16   unreachable=0    failed=0

The playbook presented here is simple and there are no conditions, tags and other Ansible features, but it shows its simple structure and ability to automate routine DBA tasks.

As soon as you start developing using Ansible and automate routine DBA tasks you would not be stopping and will continue to create more playbooks, move them to roles, add conditions, implement new requirements, etc. certainly increasing value of your position within a company.

email

Interested in working with Andrey? Schedule a tech call.

No comments

Leave a Reply

Your email address will not be published. Required fields are marked *