Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ The Terraform module deploys the following elements:
- **Ansible Playbooks** to automate post-deployment configurations
- **Firewall Rules** to allow Ansible SSH execution and Data Guard communication
(if `create_firewall` is set to `true`)
- **Artifact Registry Remote Mirror** to allow OS package updates without
Internet access (if `enable_ar_repo` is set to `true`)

This infrastructure is modular and customizable, allowing you to tailor it to specific application needs or organizational requirements.

Expand Down Expand Up @@ -92,12 +94,17 @@ Grant the service account attached to the control node VM the following IAM role
Guard HA, as well as cleanup of firewall rules when the control node is deleted. (Only if `create_firewall` is set to `true`)
- `roles/logging.logWriter`
Required to write to Google Cloud Logging.
- `roles/artifactregistry.admin`
Allows creation of an Artifact Registry remote repository, if `enable_ar_repo`
is set to `true`.

### 2. Service Account for the database VM

- `roles/secretmanager.secretAccessor` - Grants access to retrieve passwords from Secret Manager. Must be granted in the project containing the secrets either at the project or individual secret level.
- `roles/monitoring.metricWriter` - Required only if the --install-workload-agent and --oracle-metrics-secret flags are set. This allows the Google Cloud Agent for Compute Workloads to write metrics to Cloud Monitoring.
- `roles/compute.viewer` - Required only if the --install-workload-agent and --oracle-metrics-secret flags are set. Needed by the Google Cloud Agent for Compute Workloads.
- `roles/artifactregistry.reader` - Grants access to the AR remote repository,
if `enable_ar_repo` is set to `true`.

### 3. Terraform State Bucket

Expand Down
16 changes: 16 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,22 @@ SWAP_BLK_DEVICE
<br>
Optional: set if you would like a swap partition and swap file created.</td>
</tr>
<tr>
<td>Artifact Registry repository</td>
<td><p><pre>
--ar-repo-url
</pre></p></td>
<td>Empty: don't configure Artifact Registry</td>
<td>Base URL of the registry location. When provided, the installer configures
the system to use these repositories for `BaseOS` and `AppStream` instead of
public mirrors.<br>
To avoid hangs with default OS configurations, this parameter will also mark
existing YUM repositories as `disabled`.<br>
This parameter has no effect with Red Hat Enterprise Linux, where Google Cloud
already provides a local mirror, and that a remote registry is unnecessary.
Not supported with Free Edition, where all software is fetched directly from
vendor repositories.</td>
</tr>
</tbody>
</table>

Expand Down
3 changes: 3 additions & 0 deletions install-oracle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ GETOPT_OPTIONAL="$GETOPT_OPTIONAL,ora-swlib-type:,ora-swlib-path:,ora-swlib-cred
GETOPT_OPTIONAL="$GETOPT_OPTIONAL,instance-ssh-key:,instance-hostname:,ntp-pref:,inventory-file:,compatible-rdbms:,instance-ssh-extra-args:"
GETOPT_OPTIONAL="$GETOPT_OPTIONAL,help,validate,check-instance,prep-host,install-sw,config-db,allow-install-on-vm,skip-database-config,swap-blk-device:"
GETOPT_OPTIONAL="$GETOPT_OPTIONAL,install-workload-agent,oracle-metrics-secret:,db-password-secret:,data-guard-protection-mode:,skip-platform-compatibility"
GETOPT_OPTIONAL="$GETOPT_OPTIONAL,ar-repo-url:"
GETOPT_LONG="$GETOPT_MANDATORY,$GETOPT_OPTIONAL"
GETOPT_SHORT="h"

