Pythian Blog: Technical Track

Cloning Oracle grid infrastructure using Ansible

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: [code language="python" gutter="false" highlight="5,13,21,26,29,32,35,38,46,50,54,57,60,67,70,73"] --- - hosts: all become: true tasks: - name: create directory for GI file: path: "" state: directory owner: "" group: "" mode: 0755 - name: unpack GI image unarchive: extra_opts: ['--strip-components=1', '--show-stored-names'] src: "/gi_.tar.gz" dest: "" owner: "" group: "" - name: clone GI become_user: "" shell: "/oui/bin/runInstaller -silent -clone -defaultHomeName -waitforcompletion \\ ORACLE_BASE=\"\" ORACLE_HOME=\"\" " - name: execute orainstRoot.sh shell: "/orainstRoot.sh" - name: change rootmacro script to receive output to screen lineinfile: dest="/install/utl/rootmacro.sh" regexp='^OUI_SILENT=true$' line='OUI_SILENT=false' create=no - name: execute root.sh shell: "/root.sh" - name: configure GI shell: "/perl/bin/perl -I/perl/lib -I/crs/install /crs/install/roothas.pl" - name: add listener.ora to GI home template: src: listener.ora.j2 dest: "/network/admin/listener.ora" owner: "" group: "" mode: 0644 - name: add listener become_user: "" shell: "/bin/srvctl add listener -endpoints \"TCP:\"" - name: start listener become_user: "" shell: "/bin/srvctl start listener" - name: create UDEV rules script: templates/setup_disk.sh.j2 - name: load UDEV rules shell: partprobe; udevadm control --reload-rules - name: copy init ASM file template: src: init+ASM.ora.j2 dest: "/dbs/init+ASM.ora" owner: "" group: "" - name: add asm shell: "/bin/srvctl add asm -spfile '/dbs/init+ASM.ora' -d " - name: start asm shell: "/bin/srvctl start asm" - name: create dg become_user: "" shell: "cd /bin; ./asmca -silent -createDiskGroup -diskGroupName -diskList -redundancy EXTERNAL -sysAsmPassword " [/code] There are variables coming for playbook that can be defined like that: [code lang="python" gutter="false"] --- 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: "/product//grid" lsnr_port: 1521 [/code] In the playbook also templates are used for listener.ora, init+ASM.ora and to setup UDEV rules: -- listener.ora.j2 [code] LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = )(PORT = )) ) ) ADR_BASE_LISTENER = ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON [/code] -- init+ASM.ora.j2 [code lang="bash" gutter="false"] *.asm_diskstring= *.instance_type='asm' [/code] -- setup_disk.sh.j2 [code lang="bash" gutter="false"] #!/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 [/code] Execution of the playbook on the Oracle Enterprise Linux 6 server with satisfied prerequisites will lead to results: [code collapse="true" gutter="false"] 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 [/code] 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.

No Comments Yet

Let us know what you think

Subscribe by email