Gasite la instalarea de productie VADECO (Oracle 21c XE, Windows Server 2019). 1. Pe serverul VADECO procesul Oracle nu poate atinge nicio cale de pe C:, nici macar C:\Windows\Temp, desi ACL-urile sunt corecte si serviciul ruleaza ca NT SERVICE\OracleServiceXE. D: merge cu exact acelasi grant. Calea DMP era insa hardcodata "C:\DMPDIR" in 01, 02, 05, 06 si in biblioteca, deci instalarea nu se putea muta. Acum e parametrul -DmpDir, expus ca /dmpdest: in FAZA1.cmd si FAZA2.cmd si transmis tuturor pasilor. Cel mai perfid era pasul 02: recrea DIRECTORY DMPDIR pe 'C:\DMPDIR' peste valoarea pusa de 01. Chiar cu restul instalarii mutata, SYS.NEWSCHEMA ar fi cautat FIRMANOUA.dmp in alta parte, iar adaugarea unei firme noi ar fi picat peste luni, fara legatura vizibila cu instalarea. 2. New-OracleDirectory compara doar siruri de caractere: verifica ce scrie in dba_directories, nu daca baza chiar poate scrie acolo. Acum face un UTL_FILE round-trip si esueaza pe loc, cu explicatia cauzei. Inainte, directorul inutilizabil trecea drept bun si importul cadea abia in impdp cu ORA-29283, la zeci de linii distanta. Valoarea de retur nici nu era verificata in 01/03/06 - de aici si "True" ratacit in log. 3. Instalarea ROAClient seteaza TNS_ADMIN de masina spre instantclient-ul ei. Serviciul Oracle mosteneste variabilele de masina, deci citea sqlnet.ora de acolo - unde nu exista niciunul - si nu din Oracle Home, unde il scria pasul 01. Compatibilitatea pentru clienti vechi nu se aplica, iar statiile ar fi primit ORA-28040 cu fisierul scris corect, in locul gresit. Pasul 01 scrie acum sqlnet.ora si in TNS_ADMIN cand difera. 4. Pasul 05 lega schemele de DMP-uri cu "^$schema[_\.]", deci schema DANUBE putea primi DANUBE_20200914.dmp - datele altei firme, fara avertisment. Numele exact are acum intaietate, prefixul se accepta doar daca e unic, iar ambiguitatea se raporteaza. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
636 lines
25 KiB
PowerShell
636 lines
25 KiB
PowerShell
#Requires -Version 5.1
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Initial database setup for ROA Oracle.
|
|
|
|
.DESCRIPTION
|
|
Performs initial database configuration including:
|
|
- Validates Oracle installation
|
|
- Auto-detects CDB vs non-CDB configuration
|
|
- Configures DEFAULT_PROFILE (disables password expiry)
|
|
- Configures sqlnet.ora for Instant Client 10/11 compatibility
|
|
- Creates tablespace ROA
|
|
- Creates user CONTAFIN_ORACLE with required privileges
|
|
|
|
.PARAMETER OracleHome
|
|
Oracle home directory. If not specified, auto-detects from registry or environment.
|
|
|
|
.PARAMETER ServiceName
|
|
Database service name. Auto-detects: ROA for non-CDB, XEPDB1 for Oracle XE CDB.
|
|
|
|
.PARAMETER SystemPassword
|
|
SYSTEM user password. Default: romfastsoft
|
|
|
|
.PARAMETER ContafinPassword
|
|
CONTAFIN_ORACLE user password. Default: ROMFASTSOFT
|
|
|
|
.PARAMETER DatafileDir
|
|
Directory for tablespace datafiles. Auto-detects if not specified.
|
|
|
|
.PARAMETER TablespaceSize
|
|
Initial size of ROA tablespace in MB. Default: 1000
|
|
|
|
.PARAMETER SkipSqlnetConfig
|
|
Skip sqlnet.ora configuration.
|
|
|
|
.PARAMETER ResetSystemPassword
|
|
Reseteaza parola lui SYSTEM in CDB root, cu aceeasi valoare ($SystemPassword).
|
|
Necesar DOAR pe o baza mai veche, unde SYSTEM a apucat sa intre in
|
|
EXPIRED(GRACE) inainte ca profilul din CDB root sa fie corectat (Step 4b):
|
|
statusul nu se curata singur cand profilul devine UNLIMITED, cere un
|
|
ALTER USER. Pe o instalare noua nu e nevoie - contul nu apuca sa expire.
|
|
Implicit OFF, pentru ca schimba o parola.
|
|
|
|
.EXAMPLE
|
|
.\01-setup-database.ps1
|
|
|
|
.EXAMPLE
|
|
.\01-setup-database.ps1 -ServiceName "XEPDB1" -SystemPassword "mypassword"
|
|
|
|
.EXAMPLE
|
|
.\01-setup-database.ps1 -OracleHome "C:\app\oracle\product\21c\dbhomeXE" -DatafileDir "D:\oradata"
|
|
|
|
.NOTES
|
|
File Name : 01-setup-database.ps1
|
|
Prerequisite : Oracle Database installed, PowerShell 5.1+
|
|
Copyright 2024 : ROMFAST
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$OracleHome,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ServiceName,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$DbHost,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[int]$Port = 1521,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$SystemPassword = "romfastsoft",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ContafinPassword = "ROMFASTSOFT",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$DatafileDir,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[int]$TablespaceSize = 1000,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$SkipSqlnetConfig,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$ResetSystemPassword,
|
|
|
|
# Calea fizica a directorului Oracle DMPDIR. Aceeasi valoare trebuie data
|
|
# tuturor pasilor care ating DMPDIR (01, 02, 03, 05, 06), altfel ultimul
|
|
# care ruleaza repozitioneaza obiectul si ceilalti citesc din alta parte.
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$DmpDir = "C:\DMPDIR"
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Load config.ps1 if exists (provides defaults)
|
|
$configPath = Join-Path (Split-Path $PSScriptRoot -Parent) "config.ps1"
|
|
if (Test-Path $configPath) {
|
|
. $configPath
|
|
# Use config values if parameters not provided
|
|
if (-not $OracleHome -and $ORACLE_HOME) { $OracleHome = $ORACLE_HOME }
|
|
if (-not $ServiceName -and $SERVICE_NAME) { $ServiceName = $SERVICE_NAME }
|
|
if (-not $DbHost -and $DB_HOST) { $DbHost = $DB_HOST }
|
|
if (-not $Port -and $DB_PORT) { $Port = $DB_PORT }
|
|
if ($SystemPassword -eq "romfastsoft" -and $SYSTEM_PASSWORD) { $SystemPassword = $SYSTEM_PASSWORD }
|
|
if ($ContafinPassword -eq "ROMFASTSOFT" -and $CONTAFIN_PASSWORD) { $ContafinPassword = $CONTAFIN_PASSWORD }
|
|
if (-not $DatafileDir -and $DATAFILE_DIR) { $DatafileDir = $DATAFILE_DIR }
|
|
}
|
|
|
|
# Source library functions
|
|
. "$PSScriptRoot\lib\logging-functions.ps1"
|
|
. "$PSScriptRoot\lib\oracle-functions.ps1"
|
|
|
|
# Initialize logging
|
|
$logPath = Join-Path $PSScriptRoot "..\logs\01-setup-database_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
|
Initialize-LogFile -LogPath $logPath -ScriptName "01-setup-database.ps1"
|
|
|
|
try {
|
|
Write-LogSection "ROA Database Initial Setup"
|
|
|
|
# Step 1: Validate Oracle installation
|
|
Write-Log "Detecting Oracle installation..."
|
|
|
|
$oraHome = Get-OracleHome -OracleHome $OracleHome
|
|
Write-LogSuccess "Oracle Home: $oraHome"
|
|
|
|
# Step 2: Auto-detect service name if not specified
|
|
if (-not $ServiceName) {
|
|
Write-Log "Auto-detecting service name..."
|
|
|
|
# First try to connect to XE to check CDB status
|
|
try {
|
|
$version = Get-OracleVersion -OracleHome $oraHome -ServiceName "XE" -DbHost $DbHost -Port $Port -Password $SystemPassword
|
|
if ($version.IsCDB) {
|
|
$ServiceName = "XEPDB1"
|
|
Write-Log "Detected CDB installation, using PDB: XEPDB1"
|
|
}
|
|
else {
|
|
$ServiceName = "XE"
|
|
Write-Log "Detected non-CDB installation, using service: XE"
|
|
}
|
|
}
|
|
catch {
|
|
# Try ROA as fallback
|
|
try {
|
|
$null = Test-OracleConnection -OracleHome $oraHome -ServiceName "ROA" -DbHost $DbHost -Port $Port -Password $SystemPassword
|
|
$ServiceName = "ROA"
|
|
Write-Log "Using existing service: ROA"
|
|
}
|
|
catch {
|
|
$ServiceName = "XEPDB1"
|
|
Write-Log "Defaulting to XEPDB1"
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-LogSuccess "Service Name: $ServiceName"
|
|
if ($DbHost) {
|
|
Write-Log "Database Host: ${DbHost}:${Port}"
|
|
}
|
|
|
|
# Step 3: Test connection
|
|
Write-Log "Testing database connection..."
|
|
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword)) {
|
|
throw "Cannot connect to database. Please verify ServiceName, Host and SystemPassword."
|
|
}
|
|
Write-LogSuccess "Database connection successful"
|
|
|
|
# Get version info
|
|
$versionInfo = Get-OracleVersion -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword
|
|
Write-Log "Oracle Version: $($versionInfo.Version)"
|
|
Write-Log "Oracle Edition: $($versionInfo.Edition)"
|
|
Write-Log "CDB Mode: $($versionInfo.IsCDB)"
|
|
|
|
# Check container info
|
|
$containerInfo = Test-PDB -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword
|
|
Write-Log "Container: $($containerInfo.ContainerName)"
|
|
if ($containerInfo.IsPDB) {
|
|
Write-Log "Connected to PDB (Pluggable Database)"
|
|
}
|
|
elseif ($containerInfo.IsNonCDB) {
|
|
Write-Log "Connected to non-CDB database"
|
|
}
|
|
|
|
# Step 4: Configure DEFAULT_PROFILE (no password expiry)
|
|
Write-LogSection "Configuring DEFAULT_PROFILE"
|
|
|
|
$profileSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
PROMPT Configuring DEFAULT_PROFILE - disabling password expiration...
|
|
ALTER PROFILE DEFAULT LIMIT
|
|
PASSWORD_LIFE_TIME UNLIMITED
|
|
PASSWORD_GRACE_TIME UNLIMITED
|
|
PASSWORD_REUSE_TIME UNLIMITED
|
|
PASSWORD_REUSE_MAX UNLIMITED
|
|
FAILED_LOGIN_ATTEMPTS UNLIMITED
|
|
PASSWORD_LOCK_TIME UNLIMITED;
|
|
COMMIT;
|
|
SELECT 'PROFILE_CONFIGURED' FROM dual;
|
|
EXIT;
|
|
"@
|
|
|
|
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $profileSql -AsSysdba
|
|
|
|
if ($result -match "PROFILE_CONFIGURED") {
|
|
Write-LogSuccess "DEFAULT_PROFILE configured successfully"
|
|
}
|
|
else {
|
|
Write-LogWarning "Could not verify profile configuration"
|
|
Write-LogDebug $result
|
|
}
|
|
|
|
# Step 4b: Acelasi profil si in CDB root
|
|
# ALTER PROFILE dintr-un PDB NU acopera CDB root: acolo DEFAULT ramane cu
|
|
# PASSWORD_LIFE_TIME 180, deci SYSTEM din root expira la ~6 luni de la instalare
|
|
# (ORA-28002, apoi ORA-28001). Verificat pe VM 302: SYSTEM era EXPIRED(GRACE).
|
|
# Se comuta pe CDB$ROOT ca SYSDBA si se altereaza profilul local de acolo.
|
|
if ($containerInfo.IsPDB) {
|
|
Write-Log "Applying DEFAULT_PROFILE in CDB root as well..."
|
|
|
|
$profileCdbSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
ALTER SESSION SET CONTAINER = CDB`$ROOT;
|
|
ALTER PROFILE DEFAULT LIMIT
|
|
PASSWORD_LIFE_TIME UNLIMITED
|
|
PASSWORD_GRACE_TIME UNLIMITED
|
|
PASSWORD_REUSE_TIME UNLIMITED
|
|
PASSWORD_REUSE_MAX UNLIMITED
|
|
FAILED_LOGIN_ATTEMPTS UNLIMITED
|
|
PASSWORD_LOCK_TIME UNLIMITED;
|
|
SELECT 'PROFILE_CDB_CONFIGURED' FROM dual;
|
|
EXIT;
|
|
"@
|
|
|
|
$resultCdb = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $profileCdbSql -AsSysdba
|
|
|
|
if ($resultCdb -match "PROFILE_CDB_CONFIGURED" -and $resultCdb -notmatch "ORA-") {
|
|
Write-LogSuccess "DEFAULT_PROFILE configured in CDB root"
|
|
}
|
|
else {
|
|
Write-LogWarning "Could not configure DEFAULT_PROFILE in CDB root"
|
|
Write-LogWarning "SYSTEM din CDB root va expira la ~180 de zile. Manual:"
|
|
Write-LogWarning " ALTER SESSION SET CONTAINER=CDB`$ROOT;"
|
|
Write-LogWarning " ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED CONTAINER=ALL;"
|
|
Write-LogDebug $resultCdb
|
|
}
|
|
|
|
# Step 4c (optional): curata EXPIRED(GRACE) pe SYSTEM din CDB root.
|
|
# ALTER PROFILE opreste expirarile viitoare, dar NU reseteaza statusul
|
|
# unui cont deja intrat in perioada de gratie - asta cere un ALTER USER.
|
|
# Opt-in, fiindca scrie o parola.
|
|
if ($ResetSystemPassword) {
|
|
Write-Log "Resetting SYSTEM password in CDB root (clears EXPIRED(GRACE))..."
|
|
|
|
$resetSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
ALTER SESSION SET CONTAINER = CDB`$ROOT;
|
|
ALTER USER SYSTEM IDENTIFIED BY "$SystemPassword";
|
|
SELECT 'SYSTEM_STATUS:' || account_status AS rez FROM dba_users WHERE username = 'SYSTEM';
|
|
EXIT;
|
|
"@
|
|
|
|
$resetResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $resetSql -AsSysdba
|
|
|
|
if ($resetResult -match "SYSTEM_STATUS:OPEN" -and $resetResult -notmatch "ORA-") {
|
|
Write-LogSuccess "SYSTEM in CDB root: OPEN"
|
|
}
|
|
else {
|
|
Write-LogWarning "Nu am putut confirma resetarea lui SYSTEM in CDB root. Manual:"
|
|
Write-LogWarning " ALTER SESSION SET CONTAINER=CDB`$ROOT;"
|
|
Write-LogWarning " ALTER USER SYSTEM IDENTIFIED BY <parola>;"
|
|
Write-LogDebug $resetResult
|
|
}
|
|
}
|
|
}
|
|
|
|
# Step 5: Configure sqlnet.ora for old client compatibility
|
|
if (-not $SkipSqlnetConfig) {
|
|
Write-LogSection "Configuring sqlnet.ora"
|
|
|
|
# Oracle 21c uses read-only Oracle Home - config goes to 'homes' directory
|
|
# Check for Oracle 21c homes directory structure first
|
|
$oraBase = Split-Path (Split-Path (Split-Path $oraHome -Parent) -Parent) -Parent
|
|
$homesDir = Join-Path $oraBase "product\21c\homes"
|
|
|
|
# Find the actual Oracle Base Home (where user configs go)
|
|
$networkAdmin = $null
|
|
if (Test-Path $homesDir) {
|
|
# Oracle 21c with read-only Oracle Home
|
|
$oraBaseHome = Get-ChildItem -Path $homesDir -Directory |
|
|
Where-Object { $_.Name -match "OraDB" } |
|
|
Select-Object -First 1
|
|
if ($oraBaseHome) {
|
|
$networkAdmin = Join-Path $oraBaseHome.FullName "network\admin"
|
|
Write-Log "Detected Oracle 21c read-only Home structure"
|
|
Write-Log "Using Oracle Base Home: $($oraBaseHome.FullName)"
|
|
}
|
|
}
|
|
|
|
# Fallback to traditional location
|
|
if (-not $networkAdmin -or -not (Test-Path (Split-Path $networkAdmin -Parent))) {
|
|
$networkAdmin = Join-Path $oraHome "network\admin"
|
|
Write-Log "Using traditional Oracle Home network/admin location"
|
|
}
|
|
|
|
$sqlnetOra = Join-Path $networkAdmin "sqlnet.ora"
|
|
|
|
if (-not (Test-Path -Path $networkAdmin)) {
|
|
New-Item -ItemType Directory -Path $networkAdmin -Force | Out-Null
|
|
}
|
|
|
|
# Backup existing sqlnet.ora
|
|
if (Test-Path -Path $sqlnetOra) {
|
|
$backupPath = "$sqlnetOra.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
|
Copy-Item -Path $sqlnetOra -Destination $backupPath -Force
|
|
Write-Log "Backed up existing sqlnet.ora to $backupPath"
|
|
}
|
|
|
|
# Create sqlnet.ora with compatibility settings
|
|
$sqlnetContent = @"
|
|
# sqlnet.ora - ROA Oracle Configuration
|
|
# Generated by 01-setup-database.ps1 on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
|
|
|
|
# Allow connections from old Oracle Instant Client 10g/11g (ODBC drivers)
|
|
# These clients don't support newer authentication methods
|
|
SQLNET.ALLOWED_LOGON_VERSION_SERVER=8
|
|
SQLNET.ALLOWED_LOGON_VERSION_CLIENT=8
|
|
|
|
# Disable encryption requirement for old clients
|
|
SQLNET.ENCRYPTION_SERVER = ACCEPTED
|
|
SQLNET.CRYPTO_CHECKSUM_SERVER = ACCEPTED
|
|
|
|
# Timp maxim pentru finalizarea handshake-ului de conectare (setare de server).
|
|
# Nu limiteaza durata operatiilor de dupa conectare.
|
|
SQLNET.INBOUND_CONNECT_TIMEOUT = 60
|
|
|
|
# ATENTIE: NU pune aici SQLNET.RECV_TIMEOUT / SQLNET.SEND_TIMEOUT.
|
|
# Fisierul asta e citit si de clientii de pe aceeasi masina (sqlplus, impdp,
|
|
# expdp). RECV_TIMEOUT limiteaza cat asteapta CLIENTUL un pachet de raspuns,
|
|
# iar in timpul unui import Data Pump serverul poate lucra minute intregi fara
|
|
# sa trimita nimic (creare de indecsi, constrangeri). Cu RECV_TIMEOUT = 30,
|
|
# clientul impdp moare cu ORA-12609 "TNS: Receive timeout occurred", desi jobul
|
|
# de pe server continua si se termina cu bine. Rezultatul e si mai perfid decat
|
|
# un esec curat: 03-import-contafin.ps1 numara obiectele imediat dupa moartea
|
|
# clientului, gaseste 0 si raporteaza esec pentru un import care a reusit.
|
|
# Verificat pe VM 302 (2026-08-25).
|
|
|
|
# TNS Names directory
|
|
NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
|
|
"@
|
|
|
|
Set-Content -Path $sqlnetOra -Value $sqlnetContent -Encoding ASCII
|
|
Write-LogSuccess "sqlnet.ora configured at $sqlnetOra"
|
|
Write-Log "Old client compatibility enabled (SQLNET.ALLOWED_LOGON_VERSION=8)"
|
|
|
|
# Daca exista TNS_ADMIN la nivel de masina, ACELA castiga - si pentru
|
|
# clienti, si pentru serviciul Oracle, care mosteneste variabilele de
|
|
# masina. Instalarea ROAClient il pune sa arate spre instantclient-ul
|
|
# ei (D:\ROA\instantclient_11_2_0_2), unde de obicei nu exista niciun
|
|
# sqlnet.ora: atunci serverul cade pe valorile implicite, adica
|
|
# ALLOWED_LOGON_VERSION_SERVER=12, si clientii vechi primesc ORA-28040
|
|
# desi fisierul de mai sus a fost scris corect. Scriem acelasi continut
|
|
# si acolo, altfel toata configurarea de compatibilitate e degeaba.
|
|
$tnsAdmin = [Environment]::GetEnvironmentVariable('TNS_ADMIN', 'Machine')
|
|
if ($tnsAdmin) {
|
|
$tnsAdminFull = [IO.Path]::GetFullPath($tnsAdmin.TrimEnd('\'))
|
|
if ($tnsAdminFull -ne [IO.Path]::GetFullPath($networkAdmin.TrimEnd('\'))) {
|
|
Write-LogWarning "TNS_ADMIN de masina arata spre $tnsAdminFull - acolo se citeste sqlnet.ora, nu din Oracle Home."
|
|
if (-not (Test-Path $tnsAdminFull)) {
|
|
New-Item -ItemType Directory -Path $tnsAdminFull -Force | Out-Null
|
|
}
|
|
$tnsSqlnet = Join-Path $tnsAdminFull "sqlnet.ora"
|
|
if (Test-Path $tnsSqlnet) {
|
|
Copy-Item $tnsSqlnet "$tnsSqlnet.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')" -Force
|
|
}
|
|
Set-Content -Path $tnsSqlnet -Value $sqlnetContent -Encoding ASCII
|
|
Write-LogSuccess "sqlnet.ora scris si in TNS_ADMIN: $tnsSqlnet"
|
|
}
|
|
}
|
|
|
|
# Restart listener to apply changes
|
|
Write-Log "Restarting listener to apply sqlnet.ora changes..."
|
|
$lsnrctl = Join-Path $oraHome "bin\lsnrctl.exe"
|
|
if (Test-Path $lsnrctl) {
|
|
try {
|
|
& $lsnrctl stop 2>&1 | Out-Null
|
|
Start-Sleep -Seconds 3
|
|
$lsnrOutput = & $lsnrctl start 2>&1
|
|
Write-LogSuccess "Listener restarted successfully"
|
|
|
|
# Wait for services to register (can take 30-60 seconds)
|
|
Write-Log "Waiting for database services to register with listener..."
|
|
$maxWait = 60
|
|
$waited = 0
|
|
$interval = 5
|
|
while ($waited -lt $maxWait) {
|
|
Start-Sleep -Seconds $interval
|
|
$waited += $interval
|
|
# Check if our service is registered
|
|
$lsnrStatus = & $lsnrctl status 2>&1 | Out-String
|
|
if ($lsnrStatus -match $ServiceName) {
|
|
Write-Log "Service $ServiceName registered after ${waited}s"
|
|
break
|
|
}
|
|
Write-Log "Waiting... (${waited}s/${maxWait}s)"
|
|
}
|
|
if ($waited -ge $maxWait) {
|
|
Write-LogWarning "Service may not be fully registered yet. Continuing anyway..."
|
|
}
|
|
}
|
|
catch {
|
|
Write-LogWarning "Could not restart listener: $_"
|
|
Write-Log "Please restart listener manually: lsnrctl stop && lsnrctl start"
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Write-Log "Skipping sqlnet.ora configuration as requested"
|
|
}
|
|
|
|
# Step 6: Get datafile path
|
|
if (-not $DatafileDir) {
|
|
Write-Log "Auto-detecting datafile path..."
|
|
$DatafileDir = Get-DatafilePath -OracleHome $oraHome -ServiceName $ServiceName -Password $SystemPassword
|
|
}
|
|
Write-LogSuccess "Datafile directory: $DatafileDir"
|
|
|
|
# Step 7: Create tablespace ROA
|
|
Write-LogSection "Creating Tablespace ROA"
|
|
|
|
# Check if tablespace already exists
|
|
$checkTsSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
|
|
SELECT 'TS_EXISTS' FROM dba_tablespaces WHERE tablespace_name = 'ROA';
|
|
EXIT;
|
|
"@
|
|
|
|
$tsResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $checkTsSql -Silent
|
|
|
|
if ($tsResult -match "TS_EXISTS") {
|
|
Write-LogWarning "Tablespace ROA already exists, skipping creation"
|
|
}
|
|
else {
|
|
$datafilePath = Join-Path $DatafileDir "TS_ROA.DBF"
|
|
|
|
$createTsSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
PROMPT Creating tablespace ROA...
|
|
CREATE SMALLFILE TABLESPACE "ROA"
|
|
DATAFILE '$datafilePath' SIZE ${TablespaceSize}M
|
|
AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
|
|
LOGGING
|
|
EXTENT MANAGEMENT LOCAL
|
|
SEGMENT SPACE MANAGEMENT AUTO;
|
|
COMMIT;
|
|
SELECT 'TS_CREATED' FROM dual;
|
|
EXIT;
|
|
"@
|
|
|
|
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createTsSql
|
|
|
|
if ($result -match "TS_CREATED") {
|
|
Write-LogSuccess "Tablespace ROA created successfully"
|
|
Write-Log "Datafile: $datafilePath"
|
|
}
|
|
else {
|
|
Write-LogError "Failed to create tablespace ROA"
|
|
Write-LogDebug $result
|
|
throw "Tablespace creation failed"
|
|
}
|
|
}
|
|
|
|
# Step 8: Create user CONTAFIN_ORACLE
|
|
Write-LogSection "Creating User CONTAFIN_ORACLE"
|
|
|
|
# Check if user already exists
|
|
if (Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE") {
|
|
Write-LogWarning "User CONTAFIN_ORACLE already exists"
|
|
|
|
# Update password
|
|
$updatePwdSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
ALTER USER CONTAFIN_ORACLE IDENTIFIED BY "$ContafinPassword";
|
|
COMMIT;
|
|
SELECT 'PWD_UPDATED' FROM dual;
|
|
EXIT;
|
|
"@
|
|
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $updatePwdSql -Silent
|
|
|
|
if ($result -match "PWD_UPDATED") {
|
|
Write-Log "Password updated for CONTAFIN_ORACLE"
|
|
}
|
|
}
|
|
else {
|
|
$createUserSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
|
|
PROMPT Creating user CONTAFIN_ORACLE...
|
|
CREATE USER CONTAFIN_ORACLE
|
|
IDENTIFIED BY "$ContafinPassword"
|
|
DEFAULT TABLESPACE ROA
|
|
TEMPORARY TABLESPACE TEMP
|
|
PROFILE DEFAULT;
|
|
|
|
PROMPT Granting role privileges...
|
|
GRANT CONNECT TO CONTAFIN_ORACLE;
|
|
GRANT RESOURCE TO CONTAFIN_ORACLE;
|
|
|
|
PROMPT Granting system privileges...
|
|
GRANT CREATE ANY CONTEXT TO CONTAFIN_ORACLE;
|
|
GRANT CREATE SESSION TO CONTAFIN_ORACLE;
|
|
GRANT CREATE VIEW TO CONTAFIN_ORACLE;
|
|
GRANT DELETE ANY TABLE TO CONTAFIN_ORACLE;
|
|
GRANT DROP ANY CONTEXT TO CONTAFIN_ORACLE;
|
|
GRANT EXECUTE ANY PROCEDURE TO CONTAFIN_ORACLE;
|
|
GRANT INSERT ANY TABLE TO CONTAFIN_ORACLE;
|
|
GRANT SELECT ANY DICTIONARY TO CONTAFIN_ORACLE;
|
|
GRANT SELECT ANY SEQUENCE TO CONTAFIN_ORACLE;
|
|
GRANT SELECT ANY TABLE TO CONTAFIN_ORACLE;
|
|
GRANT UNLIMITED TABLESPACE TO CONTAFIN_ORACLE;
|
|
GRANT UPDATE ANY TABLE TO CONTAFIN_ORACLE;
|
|
GRANT CREATE PUBLIC SYNONYM TO CONTAFIN_ORACLE;
|
|
GRANT DROP PUBLIC SYNONYM TO CONTAFIN_ORACLE;
|
|
|
|
COMMIT;
|
|
SELECT 'USER_CREATED' FROM dual;
|
|
EXIT;
|
|
"@
|
|
|
|
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql
|
|
|
|
if ($result -match "USER_CREATED") {
|
|
Write-LogSuccess "User CONTAFIN_ORACLE created successfully"
|
|
}
|
|
else {
|
|
Write-LogError "Failed to create user CONTAFIN_ORACLE"
|
|
Write-LogDebug $result
|
|
throw "User creation failed"
|
|
}
|
|
}
|
|
|
|
# Verify user privileges
|
|
$verifyUserSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
SELECT privilege FROM dba_sys_privs WHERE grantee = 'CONTAFIN_ORACLE' ORDER BY privilege;
|
|
EXIT;
|
|
"@
|
|
|
|
$privileges = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $verifyUserSql -Silent
|
|
|
|
Write-Log "CONTAFIN_ORACLE privileges verified"
|
|
|
|
# Step 9: Create DMPDIR directory for Data Pump
|
|
Write-LogSection "Creating Data Pump Directory"
|
|
|
|
if (-not (New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $DmpDir)) {
|
|
throw "Directorul Data Pump DMPDIR ($DmpDir) nu e utilizabil de catre baza. Vezi mesajele de mai sus."
|
|
}
|
|
|
|
Write-LogSuccess "Data Pump directory DMPDIR created: $DmpDir"
|
|
|
|
# Step 10: Reset passwords with 10G verifier (required for old client auth)
|
|
# After sqlnet.ora is configured, passwords must be reset to generate 10G hash
|
|
if (-not $SkipSqlnetConfig) {
|
|
Write-LogSection "Resetting Passwords for Old Client Compatibility"
|
|
Write-Log "Resetting passwords to generate 10G password verifiers..."
|
|
|
|
$resetPwdSql = @"
|
|
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
|
-- Reset CONTAFIN_ORACLE password to generate 10G verifier
|
|
ALTER USER CONTAFIN_ORACLE IDENTIFIED BY "$ContafinPassword";
|
|
-- Verify password versions
|
|
SELECT USERNAME, PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME = 'CONTAFIN_ORACLE';
|
|
SELECT 'PWD_RESET_DONE' FROM DUAL;
|
|
EXIT;
|
|
"@
|
|
|
|
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $resetPwdSql
|
|
|
|
if ($result -match "PWD_RESET_DONE") {
|
|
Write-LogSuccess "Password reset completed - 10G verifier now available"
|
|
if ($result -match "10G") {
|
|
Write-Log "Verified: Password has 10G verifier for old client compatibility"
|
|
}
|
|
}
|
|
else {
|
|
Write-LogWarning "Could not verify password reset"
|
|
}
|
|
}
|
|
|
|
# Summary
|
|
Write-LogSection "Setup Complete"
|
|
Write-LogSuccess "Database initial setup completed successfully!"
|
|
Write-Host ""
|
|
Write-Log "Summary:"
|
|
Write-Log " Oracle Home: $oraHome"
|
|
Write-Log " Service Name: $ServiceName"
|
|
Write-Log " Oracle Version: $($versionInfo.Version)"
|
|
Write-Log " Container: $($containerInfo.ContainerName)"
|
|
Write-Log " Tablespace ROA: $DatafileDir\TS_ROA.DBF"
|
|
Write-Log " User: CONTAFIN_ORACLE"
|
|
Write-Log " Data Pump Dir: DMPDIR -> $dmpDir"
|
|
if (-not $SkipSqlnetConfig) {
|
|
Write-Log " Old Client Auth: Enabled (sqlnet.ora + 10G verifier)"
|
|
}
|
|
Write-Host ""
|
|
Write-Log "Next steps:"
|
|
Write-Log " 1. Run 02-create-sys-objects.ps1 to install SYS objects"
|
|
Write-Log " 2. Run 03-import-contafin.ps1 to import CONTAFIN_ORACLE schema"
|
|
|
|
Close-LogFile -Success $true
|
|
exit 0
|
|
}
|
|
catch {
|
|
Write-LogError "Setup failed: $_"
|
|
Write-LogError $_.ScriptStackTrace
|
|
Close-LogFile -Success $false
|
|
exit 1
|
|
}
|