Expand Down Expand Up @@ -158,6 +159,7 @@ while true; do
--skip-platform-compatibility) YAML_VARS["_skip_platform_compatibility"]="true"; shift ;;
--compatible-rdbms) YAML_VARS["compatible_rdbms"]="$2"; shift 2 ;;
--data-guard-protection-mode) YAML_VARS["ora_data_guard_protection_mode"]="$2"; shift 2 ;;
--ar-repo-url) YAML_VARS["ar_repo_url"]="$2"; shift 2 ;;
--) shift; ANSIBLE_ARGS+=("$@"); break ;;
*) echo "Internal error! Unexpected option: $1" >&2; exit 1 ;;
esac
Expand Down Expand Up @@ -286,6 +288,7 @@ if [ "$HELP_ONLY" = true ]; then
echo " --compatible-rdbms <version> Compatible RDBMS version."
echo " --data-guard-protection-mode Data Guard protection mode (Maximum Performance, Maximum Availability, Maximum Protection)."
echo " --inventory-file <file> Custom Ansible inventory file."
echo " --ar-repo-url <url> Artifact Registry remote repository base URL."
exit 0
fi

Expand Down
2 changes: 2 additions & 0 deletions presubmit_tests/data-guard.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ ora_db_name = "orcl"
ora_db_domain = "test2.example_domain01.com"
ora_db_container = false
ora_disk_mgmt = "FS"
assign_public_ip = false
enable_ar_repo = true

49 changes: 49 additions & 0 deletions roles/base-provision/tasks/ar_repo_setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
- name: ar_mirror_setup | Setup Artifact Registry mirrors
become: true
block:
- name: ar_mirror_setup | Disable all repositories to prevent timeouts
command: "dnf config-manager --set-disabled *"
tags: os_packages

- name: ar_mirror_setup | Re-enable Google Compute Engine repo (via PGA)
# This preserves the Guest Agent and other critical GCP services
command: "dnf config-manager --set-enabled google-compute-engine"
register: enable_gce_repo
failed_when: false
tags: os_packages

- name: ar_mirror_setup | Add official google-cloud-sdk repo (via PGA)
yum_repository:
name: google-cloud-sdk
file: google-cloud
description: Google Cloud SDK
baseurl: "https://packages.cloud.google.com/yum/repos/cloud-sdk-el{{ ansible_distribution_major_version }}-x86_64"
enabled: yes
gpgcheck: yes
repo_gpgcheck: no
gpgkey:
- https://packages.cloud.google.com/yum/doc/yum-key.gpg
- https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

- name: ar_mirror_setup | Install Artifact Registry DNF plugin
package:
name: dnf-plugin-artifact-registry
state: present

- name: ar_mirror_setup | Configure project-specific mirrors
yum_repository:
name: "ar-{{ item }}"
description: "Internal Artifact Registry repository for {{ item }}"
baseurl: "{{ ar_repo_url }}/oracle-linux-{{ ansible_distribution_major_version }}-{{ item }}-repo"
enabled: yes
gpgcheck: yes
repo_gpgcheck: no
gpgkey: "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle"
priority: "1"
loop:
- baseos
- appstream

when:
- ansible_distribution == 'OracleLinux'
tags: os_packages
10 changes: 10 additions & 0 deletions roles/base-provision/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
name: ntp
state: absent
lock_timeout: "{{ pkg_mgr_lock_timeout }}"
when: cluster_name is defined
tags: ntp

- name: Remove ntp conf
file:
path: /etc/ntp.conf
state: absent
when: cluster_name is defined
tags: ntp

- name: Gather installed packages
Expand All @@ -58,6 +60,14 @@
- avahi-daemon.service
tags: cvu

- name: Set up Artifact Registry mirrors if enabled
include_tasks:
file: ar_repo_setup.yml
when:
- install_os_packages
- ar_repo_url is defined and ar_repo_url | length > 0
tags: os-packages

