Files
ROMFASTSQL/proxmox/lxc108-oracle/roa-windows-setup/scripts/01-setup-database.ps1
Marius ec66377e0f fix(oracle): calea DMPDIR devine parametru; sqlnet.ora ajunge unde e citit
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
2026-08-25 21:18:43 +03:00

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
}