diff --git a/roles/oradb-manage-statspack/README.md b/roles/oradb-manage-statspack/README.md new file mode 100644 index 000000000..fd8702f38 --- /dev/null +++ b/roles/oradb-manage-statspack/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Do not create the perfstat user before creating the statspack +inside the database. The detection of existing statspack installation +is based on the perfstat user. The installation will be skkipped when +user is existing. + +Role Variables +-------------- + +The following example only shows mandatory variables from oracle_databases: + +```yaml +oracle_databases: + - oracle_db_name: DB1 + oracle_db_type: SI + statspack: + state: present + tablespace: sysaux + tablespace_temp: temp + purgedays: 14 + snaplevel: 7 + snapinterval: "FREQ=hourly;byminute=0;bysecond=0" +``` + +Dependencies +------------ + +Author Information +------------------ + +Thorsten Bruhns diff --git a/roles/oradb-manage-statspack/defaults/main.yml b/roles/oradb-manage-statspack/defaults/main.yml new file mode 100644 index 000000000..5c7f3336e --- /dev/null +++ b/roles/oradb-manage-statspack/defaults/main.yml @@ -0,0 +1,26 @@ +--- +# Global Defaults for Purge and Snapshot-Jobs. +# could be overwritten per dtabase with: +# oracle_databases: +# - oracle_db_name: test +# statspack: +# purgedays: 60 +purgedays: 35 +purgeinterval: "FREQ=daily;byhour=3;byminute=15;bysecond=0" +snapinterval: "FREQ=hourly;byminute=0;bysecond=0" +snaplevel: 7 + +db_user: system +db_password_cdb: "{% if dbpasswords is defined and dbpasswords[dbh.oracle_db_name] is defined and dbpasswords[dbh.oracle_db_name][db_user] is defined%}{{dbpasswords[dbh.oracle_db_name][db_user]}}{% else %}{{ default_dbpass}}{% endif%}" # noqa yaml +db_password_pdb: "{%- if dbpasswords is defined and dbpasswords[pdb.0.cdb] is defined and dbpasswords[pdb.0.cdb][db_user] is defined -%} + {{dbpasswords[pdb.0.cdb][db_user]}} + {%- else -%} + {{ default_dbpass}} + {%- endif -%}" + +db_service_name: "{% if dbh is defined %} + {%- if dbh.oracle_db_unique_name is defined %}{{ dbh.oracle_db_unique_name }} + {%- elif dbh.oracle_db_instance_name is defined %}{{ dbh.oracle_db_instance_name }} + {%- else %}{{ dbh.oracle_db_name }} + {%- endif %} + {%- endif %}" diff --git a/roles/oradb-manage-statspack/files/spcreate.sh b/roles/oradb-manage-statspack/files/spcreate.sh new file mode 100644 index 000000000..374cc2125 --- /dev/null +++ b/roles/oradb-manage-statspack/files/spcreate.sh @@ -0,0 +1,43 @@ +#!/usr/bin/bash +set -euo pipefail + +cd $HOME + +env | grep ^ORACLE | sort + +PDB=${pdb_name:-"_"} + +${ORACLE_HOME}/bin/sqlplus -S -L /nolog < '_' then + execute immediate 'alter session set container = ${PDB}'; + end if; +end; +/ + +@?/rdbms/admin/spcreate + +set echo on +alter session set current_schema=perfstat; + +PROMPT Fixup for idle Events (old stupid bug from Oracle...) +-- Re-fill STATS\$IDLE_EVENT with latest idle events that Oracle regularly forgets to update. +delete from perfstat.STATS\$IDLE_EVENT; +insert into perfstat.STATS\$IDLE_EVENT select name from V\$EVENT_NAME where wait_class='Idle'; +commit; + +PROMPT Create custom index for selecting sql_id from STATS\$SQLTEXT +create index perfstat.STATS\$SQLTEXT_UK1 on STATS\$SQLTEXT(sql_id, piece); + +exit +EOF \ No newline at end of file diff --git a/roles/oradb-manage-statspack/files/spdrop.sh b/roles/oradb-manage-statspack/files/spdrop.sh new file mode 100644 index 000000000..f09a7b7b3 --- /dev/null +++ b/roles/oradb-manage-statspack/files/spdrop.sh @@ -0,0 +1,23 @@ +#!/usr/bin/bash +set -euo pipefail + +cd $HOME + +env | grep ^ORACLE | sort + +PDB=${pdb_name:-"_"} + +${ORACLE_HOME}/bin/sqlplus -S -L /nolog < '_' then + execute immediate 'alter session set container = ${PDB}'; + end if; +end; +/ + +@?/rdbms/admin/spdrop +exit +EOF \ No newline at end of file diff --git a/roles/oradb-manage-statspack/meta/main.yml b/roles/oradb-manage-statspack/meta/main.yml new file mode 100644 index 000000000..30ea1b718 --- /dev/null +++ b/roles/oradb-manage-statspack/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: orasw-meta diff --git a/roles/oradb-manage-statspack/tasks/main.yml b/roles/oradb-manage-statspack/tasks/main.yml new file mode 100644 index 000000000..a2d70600b --- /dev/null +++ b/roles/oradb-manage-statspack/tasks/main.yml @@ -0,0 +1,274 @@ +--- +- block: + - name: oradb-manage-statspack | Drop Statspack Schema + script: spdrop.sh + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ dbh.oracle_db_instance_name | default(dbh.oracle_db_unique_name | default(dbh.oracle_db_name)) }}" + with_items: "{{ oracle_databases }}" + loop_control: + loop_var: dbh + label: "{{ dbh.oracle_db_name }}" + register: statspackdropcmd + become: true + become_user: "{{ oracle_user }}" + when: + - dbh.statspack is defined + - dbh.statspack.state | default('present') == 'absent' + + - debug: msg="{{ item.stdout_lines }}" # noqa unnamed-task + with_items: + - "{{ statspackdropcmd.results }}" + loop_control: + label: "" + when: + - statspackdropcmd is defined + - item.stdout_lines is defined + + tags: + - spdrop + - spcdb + +- block: + - name: oradb-manage-statspack | Create Statspack Schema (existing user is ignored) + script: spcreate.sh + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ dbh.oracle_db_instance_name | default(dbh.oracle_db_unique_name | default(dbh.oracle_db_name)) }}" + perfstat_password: "{{ db_password_cdb }}" + temporary_tablespace: "{{ dbh.statspack.tablespace_temp | default('temp') }}" + default_tablespace: "{{ dbh.statspack.tablespace | default('sysaux') }}" + purgedates: "{{ dbh.statspack.purgedays | default(35) }}" + snaplevel: "{{ dbh.statspack.snaplevel | default(7) }}" + with_items: "{{ oracle_databases }}" + loop_control: + loop_var: dbh + label: "{{ dbh.oracle_db_name }}" + register: statspackcmd + become: true + become_user: "{{ oracle_user }}" + failed_when: + - statspackcmd.rc != 0 + - '"ORA-01920:" not in statspackcmd.stdout' # ORA-01920: user name 'PERFSTAT' conflicts with another user + when: + - dbh.statspack is defined + - dbh.statspack.state | default('present') == 'present' + + - debug: msg="{{ item.stdout_lines }}" # noqa unnamed-task + with_items: + - "{{ statspackcmd.results }}" + loop_control: + label: "" + when: + - statspackcmd is defined + - item.stdout_lines is defined + tags: + - spcreate + - spcdb + +- name: oradb-manage-statspack | Create/Modify Purge Job + oracle_job: + hostname: "{{ ansible_hostname }}" + service_name: "{{ db_service_name }}" + port: "{{ dbh.listener_port | default(listener_port | default(1521)) }}" + user: "{{ db_user }}" + password: "{{ db_password_cdb }}" + job_name: "PERFSTAT.PURGE" + comments: "Statspack Purge-Job" + job_type: "plsql_block" + job_action: "PERFSTAT.STATSPACK.PURGE({{ dbh.statspack.purgedays | default(purgedays) }});" + logging_level: "runs" + repeat_interval: "{{ dbh.statspack.purgeinterval | default(purgeinterval) }}" + state: "present" + + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ dbh.oracle_db_instance_name | default(dbh.oracle_db_unique_name | default(dbh.oracle_db_name)) }}" + with_items: + - "{{ oracle_databases }}" + when: + - oracle_databases is defined + - dbh.statspack is defined + - dbh.statspack.state | default('present') == 'present' + become_user: "{{ oracle_user }}" + loop_control: + loop_var: dbh + label: "{{ dbh.oracle_db_name }}" + tags: + - spjob + - spcdb + +- name: oradb-manage-statspack | Create/Modify Snapshot Job + oracle_job: + hostname: "{{ ansible_hostname }}" + service_name: "{{ db_service_name }}" + port: "{{ dbh.listener_port | default(listener_port | default(1521)) }}" + user: "{{ db_user }}" + password: "{{ db_password_cdb }}" + job_name: "PERFSTAT.SNAPSHOT" + comments: "Statspack Snapshot-Job" + job_type: "plsql_block" + job_action: "PERFSTAT.STATSPACK.SNAP(i_snap_level => {{ dbh.statspack.snaplevel | default(snaplevel) }});" + logging_level: "runs" + repeat_interval: "{{ dbh.statspack.snapinterval | default(snapinterval) }}" + state: "present" + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ dbh.oracle_db_instance_name | default(dbh.oracle_db_unique_name | default(dbh.oracle_db_name)) }}" + with_items: + - "{{ oracle_databases }}" + when: + - oracle_databases is defined + - dbh.statspack is defined + - dbh.statspack.state | default('present') == 'present' + become_user: "{{ oracle_user }}" + loop_control: + loop_var: dbh + label: "{{ dbh.oracle_db_name }}" + tags: + - spjob + - spcdb + +- block: + - name: oradb-manage-statspack | Drop Statspack Schema (PDB) + script: spdrop.sh + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ oracle_db_instance_name }}" + pdb_name: "{{ pdb.0.pdb_name }}" + loop: + - "{{ oracle_pdbs |flatten(levels=1) }}" + loop_control: + loop_var: pdb + label: "{{ pdb.0.cdb | default('') }} {{ pdb.0.pdb_name | default('') }} {{ oracle_db_instance_name | default('') }}" + register: statspackdropcmd + become: true + become_user: "{{ oracle_user }}" + failed_when: + - statspackdropcmd.rc != 0 + - '"ORA-01920:" not in statspackdropcmd.stdout' # ORA-01920: user name 'PERFSTAT' conflicts with another user + when: + - oracle_pdbs is defined + - pdb.0.statspack is defined + - pdb.0.statspack.state | default('present') == 'absent' + + - debug: msg="{{ item.stdout_lines }}" # noqa unnamed-task + with_items: + - "{{ statspackdropcmd.results }}" + loop_control: + label: "" + when: + - statspackdropcmd is defined + - item.stdout_lines is defined + become: true + become_user: "{{ oracle_user }}" + tags: + - spdrop + - sppdb + +- block: + - name: oradb-manage-statspack | Create Statspack Schema in PDBs (existing user is ignored) + script: spcreate.sh + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + ORACLE_SID: "{{ oracle_db_instance_name }}" + perfstat_password: perfstat + temporary_tablespace: "{{ pdb.statspack.tablespace_temp | default('temp') }}" + default_tablespace: "{{ pdb.statspack.tablespace | default('sysaux') }}" + purgedates: "{{ pdb.statspack.purgedays | default(35) }}" + snaplevel: "{{ pdb.statspack.snaplevel | default(7) }}" + pdb_name: "{{ pdb.0.pdb_name }}" + loop: + - "{{ oracle_pdbs |flatten(levels=1) }}" + loop_control: + loop_var: pdb + label: "{{ pdb.0.cdb | default('') }} {{ pdb.0.pdb_name | default('') }} {{ oracle_db_instance_name | default('') }}" + register: statspackcmd + become: true + become_user: "{{ oracle_user }}" + failed_when: + - statspackcmd.rc != 0 + - '"ORA-01920:" not in statspackcmd.stdout' # ORA-01920: user name 'PERFSTAT' conflicts with another user + when: + - oracle_pdbs is defined + - pdb.0.statspack is defined + - pdb.0.statspack.state | default('present') == 'present' + + - debug: msg="{{ item.stdout_lines }}" # noqa unnamed-task + with_items: + - "{{ statspackcmd.results }}" + loop_control: + label: "" + when: + - statspackcmd is defined + - item.stdout_lines is defined + become: true + become_user: "{{ oracle_user }}" + tags: + - spcreate + - sppdb + +- name: oradb-manage-statspack | Create/Modify Purge Job (PDB) + oracle_job: + hostname: "{{ ansible_hostname }}" + service_name: "{{ pdb.0.pdb_name }}" + port: "{{ pdb.listener_port | default(listener_port | default(1521)) }}" + user: "{{ db_user }}" + password: "{{ db_password_pdb }}" + job_name: "PERFSTAT.PURGE" + comments: "Statspack Purge-Job" + job_type: "plsql_block" + job_action: "PERFSTAT.STATSPACK.PURGE({{ pdb.statspack.purgedays | default(purgedays) }});" + logging_level: "runs" + repeat_interval: "{{ pdb.0.statspack.purgeinterval | default(purgeinterval) }}" + state: "present" + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + loop: + - "{{ oracle_pdbs |flatten(levels=1) }}" + loop_control: + loop_var: pdb + label: "{{ pdb.0.cdb | default('') }} {{ pdb.0.pdb_name | default('') }}" + when: + - oracle_pdbs is defined + - pdb.0.cdb is defined + - pdb.0.pdb_name is defined + - pdb.0.statspack is defined + - pdb.0.statspack.state | default('present') == 'present' + become_user: "{{ oracle_user }}" + tags: + - spjob + - sppdb + +- name: oradb-manage-statspack | Create/Modify Snapshot Job (PDB) + oracle_job: + hostname: "{{ ansible_hostname }}" + service_name: "{{ pdb.0.pdb_name }}" + port: "{{ pdb.listener_port | default(listener_port | default(1521)) }}" + user: "{{ db_user }}" + password: "{{ db_password_pdb }}" + job_name: "PERFSTAT.SNAPSHOT" + comments: "Statspack Snapshot-Job" + job_type: "plsql_block" + job_action: "PERFSTAT.STATSPACK.SNAP(i_snap_level => {{ pdb.0.statspack.snaplevel | default(snaplevel) }});" + logging_level: "runs" + repeat_interval: "{{ pdb.0.statspack.snapinterval | default(snapinterval) }}" + state: "present" + environment: + ORACLE_HOME: "{{ oracle_home_db }}" + loop: + - "{{ oracle_pdbs |flatten(levels=1) }}" + loop_control: + loop_var: pdb + label: "{{ pdb.0.cdb | default('') }} {{ pdb.0.pdb_name | default('') }}" + when: + - oracle_pdbs is defined + - pdb.0.cdb is defined + - pdb.0.pdb_name is defined + - pdb.0.statspack is defined + - pdb.0.statspack.state | default('present') == 'present' + become: true + become_user: "{{ oracle_user }}" + tags: + - spjob + - sppdb diff --git a/roles/orasw-meta/defaults/main.yml b/roles/orasw-meta/defaults/main.yml index e05385b8d..c9d41e7b6 100644 --- a/roles/orasw-meta/defaults/main.yml +++ b/roles/orasw-meta/defaults/main.yml @@ -172,6 +172,12 @@ oracle_home_db: "{%- if dbh is defined -%} {%- else -%} {{oracle_base}}/{{db_homes_config[dbh.home]['version']}}/{{db_homes_config[dbh.home]['home']}} {%- endif -%} + {%- elif pdb.0.home is defined %} + {%- if db_homes_config[pdb.0.home]['oracle_home'] is defined -%} + {{db_homes_config[pdb.0.home]['oracle_home']}} + {%- else -%} + {{oracle_base}}/{{db_homes_config[pdb.0.home]['version']}}/{{db_homes_config[pdb.0.home]['home']}} + {%- endif -%} {%- elif item.0 is defined -%} {%- if db_homes_config[item.0.home]['oracle_home'] is defined -%} {{db_homes_config[item[0].home]['oracle_home']}} @@ -214,6 +220,14 @@ db_version: "{%- if dbh is defined and db_homes_config[dbh.home] is defined -%} {%- endif -%} {%- endif -%}" +oracle_db_instance_name: "{%- if pdb.0.cdb is defined -%} + {%- for db in oracle_databases -%} + {%- if db.oracle_db_name == pdb.0.cdb -%} + {{ db.oracle_db_instance_name | default(db.oracle_db_unique_name | default(db.oracle_db_name)) }} + {%- endif -%} + {%- endfor -%} + {%- endif -%}" + oracle_home_gi: "{% if configure_cluster %}{{ oracle_home_gi_cl }}{% else %}{{ oracle_home_gi_so }}{% endif %}" oracle_home_gi_cl: "/u01/app/{{ oracle_install_version_gi }}/grid" # ORACLE_HOME for Grid Infrastructure (Clustered) oracle_home_gi_so: "{{ oracle_base }}/{{ oracle_install_version_gi }}/grid" # ORACLE_HOME for Grid Infrastructure (Stand Alone)