- name: Install required base OS packages
package:
name: "{{ required_packages }}"
Expand Down
38 changes: 37 additions & 1 deletion terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,21 @@ data "google_compute_subnetwork" "subnetwork" {

locals {
network = local.subnetwork1_opt == null ? "projects/${var.project_id}/global/networks/default" : data.google_compute_subnetwork.subnetwork[0].network
# Derive region from zone1 (e.g., us-central1-b -> us-central1)
region = join("-", slice(split("-", var.zone1), 0, 2))

os_repo_types = ["baseos", "appstream"]

os_upstreams = {
"oracle-linux-8" = {
"baseos" = "https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64"
"appstream" = "https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64"
}
"oracle-linux-9" = {
"baseos" = "https://yum.oracle.com/repo/OracleLinux/OL9/baseos/latest/x86_64"
"appstream" = "https://yum.oracle.com/repo/OracleLinux/OL9/appstream/x86_64"
}
}
}

data "google_compute_image" "os_image" {
Expand Down Expand Up @@ -241,6 +256,8 @@ locals {
}
]

ar_repo_base_url = var.enable_ar_repo ? "https://${local.region}-yum.pkg.dev/remote/${var.project_id}" : ""

common_flags = join(" ", compact([
local.ora_disk_mgmt_flag != "" ? "--ora-disk-mgmt ${local.ora_disk_mgmt_flag}" : "",
length(local.asm_disk_config) > 0 ? "--ora-asm-disks-json '${jsonencode(local.asm_disk_config)}'" : "",
Expand All @@ -266,7 +283,8 @@ locals {
var.skip_database_config ? "--skip-database-config" : "",
var.ora_pga_target_mb != "" ? "--ora-pga-target-mb ${var.ora_pga_target_mb}" : "",
var.ora_sga_target_mb != "" ? "--ora-sga-target-mb ${var.ora_pga_target_mb}" : "",
var.data_guard_protection_mode != "" ? "--data-guard-protection-mode '${var.data_guard_protection_mode}'" : ""
var.data_guard_protection_mode != "" ? "--data-guard-protection-mode '${var.data_guard_protection_mode}'" : "",
local.ar_repo_base_url != "" ? "--ar-repo-url '${local.ar_repo_base_url}'" : ""
]))
}

Expand Down Expand Up @@ -375,6 +393,24 @@ resource "google_compute_firewall" "db_sync" {
target_tags = [local.db_tag]
}

resource "google_artifact_registry_repository" "os_package_repos" {
# Only create repositories if the guard is true and the image family is supported
for_each = (var.enable_ar_repo && contains(keys(local.os_upstreams), var.source_image_family)) ? toset(local.os_repo_types) : []

project = var.project_id
location = local.region
repository_id = "${var.source_image_family}-${each.key}-repo"
description = "Remote repo for ${var.source_image_family} ${each.key} packages"
format = "YUM"
mode = "REMOTE_REPOSITORY"

remote_repository_config {
common_repository {
uri = local.os_upstreams[var.source_image_family][each.key]
}
}
}

output "control_node_log_url" {
description = "Logs Explorer URL with Oracle Toolkit output"
value = "https://console.cloud.google.com/logs/query;query=resource.labels.instance_id%3D${urlencode(google_compute_instance.control_node.instance_id)};duration=P30D?project=${urlencode(var.project_id)}"
Expand Down
6 changes: 6 additions & 0 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,9 @@ variable "create_firewall" {
type = bool
default = false
}

variable "enable_ar_repo" {
description = "Controls whether to create Google Cloud Artifact Registry remote repositories to fetch OS packages."
type = bool
default = false
}
7 changes: 7 additions & 0 deletions validate-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,13 @@
fail_msg: "instance-ip-addr and primary-ip-addr cannot be the same."
when: primary_ip_addr is defined

- name: Validate AR Repo is not used with free edition
ansible.builtin.assert:
that:
- not (ar_repo_url is defined and ar_repo_url | length > 0)
fail_msg: "Artifact Registry repositories (--ar-repo-url) are not supported with the Oracle Database free edition."
when: ora_edition is defined and ora_edition == 'FREE'

- name: Validate ASM Disk Configuration
block:
- name: Assert that ora_asm_disks and ora_asm_disks_json are mutually exclusive
Expand Down