standby roa vm windows
This commit is contained in:
@@ -0,0 +1,925 @@
|
||||
# Oracle DR - Windows VM Implementation Plan
|
||||
**Generated:** 2025-10-08
|
||||
**Objective:** Replace Linux LXC DR with Windows VM for same-platform RMAN restore
|
||||
**Target:** Windows VM in Proxmox, IP 10.0.20.37, Oracle 19c SE2
|
||||
|
||||
---
|
||||
|
||||
## 📋 PRE-IMPLEMENTATION CHECKLIST
|
||||
|
||||
### Current Infrastructure
|
||||
- ✅ PRIMARY: Windows Server, Oracle 19c SE2, IP: 10.0.20.36, SSH port 22122
|
||||
- ✅ Database: ROA, DBID: 1363569330
|
||||
- ✅ RMAN backups: FULL daily (02:30 AM), INCREMENTAL midday (14:00)
|
||||
- ✅ Transfer scripts: PowerShell scripts working to LXC 10.0.20.37
|
||||
- ✅ Backup size: ~7GB compressed (from 23GB), retention 2 days
|
||||
- ✅ Current DR target: Linux LXC 109 (10.0.20.37) - TO BE REPLACED
|
||||
|
||||
### What We'll Build
|
||||
- 🎯 Windows VM in Proxmox (replaces LXC 109)
|
||||
- 🎯 IP: 10.0.20.37 (same as current LXC)
|
||||
- 🎯 Oracle 19c SE2 installed (empty database template)
|
||||
- 🎯 OpenSSH Server for passwordless transfer
|
||||
- 🎯 RMAN restore scripts (automated DR recovery)
|
||||
- 🎯 Zero daily resource consumption (VM powered off when not needed)
|
||||
|
||||
### Resource Requirements
|
||||
- RAM: 4-6 GB (allocated, but VM runs only during DR events)
|
||||
- Disk: 100 GB (OS + Oracle + backup storage)
|
||||
- CPU: 2-4 vCPU
|
||||
- Network: Access to 10.0.20.0/24
|
||||
|
||||
---
|
||||
|
||||
## 🚀 PHASE 1: CREATE WINDOWS VM IN PROXMOX (30 minutes)
|
||||
|
||||
### Step 1.1: Download Windows 11 ISO
|
||||
```bash
|
||||
# On Proxmox host or download station
|
||||
cd /var/lib/vz/template/iso
|
||||
|
||||
# Option A: Download Windows 11 from Microsoft
|
||||
wget -O Win11_EnglishInternational_x64v1.iso \
|
||||
"https://software-download.microsoft.com/download/pr/..."
|
||||
|
||||
# Option B: Upload existing ISO via Proxmox web UI
|
||||
# Datacenter → Storage → ISO Images → Upload
|
||||
```
|
||||
|
||||
### Step 1.2: Create VM in Proxmox Web UI
|
||||
```
|
||||
Proxmox Web UI → Create VM
|
||||
|
||||
General:
|
||||
- VM ID: 109 (same as LXC number for consistency)
|
||||
- Name: oracle-dr-windows
|
||||
- Start at boot: NO (VM stays off until DR event)
|
||||
|
||||
OS:
|
||||
- ISO: Win11_EnglishInternational_x64v1.iso
|
||||
- Type: Microsoft Windows
|
||||
- Version: 11/2022
|
||||
|
||||
System:
|
||||
- Machine: q35
|
||||
- BIOS: OVMF (UEFI)
|
||||
- Add TPM: YES (for Windows 11)
|
||||
- SCSI Controller: VirtIO SCSI
|
||||
|
||||
Disks:
|
||||
- Bus/Device: SCSI 0
|
||||
- Storage: local-lvm (or your storage)
|
||||
- Size: 100 GB
|
||||
- Cache: Write back
|
||||
- Discard: YES
|
||||
- IO thread: YES
|
||||
|
||||
CPU:
|
||||
- Cores: 4
|
||||
- Type: host
|
||||
|
||||
Memory:
|
||||
- RAM: 6144 MB (6 GB)
|
||||
- Ballooning: NO
|
||||
|
||||
Network:
|
||||
- Bridge: vmbr0
|
||||
- Model: VirtIO
|
||||
- Firewall: NO
|
||||
```
|
||||
|
||||
### Step 1.3: Install Windows 11
|
||||
```
|
||||
1. Start VM → Open Console (noVNC)
|
||||
2. Boot from ISO
|
||||
3. Windows Setup:
|
||||
- Language: English
|
||||
- Install Now
|
||||
- Windows 11 Pro (or your edition)
|
||||
- Custom Install
|
||||
- Load driver: Browse → virtio-win-0.1.x (if needed for disk detection)
|
||||
- Select disk → Format → Next
|
||||
|
||||
4. Initial Setup:
|
||||
- Computer name: ORACLE-DR
|
||||
- Local account: Administrator / <strong-password>
|
||||
- Disable all telemetry/tracking options
|
||||
|
||||
5. First boot:
|
||||
- Disable Windows Defender real-time protection (for Oracle performance)
|
||||
- Disable Windows Update automatic restart
|
||||
- Install VirtIO drivers (guest tools)
|
||||
```
|
||||
|
||||
### Step 1.4: Configure Network (Static IP)
|
||||
```powershell
|
||||
# In Windows VM, run PowerShell as Administrator
|
||||
|
||||
# Set static IP 10.0.20.37
|
||||
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 10.0.20.37 -PrefixLength 24 -DefaultGateway 10.0.20.1
|
||||
|
||||
# Set DNS
|
||||
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses ("10.0.20.1","8.8.8.8")
|
||||
|
||||
# Verify
|
||||
Get-NetIPAddress | Where-Object {$_.IPAddress -eq "10.0.20.37"}
|
||||
Test-Connection 10.0.20.36 -Count 2
|
||||
```
|
||||
|
||||
### Step 1.5: Windows Initial Configuration
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
|
||||
# Enable Remote Desktop (optional, for management)
|
||||
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0
|
||||
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
|
||||
|
||||
# Disable Windows Firewall for private network (or configure rules)
|
||||
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
|
||||
|
||||
# Set timezone
|
||||
Set-TimeZone -Id "GTB Standard Time" # Romania timezone
|
||||
|
||||
# Disable hibernation (saves disk space)
|
||||
powercfg /hibernate off
|
||||
|
||||
# Create directories for Oracle
|
||||
New-Item -ItemType Directory -Path "D:\oracle" -Force
|
||||
New-Item -ItemType Directory -Path "D:\oracle\backups" -Force
|
||||
New-Item -ItemType Directory -Path "D:\oracle\oradata" -Force
|
||||
New-Item -ItemType Directory -Path "D:\oracle\fra" -Force
|
||||
```
|
||||
|
||||
**✅ PHASE 1 COMPLETE:** Windows VM created, network configured, ready for Oracle installation
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ PHASE 2: INSTALL ORACLE 19c (60-90 minutes)
|
||||
|
||||
### Step 2.1: Download Oracle 19c
|
||||
```
|
||||
On developer machine or PRIMARY:
|
||||
|
||||
1. Go to: https://www.oracle.com/database/technologies/oracle19c-windows-downloads.html
|
||||
2. Download: WINDOWS.X64_193000_db_home.zip (3.0 GB)
|
||||
3. Transfer to VM:
|
||||
- Option A: Shared folder via Proxmox
|
||||
- Option B: HTTP file server
|
||||
- Option C: Direct download in VM
|
||||
```
|
||||
|
||||
### Step 2.2: Prepare Installation (in Windows VM)
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
|
||||
# Extract Oracle installation
|
||||
Expand-Archive -Path "C:\Temp\WINDOWS.X64_193000_db_home.zip" -DestinationPath "D:\oracle\product\19c\dbhome_1"
|
||||
|
||||
# Create response file for silent install
|
||||
$responseFile = @"
|
||||
oracle.install.option=INSTALL_DB_SWONLY
|
||||
UNIX_GROUP_NAME=
|
||||
INVENTORY_LOCATION=D:\oracle\oraInventory
|
||||
ORACLE_HOME=D:\oracle\product\19c\dbhome_1
|
||||
ORACLE_BASE=D:\oracle
|
||||
oracle.install.db.InstallEdition=SE2
|
||||
oracle.install.db.OSDBA_GROUP=ORA_DBA
|
||||
oracle.install.db.OSOPER_GROUP=ORA_OPER
|
||||
oracle.install.db.OSBACKUPDBA_GROUP=ORA_BACKUPDBA
|
||||
oracle.install.db.OSDGDBA_GROUP=ORA_DG
|
||||
oracle.install.db.OSKMDBA_GROUP=ORA_KM
|
||||
oracle.install.db.OSRACDBA_GROUP=ORA_RAC
|
||||
DECLINE_SECURITY_UPDATES=true
|
||||
"@
|
||||
|
||||
$responseFile | Out-File -FilePath "D:\oracle\db_install.rsp" -Encoding ASCII
|
||||
```
|
||||
|
||||
### Step 2.3: Silent Installation
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
|
||||
cd D:\oracle\product\19c\dbhome_1
|
||||
|
||||
# Silent install (takes 30-60 minutes)
|
||||
.\setup.exe -silent -responseFile D:\oracle\db_install.rsp -ignorePrereqFailure
|
||||
|
||||
# Wait for completion, check log:
|
||||
# D:\oracle\oraInventory\logs\installActions<timestamp>.log
|
||||
|
||||
# Run root scripts (as Administrator)
|
||||
D:\oracle\product\19c\dbhome_1\root.bat
|
||||
```
|
||||
|
||||
### Step 2.4: Create Listener
|
||||
```powershell
|
||||
# Set environment
|
||||
$env:ORACLE_HOME = "D:\oracle\product\19c\dbhome_1"
|
||||
$env:PATH = "$env:ORACLE_HOME\bin;$env:PATH"
|
||||
|
||||
# Create listener.ora
|
||||
$listenerOra = @"
|
||||
LISTENER =
|
||||
(DESCRIPTION_LIST =
|
||||
(DESCRIPTION =
|
||||
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.20.37)(PORT = 1521))
|
||||
)
|
||||
)
|
||||
"@
|
||||
|
||||
$listenerOra | Out-File -FilePath "D:\oracle\product\19c\dbhome_1\network\admin\listener.ora" -Encoding ASCII
|
||||
|
||||
# Start listener
|
||||
lsnrctl start
|
||||
|
||||
# Configure listener as Windows service (optional)
|
||||
```
|
||||
|
||||
### Step 2.5: Create Empty Database Template (for faster DR restore)
|
||||
```powershell
|
||||
# Create init parameter file
|
||||
$initROA = @"
|
||||
DB_NAME=ROA
|
||||
DB_BLOCK_SIZE=8192
|
||||
COMPATIBLE=19.0.0
|
||||
MEMORY_TARGET=2G
|
||||
PROCESSES=300
|
||||
OPEN_CURSORS=300
|
||||
DB_RECOVERY_FILE_DEST=D:\oracle\fra
|
||||
DB_RECOVERY_FILE_DEST_SIZE=20G
|
||||
CONTROL_FILES=('D:\oracle\oradata\ROA\control01.ctl','D:\oracle\oradata\ROA\control02.ctl')
|
||||
"@
|
||||
|
||||
$initROA | Out-File -FilePath "D:\oracle\product\19c\dbhome_1\database\initROA.ora" -Encoding ASCII
|
||||
|
||||
# Create directory structure
|
||||
New-Item -ItemType Directory -Path "D:\oracle\oradata\ROA" -Force
|
||||
New-Item -ItemType Directory -Path "D:\oracle\fra" -Force
|
||||
|
||||
# Note: We will NOT create the database now
|
||||
# Database will be created via RMAN RESTORE during DR event
|
||||
```
|
||||
|
||||
**✅ PHASE 2 COMPLETE:** Oracle 19c installed, listener configured, ready for SSH setup
|
||||
|
||||
---
|
||||
|
||||
## 🔐 PHASE 3: CONFIGURE SSH FOR AUTOMATED TRANSFERS (20 minutes)
|
||||
|
||||
### Step 3.1: Install OpenSSH Server
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
|
||||
# Install OpenSSH Server
|
||||
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
||||
|
||||
# Start and enable service
|
||||
Start-Service sshd
|
||||
Set-Service -Name sshd -StartupType 'Automatic'
|
||||
|
||||
# Confirm firewall rule
|
||||
Get-NetFirewallRule -Name *ssh*
|
||||
|
||||
# Test SSH from developer machine
|
||||
# ssh Administrator@10.0.20.37
|
||||
```
|
||||
|
||||
### Step 3.2: Configure Passwordless SSH (Key-based Authentication)
|
||||
```powershell
|
||||
# On Windows VM, as Administrator
|
||||
|
||||
# Create .ssh directory
|
||||
$sshDir = "$env:ProgramData\ssh"
|
||||
New-Item -ItemType Directory -Path $sshDir -Force
|
||||
|
||||
# Get public key from PRIMARY server
|
||||
# Option A: Copy manually from PRIMARY C:\Users\Administrator\.ssh\id_rsa.pub
|
||||
# Option B: Download via SCP from developer machine
|
||||
|
||||
# For this example, manually copy the content:
|
||||
# From PRIMARY run: Get-Content C:\Users\Administrator\.ssh\id_rsa.pub
|
||||
|
||||
# On DR Windows VM:
|
||||
$publicKey = "<paste-public-key-here>"
|
||||
$publicKey | Out-File -FilePath "$sshDir\administrators_authorized_keys" -Encoding ASCII
|
||||
|
||||
# Set permissions (CRITICAL for SSH to work)
|
||||
icacls "$sshDir\administrators_authorized_keys" /inheritance:r
|
||||
icacls "$sshDir\administrators_authorized_keys" /grant "SYSTEM:(F)"
|
||||
icacls "$sshDir\administrators_authorized_keys" /grant "BUILTIN\Administrators:(F)"
|
||||
|
||||
# Restart SSH service
|
||||
Restart-Service sshd
|
||||
```
|
||||
|
||||
### Step 3.3: Configure SSH for SYSTEM Account (for scheduled tasks)
|
||||
```powershell
|
||||
# Windows scheduled tasks run as SYSTEM, so we need SYSTEM's SSH key
|
||||
|
||||
# Create SYSTEM's .ssh directory
|
||||
$systemSSHDir = "C:\Windows\System32\config\systemprofile\.ssh"
|
||||
New-Item -ItemType Directory -Path $systemSSHDir -Force
|
||||
|
||||
# Copy the same authorized_keys
|
||||
Copy-Item "$env:ProgramData\ssh\administrators_authorized_keys" `
|
||||
-Destination "$systemSSHDir\authorized_keys" -Force
|
||||
|
||||
# Set permissions
|
||||
icacls "$systemSSHDir\authorized_keys" /inheritance:r
|
||||
icacls "$systemSSHDir\authorized_keys" /grant "SYSTEM:(F)"
|
||||
```
|
||||
|
||||
### Step 3.4: Test SSH Connection from PRIMARY
|
||||
```powershell
|
||||
# On PRIMARY (10.0.20.36), test SSH to DR VM
|
||||
|
||||
# Test 1: Manual connection
|
||||
ssh -i C:\Users\Administrator\.ssh\id_rsa Administrator@10.0.20.37 "echo SSH_OK"
|
||||
|
||||
# Test 2: File transfer
|
||||
echo "test content" > C:\Temp\test.txt
|
||||
scp -i C:\Users\Administrator\.ssh\id_rsa C:\Temp\test.txt Administrator@10.0.20.37:D:\oracle\backups\
|
||||
|
||||
# If successful, you should see the file on DR VM
|
||||
```
|
||||
|
||||
**✅ PHASE 3 COMPLETE:** OpenSSH configured, passwordless authentication working
|
||||
|
||||
---
|
||||
|
||||
## 📝 PHASE 4: UPDATE TRANSFER SCRIPTS (15 minutes)
|
||||
|
||||
### Step 4.1: Modify 02_transfer_to_dr.ps1 for Windows Target
|
||||
```powershell
|
||||
# File: D:\rman_backup\02_transfer_to_dr_windows.ps1
|
||||
# Changes needed:
|
||||
|
||||
# OLD (Linux target):
|
||||
# $DRPath = "/opt/oracle/backups/primary"
|
||||
|
||||
# NEW (Windows target):
|
||||
$DRHost = "10.0.20.37"
|
||||
$DRUser = "Administrator" # Changed from "root"
|
||||
$DRPath = "D:/oracle/backups/primary" # Windows path with forward slashes for SCP
|
||||
$SSHKeyPath = "C:\Users\Administrator\.ssh\id_rsa"
|
||||
|
||||
# Update SSH commands to use Windows paths
|
||||
# Example: Directory creation
|
||||
$null = & ssh -n -i $SSHKeyPath "${DRUser}@${DRHost}" `
|
||||
"New-Item -ItemType Directory -Path '$DRPath' -Force" 2>&1
|
||||
|
||||
# Update cleanup command for Windows
|
||||
function Cleanup-OldBackupsOnDR {
|
||||
Write-Log "Cleaning up old backups on DR (keeping last 2 days)..."
|
||||
|
||||
try {
|
||||
$cleanupCmd = @"
|
||||
Get-ChildItem -Path '$DRPath' -Filter '*.BKP' |
|
||||
Where-Object { `$_.LastWriteTime -lt (Get-Date).AddDays(-2) } |
|
||||
Remove-Item -Force
|
||||
"@
|
||||
$result = & ssh -n -i $SSHKeyPath "${DRUser}@${DRHost}" "powershell -Command `"$cleanupCmd`"" 2>&1
|
||||
|
||||
Write-Log "Cleanup completed on DR"
|
||||
} catch {
|
||||
Write-Log "Cleanup warning: $_" "WARNING"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4.2: Create Updated Transfer Scripts
|
||||
```powershell
|
||||
# Save updated versions:
|
||||
# - 02_transfer_to_dr_windows.ps1 (FULL backup transfer)
|
||||
# - 02b_transfer_incremental_to_dr_windows.ps1 (INCREMENTAL transfer)
|
||||
|
||||
# Key changes for Windows:
|
||||
# 1. DRUser = "Administrator" instead of "root"
|
||||
# 2. DRPath = "D:/oracle/backups/primary" (Windows path)
|
||||
# 3. SSH commands use PowerShell instead of Linux commands
|
||||
# 4. Directory check: Test-Path instead of "test -f"
|
||||
# 5. Cleanup: Get-ChildItem instead of find
|
||||
```
|
||||
|
||||
### Step 4.3: Test Transfer Script
|
||||
```powershell
|
||||
# On PRIMARY, test the new script
|
||||
|
||||
# Manual test
|
||||
D:\rman_backup\02_transfer_to_dr_windows.ps1
|
||||
|
||||
# Check log output
|
||||
Get-Content "D:\rman_backup\logs\transfer_$(Get-Date -Format 'yyyyMMdd').log" -Tail 50
|
||||
|
||||
# Verify on DR VM
|
||||
ssh Administrator@10.0.20.37 "Get-ChildItem D:\oracle\backups\primary"
|
||||
```
|
||||
|
||||
**✅ PHASE 4 COMPLETE:** Transfer scripts updated and tested for Windows target
|
||||
|
||||
---
|
||||
|
||||
## 🔄 PHASE 5: CREATE RMAN RESTORE SCRIPT ON DR VM (30 minutes)
|
||||
|
||||
### Step 5.1: Create RMAN Restore Script
|
||||
```powershell
|
||||
# File: D:\oracle\scripts\rman_restore_from_primary.ps1
|
||||
# Run on DR Windows VM
|
||||
|
||||
param(
|
||||
[string]$BackupPath = "D:\oracle\backups\primary",
|
||||
[string]$OracleHome = "D:\oracle\product\19c\dbhome_1",
|
||||
[string]$OracleBase = "D:\oracle",
|
||||
[string]$DataDir = "D:\oracle\oradata\ROA",
|
||||
[string]$FRADir = "D:\oracle\fra",
|
||||
[int]$DBID = 1363569330,
|
||||
[string]$LogFile = "D:\oracle\logs\restore_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$timestamp] [$Level] $Message"
|
||||
Write-Host $logLine
|
||||
Add-Content -Path $LogFile -Value $logLine -Encoding UTF8
|
||||
}
|
||||
|
||||
try {
|
||||
Write-Log "======================================================================"
|
||||
Write-Log "Oracle DR Restore - Starting"
|
||||
Write-Log "======================================================================"
|
||||
Write-Log "Backup Path: $BackupPath"
|
||||
Write-Log "Oracle Home: $OracleHome"
|
||||
Write-Log "DBID: $DBID"
|
||||
|
||||
# Set environment
|
||||
$env:ORACLE_HOME = $OracleHome
|
||||
$env:ORACLE_SID = "ROA"
|
||||
$env:PATH = "$OracleHome\bin;$env:PATH"
|
||||
|
||||
# Step 1: Cleanup old database files
|
||||
Write-Log "[1/6] Cleaning old database files..."
|
||||
if (Test-Path $DataDir) {
|
||||
Remove-Item "$DataDir\*" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (Test-Path $FRADir) {
|
||||
Remove-Item "$FRADir\*" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
New-Item -ItemType Directory -Path $DataDir -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path $FRADir -Force | Out-Null
|
||||
|
||||
# Step 2: Startup NOMOUNT
|
||||
Write-Log "[2/6] Starting instance in NOMOUNT mode..."
|
||||
$sqlNomount = @"
|
||||
STARTUP NOMOUNT PFILE='$OracleHome\database\initROA.ora';
|
||||
EXIT;
|
||||
"@
|
||||
$sqlNomount | sqlplus / as sysdba
|
||||
|
||||
# Step 3: RMAN Restore
|
||||
Write-Log "[3/6] Running RMAN RESTORE CONTROLFILE..."
|
||||
|
||||
$rmanScript = @"
|
||||
SET DBID $DBID;
|
||||
|
||||
RUN {
|
||||
ALLOCATE CHANNEL ch1 DEVICE TYPE DISK;
|
||||
|
||||
# Restore controlfile from autobackup
|
||||
SET CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '$BackupPath/%F';
|
||||
RESTORE CONTROLFILE FROM AUTOBACKUP;
|
||||
}
|
||||
|
||||
EXIT;
|
||||
"@
|
||||
|
||||
$rmanScript | rman TARGET /
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "RMAN RESTORE CONTROLFILE failed"
|
||||
}
|
||||
|
||||
# Step 4: Mount database
|
||||
Write-Log "[4/6] Mounting database..."
|
||||
"ALTER DATABASE MOUNT; EXIT;" | sqlplus / as sysdba
|
||||
|
||||
# Step 5: Catalog and restore database
|
||||
Write-Log "[5/6] Cataloging backups and restoring database..."
|
||||
|
||||
$rmanRestore = @"
|
||||
CATALOG START WITH '$BackupPath/' NOPROMPT;
|
||||
|
||||
RUN {
|
||||
SET NEWNAME FOR DATABASE TO '$DataDir\%b';
|
||||
RESTORE DATABASE;
|
||||
SWITCH DATAFILE ALL;
|
||||
RECOVER DATABASE;
|
||||
}
|
||||
|
||||
EXIT;
|
||||
"@
|
||||
|
||||
$rmanRestore | rman TARGET /
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "RMAN RESTORE DATABASE failed"
|
||||
}
|
||||
|
||||
# Step 6: Open database RESETLOGS
|
||||
Write-Log "[6/6] Opening database with RESETLOGS..."
|
||||
"ALTER DATABASE OPEN RESETLOGS; EXIT;" | sqlplus / as sysdba
|
||||
|
||||
Write-Log "======================================================================"
|
||||
Write-Log "DR RESTORE COMPLETED SUCCESSFULLY!"
|
||||
Write-Log "======================================================================"
|
||||
Write-Log "Database ROA is now OPEN and ready"
|
||||
|
||||
# Verify
|
||||
Write-Log "Verification:"
|
||||
$verifySQL = @"
|
||||
SELECT name, open_mode, database_role FROM v`$database;
|
||||
EXIT;
|
||||
"@
|
||||
$verifySQL | sqlplus -s / as sysdba
|
||||
|
||||
exit 0
|
||||
|
||||
} catch {
|
||||
Write-Log "CRITICAL ERROR: $($_.Exception.Message)" "ERROR"
|
||||
Write-Log "Stack trace: $($_.ScriptStackTrace)" "ERROR"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5.2: Create Quick Test Script
|
||||
```powershell
|
||||
# File: D:\oracle\scripts\test_restore_latest.ps1
|
||||
# Quick test to verify restore works
|
||||
|
||||
$BackupPath = "D:\oracle\backups\primary"
|
||||
$LatestBackup = Get-ChildItem "$BackupPath\*.BKP" |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
|
||||
Write-Host "Latest backup: $($LatestBackup.Name)"
|
||||
Write-Host "Size: $([math]::Round($LatestBackup.Length / 1GB, 2)) GB"
|
||||
Write-Host "Date: $($LatestBackup.LastWriteTime)"
|
||||
Write-Host ""
|
||||
Write-Host "Ready to test restore? Run:"
|
||||
Write-Host "D:\oracle\scripts\rman_restore_from_primary.ps1"
|
||||
```
|
||||
|
||||
**✅ PHASE 5 COMPLETE:** RMAN restore script created and ready to test
|
||||
|
||||
---
|
||||
|
||||
## 🧪 PHASE 6: TEST DR RESTORE (30 minutes)
|
||||
|
||||
### Step 6.1: Verify Backups Transferred
|
||||
```powershell
|
||||
# On DR Windows VM
|
||||
|
||||
# Check backup files
|
||||
Get-ChildItem D:\oracle\backups\primary\*.BKP |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object Name, @{N='SizeMB';E={[math]::Round($_.Length/1MB,2)}}, LastWriteTime
|
||||
|
||||
# Expected output: 15-20 files (FULL + INCREMENTAL + CONTROLFILE + SPFILE + ARCHIVELOGS)
|
||||
```
|
||||
|
||||
### Step 6.2: Run Test Restore
|
||||
```powershell
|
||||
# IMPORTANT: This will create a live database on DR VM
|
||||
# Make sure PRIMARY is still running (don't confuse them!)
|
||||
|
||||
# Run restore
|
||||
D:\oracle\scripts\rman_restore_from_primary.ps1
|
||||
|
||||
# Monitor progress in log
|
||||
Get-Content "D:\oracle\logs\restore_*.log" -Wait
|
||||
|
||||
# Expected duration: 10-15 minutes
|
||||
```
|
||||
|
||||
### Step 6.3: Verify Database
|
||||
```powershell
|
||||
# Connect to restored database
|
||||
sqlplus sys/romfastsoft@10.0.20.37:1521/ROA as sysdba
|
||||
|
||||
SQL> SELECT name, open_mode FROM v$database;
|
||||
# Expected: ROA, READ WRITE
|
||||
|
||||
SQL> SELECT tablespace_name, status FROM dba_tablespaces;
|
||||
# Expected: SYSTEM, SYSAUX, UNDOTBS, TS_ROA, USERS - all ONLINE
|
||||
|
||||
SQL> SELECT COUNT(*) FROM dba_tables WHERE owner='<your-app-schema>';
|
||||
# Verify application tables restored
|
||||
|
||||
SQL> EXIT;
|
||||
```
|
||||
|
||||
### Step 6.4: Shutdown DR Database (conserve resources)
|
||||
```powershell
|
||||
# After successful test, shutdown database
|
||||
sqlplus / as sysdba
|
||||
|
||||
SQL> SHUTDOWN IMMEDIATE;
|
||||
SQL> EXIT;
|
||||
|
||||
# Stop listener
|
||||
lsnrctl stop
|
||||
|
||||
# Optional: Shutdown Windows VM to conserve resources
|
||||
# (VM will be started only during actual DR events)
|
||||
```
|
||||
|
||||
**✅ PHASE 6 COMPLETE:** DR restore tested and verified working
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ PHASE 7: UPDATE TASK SCHEDULER ON PRIMARY (10 minutes)
|
||||
|
||||
### Step 7.1: Update Scheduled Tasks to Use New Scripts
|
||||
```powershell
|
||||
# On PRIMARY (10.0.20.36)
|
||||
|
||||
# Task 1: FULL Backup + Transfer (already exists, just update transfer script)
|
||||
# Name: "Oracle RMAN Daily Backup + DR Transfer"
|
||||
# Trigger: Daily 02:30 AM
|
||||
# Action 1: Run RMAN backup (unchanged)
|
||||
# Action 2: UPDATE to new script
|
||||
|
||||
# Update task to use new transfer script
|
||||
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
|
||||
-Argument "-NoProfile -ExecutionPolicy Bypass -File D:\rman_backup\02_transfer_to_dr_windows.ps1"
|
||||
|
||||
Set-ScheduledTask -TaskName "Oracle RMAN Daily Backup + DR Transfer" -Action $action
|
||||
|
||||
# Task 2: INCREMENTAL Backup + Transfer
|
||||
# Similar update for incremental task
|
||||
```
|
||||
|
||||
### Step 7.2: Test Scheduled Task Manually
|
||||
```powershell
|
||||
# On PRIMARY
|
||||
|
||||
# Run FULL backup + transfer task manually
|
||||
Start-ScheduledTask -TaskName "Oracle RMAN Daily Backup + DR Transfer"
|
||||
|
||||
# Monitor task status
|
||||
Get-ScheduledTask -TaskName "Oracle RMAN Daily Backup + DR Transfer" |
|
||||
Get-ScheduledTaskInfo
|
||||
|
||||
# Check transfer log
|
||||
Get-Content "D:\rman_backup\logs\transfer_$(Get-Date -Format 'yyyyMMdd').log" -Tail 50
|
||||
|
||||
# Verify on DR
|
||||
ssh Administrator@10.0.20.37 "Get-ChildItem D:\oracle\backups\primary -Filter *.BKP | Measure-Object"
|
||||
```
|
||||
|
||||
**✅ PHASE 7 COMPLETE:** Automated backup and transfer configured
|
||||
|
||||
---
|
||||
|
||||
## 📚 PHASE 8: CREATE DR RUNBOOK (15 minutes)
|
||||
|
||||
### Step 8.1: DR Emergency Procedure
|
||||
```markdown
|
||||
# DISASTER RECOVERY PROCEDURE
|
||||
## When PRIMARY Server (10.0.20.36) Fails
|
||||
|
||||
### PRE-REQUISITES
|
||||
- Proxmox access available
|
||||
- DR Windows VM exists (ID 109)
|
||||
- Latest backups transferred (<24h old)
|
||||
|
||||
### DR ACTIVATION STEPS (RTO: 15-20 minutes)
|
||||
|
||||
1. **Start DR Windows VM (2 minutes)**
|
||||
```
|
||||
Proxmox Web UI → VM 109 (oracle-dr-windows) → Start
|
||||
Wait for Windows to boot
|
||||
Verify network: ping 10.0.20.37
|
||||
```
|
||||
|
||||
2. **Verify Backups Present (1 minute)**
|
||||
```powershell
|
||||
# RDP or Console to 10.0.20.37
|
||||
Get-ChildItem D:\oracle\backups\primary\*.BKP |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 10
|
||||
|
||||
# Verify you see today's or yesterday's backups
|
||||
```
|
||||
|
||||
3. **Run RMAN Restore (12-15 minutes)**
|
||||
```powershell
|
||||
# Run restore script
|
||||
D:\oracle\scripts\rman_restore_from_primary.ps1
|
||||
|
||||
# Monitor log in real-time
|
||||
Get-Content D:\oracle\logs\restore_*.log -Wait
|
||||
```
|
||||
|
||||
4. **Verify Database (2 minutes)**
|
||||
```powershell
|
||||
# Connect to database
|
||||
sqlplus sys/romfastsoft@localhost:1521/ROA as sysdba
|
||||
|
||||
SQL> SELECT name, open_mode FROM v$database;
|
||||
SQL> SELECT tablespace_name, status FROM dba_tablespaces;
|
||||
SQL> -- Verify critical application tables
|
||||
SQL> EXIT;
|
||||
```
|
||||
|
||||
5. **Update Network/DNS (5 minutes)**
|
||||
```
|
||||
- Update DNS: roa-db.example.com → 10.0.20.37
|
||||
- OR: Update application connection strings to 10.0.20.37
|
||||
- Test application connectivity
|
||||
```
|
||||
|
||||
6. **Monitor & Notify**
|
||||
```
|
||||
- Monitor database alert log: D:\oracle\diag\rdbms\roa\ROA\trace\alert_ROA.log
|
||||
- Notify team that DR is active
|
||||
- Document incident timeline
|
||||
```
|
||||
|
||||
### RECOVERY BACK TO PRIMARY (When repaired)
|
||||
|
||||
1. Create fresh RMAN backup from DR (now contains latest data)
|
||||
2. Transfer backup to repaired PRIMARY
|
||||
3. Restore on PRIMARY
|
||||
4. Switch DNS/connections back to PRIMARY
|
||||
5. Shutdown DR VM
|
||||
|
||||
### TESTING SCHEDULE
|
||||
- Monthly DR test: Last Sunday of month
|
||||
- Test duration: 30 minutes
|
||||
- Document test results
|
||||
```
|
||||
|
||||
**✅ PHASE 8 COMPLETE:** DR runbook documented
|
||||
|
||||
---
|
||||
|
||||
## 📊 FINAL ARCHITECTURE
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PRODUCTION ENVIRONMENT │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ PRIMARY (10.0.20.36) - Windows Physical Server │
|
||||
│ ├─ Oracle 19c SE2 │
|
||||
│ ├─ Database: ROA │
|
||||
│ ├─ RMAN Backups: │
|
||||
│ │ ├─ FULL: Daily 02:30 AM (~7GB compressed) │
|
||||
│ │ └─ INCREMENTAL: Daily 14:00 (~50MB) │
|
||||
│ └─ Automatic Transfer to DR via SSH/SCP │
|
||||
│ │
|
||||
│ ↓ SSH Transfer │
|
||||
│ ↓ (950 Mbps) │
|
||||
│ ↓ │
|
||||
│ DR (10.0.20.37) - Windows VM in Proxmox (ID 109) │
|
||||
│ ├─ Oracle 19c SE2 (installed, ready) │
|
||||
│ ├─ VM State: POWERED OFF (0 RAM consumption) │
|
||||
│ ├─ Backups: D:\oracle\backups\primary │
|
||||
│ ├─ Storage: 100 GB (OS + Oracle + backups) │
|
||||
│ └─ Restore Script: D:\oracle\scripts\rman_restore... │
|
||||
│ │
|
||||
│ DR ACTIVATION (when needed): │
|
||||
│ ├─ 1. Power ON VM (2 min) │
|
||||
│ ├─ 2. Run restore script (12 min) │
|
||||
│ ├─ 3. Database OPEN (1 min) │
|
||||
│ └─ TOTAL RTO: ~15 minutes │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
METRICS:
|
||||
- RPO: 24 hours (daily backup) + 6 hours (incremental)
|
||||
- RTO: 15 minutes
|
||||
- Storage: 150 GB total (100GB VM + 50GB backups)
|
||||
- Daily resources: ZERO (VM powered off)
|
||||
- DR test: Monthly
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ POST-IMPLEMENTATION CHECKLIST
|
||||
|
||||
After completing all phases, verify:
|
||||
|
||||
- [ ] Windows VM created in Proxmox (VM ID 109, IP 10.0.20.37)
|
||||
- [ ] Oracle 19c SE2 installed and working
|
||||
- [ ] OpenSSH Server configured with passwordless authentication
|
||||
- [ ] Transfer scripts updated and tested (FULL + INCREMENTAL)
|
||||
- [ ] RMAN restore script created on DR VM
|
||||
- [ ] DR restore tested successfully (database opens and is usable)
|
||||
- [ ] Scheduled tasks on PRIMARY updated
|
||||
- [ ] DR runbook documented and accessible
|
||||
- [ ] Team trained on DR activation procedure
|
||||
- [ ] Monthly DR test scheduled in calendar
|
||||
- [ ] VM shutdown after initial setup (to conserve resources)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 TROUBLESHOOTING GUIDE
|
||||
|
||||
### Issue: SSH Connection Fails
|
||||
```powershell
|
||||
# Check 1: SSH service running?
|
||||
Get-Service sshd
|
||||
|
||||
# Check 2: Firewall blocking?
|
||||
Get-NetFirewallRule -Name *ssh*
|
||||
|
||||
# Check 3: Authorized keys permissions?
|
||||
icacls "C:\ProgramData\ssh\administrators_authorized_keys"
|
||||
|
||||
# Check 4: Test from PRIMARY
|
||||
ssh -v Administrator@10.0.20.37
|
||||
```
|
||||
|
||||
### Issue: RMAN Restore Fails "CONTROLFILE not found"
|
||||
```
|
||||
# This is the cross-platform issue!
|
||||
# Solution: Ensure you're using Windows→Windows (same platform)
|
||||
# Check Oracle version matches: 19c on both sides
|
||||
```
|
||||
|
||||
### Issue: Database Won't Start
|
||||
```powershell
|
||||
# Check alert log
|
||||
Get-Content D:\oracle\diag\rdbms\roa\ROA\trace\alert_ROA.log -Tail 100
|
||||
|
||||
# Check parameter file
|
||||
Get-Content D:\oracle\product\19c\dbhome_1\database\initROA.ora
|
||||
|
||||
# Verify directories exist
|
||||
Test-Path D:\oracle\oradata\ROA
|
||||
Test-Path D:\oracle\fra
|
||||
```
|
||||
|
||||
### Issue: VM Uses Too Much Disk
|
||||
```powershell
|
||||
# Check backup retention
|
||||
Get-ChildItem D:\oracle\backups\primary\*.BKP |
|
||||
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-3) } |
|
||||
Remove-Item -Force
|
||||
|
||||
# Check FRA usage
|
||||
SELECT * FROM V$RECOVERY_FILE_DEST;
|
||||
|
||||
# Cleanup old archives
|
||||
RMAN> DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-2';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 SUPPORT & REFERENCES
|
||||
|
||||
### Oracle Documentation
|
||||
- RMAN Backup and Recovery: https://docs.oracle.com/en/database/oracle/oracle-database/19/bradv/
|
||||
- Cross-Platform Migration: https://docs.oracle.com/en/database/oracle/oracle-database/19/spmds/
|
||||
- Windows Installation: https://docs.oracle.com/en/database/oracle/oracle-database/19/ntqrf/
|
||||
|
||||
### Internal Scripts
|
||||
- PRIMARY RMAN backup: D:\rman_backup\rman_backup.txt
|
||||
- Transfer script (FULL): D:\rman_backup\02_transfer_to_dr_windows.ps1
|
||||
- Transfer script (INCREMENTAL): D:\rman_backup\02b_transfer_incremental_to_dr_windows.ps1
|
||||
- DR restore script: D:\oracle\scripts\rman_restore_from_primary.ps1 (on DR VM)
|
||||
|
||||
### Logs Location
|
||||
- PRIMARY transfer logs: D:\rman_backup\logs\
|
||||
- DR restore logs: D:\oracle\logs\
|
||||
- Oracle alert log: D:\oracle\diag\rdbms\roa\ROA\trace\alert_ROA.log
|
||||
|
||||
---
|
||||
|
||||
## 🎯 IMPLEMENTATION TIMELINE
|
||||
|
||||
| Phase | Task | Duration | Responsible |
|
||||
|-------|------|----------|-------------|
|
||||
| 1 | Create Windows VM in Proxmox | 30 min | Infrastructure Admin |
|
||||
| 2 | Install Oracle 19c | 90 min | DBA |
|
||||
| 3 | Configure SSH | 20 min | Infrastructure Admin |
|
||||
| 4 | Update Transfer Scripts | 15 min | DBA |
|
||||
| 5 | Create Restore Script | 30 min | DBA |
|
||||
| 6 | Test DR Restore | 30 min | DBA |
|
||||
| 7 | Update Scheduled Tasks | 10 min | DBA |
|
||||
| 8 | Document DR Runbook | 15 min | DBA |
|
||||
| **TOTAL** | | **~4 hours** | |
|
||||
|
||||
**Note:** This is one-time setup. After completion, daily operations are fully automated with ZERO maintenance overhead.
|
||||
|
||||
---
|
||||
|
||||
**Generated:** 2025-10-08
|
||||
**Version:** 1.0
|
||||
**Status:** Ready for Implementation
|
||||
**Next Session:** Start with Phase 1 - Create Windows VM
|
||||
|
||||
Reference in New Issue
Block a user