fix(roa): aliasul TNS lipsea din Oracle Home, iar actualizarea esua tacut

Constatat la VADECO pe 2026-08-28: pe serverul acela actualizarea ROA nu
aplicase NICIODATA un script, desi jobul raporta succes de la instalare.

PACK_UPDATE nu aplica el scripturile - genereaza D:\DMPDIR\script_master.sql
si lanseaza un sqlplus EXTERN, apoi se termina. Deci UPDATEROA_ZILNIC
raporteaza starea lansarii, nu a actualizarii: SUCCEEDED in ~5 secunde chiar
si cand nu s-a aplicat nimic. Scriptul generat incepe cu
"CONNECT CONTAFIN_ORACLE/...@ROA" (aliasul vine din NOM_FIRME.NUME_SERVER)
si are WHENEVER SQLERROR EXIT, deci iese la prima linie daca aliasul nu se
rezolva.

Lantul cauzal: sqlplus-ul lansat de baza mosteneste mediul serviciului
Oracle. La o instalare noua instanta porneste INAINTE ca 01-setup-database
sa scrie TNS_ADMIN de masina, deci serviciul nu il are si cade pe
tnsnames.ora din Oracle Home. La 21c XE home-ul e read-only, deci fisierul
real e in product\21c\homes\OraDB21Home1\network\admin, iar acolo Oracle
genereaza doar XE, LISTENER_XE si ORACLR_CONNECTION_DATA - fara ROA.
Rezultat: ORA-12154, tacut. Perfid: tnsping ROA REUSESTE dintr-o sesiune
interactiva, pentru ca aceea are TNS_ADMIN.

Eroarea era mascata dublu - jobul zicea SUCCEEDED, iar emailul de raportare
nu pleaca oricum (ORA-29279, SMTP-ul romfast nu anunta AUTH).

01-setup-database.ps1 scrie acum aliasul si in tnsnames.ora al Oracle
Home-ului, cu acelasi IP din LAN. Blocul se IMBINA in fisierul existent:
XE, LISTENER_XE si ORACLR_CONNECTION_DATA raman neatinse, pentru ca de ele
depind extproc si inregistrarea instantei la listener. Cu backup si
idempotent - regexul consuma si comentariile lipite deasupra lui "ROA =",
altfel antetul se dubla la fiecare rulare (prins de test).

Testat unitar (fisier Oracle fara ROA, idempotenta peste 4 rulari, ROA
preexistent cu alt IP la mijloc, fisier inexistent, paranteze echilibrate,
fara BOM) si end-to-end pe o copie a fisierului real de pe serverul VADECO:
tnsping ROA OK, sqlplus CONTAFIN_ORACLE@ROA conectat in XEPDB1, zero ORA-,
XE si LISTENER_XE inca se rezolva.

docs/lectii-actualizare-roa-alias-tns.md are diagnosticul complet, inclusiv
cum verifici ca actualizarea chiar s-a aplicat: script_master.log si
SCHEMA.versiune, NU statusul jobului. Contine si capcana ca randurile din
SCHEMA.versiune vin cu dump-ul la import, deci o schema proaspat importata
pare la zi fara ca actualizarea sa fi rulat vreodata local.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9Sa54oFKpE2XhD6A7NTch
This commit is contained in:
Marius
2026-08-28 15:04:10 +03:00
parent e9b07853b0
commit 31c4065bd2
4 changed files with 234 additions and 6 deletions

View File

@@ -353,6 +353,16 @@ EXEC DBMS_SCHEDULER.ENABLE('CONTAFIN_ORACLE.UPDATEROA_ZILNIC');
EXEC DBMS_SCHEDULER.ENABLE('CONTAFIN_ORACLE.UPDATERTVAI_ZILNIC');
```
> **`SUCCEEDED` la jobul de update NU înseamnă că s-a aplicat ceva.** Jobul doar
> lansează un `sqlplus` extern și se termină în ~5 secunde. Dacă aliasul TNS din
> `NOM_FIRME.NUME_SERVER` (de regulă `ROA`) nu se rezolvă **în mediul serviciului
> Oracle**, scriptul generat iese la prima linie cu `ORA-12154` și actualizarea nu
> rulează niciodată — tăcut, pentru că jobul raportează succes, iar emailul de
> eroare nu pleacă. `01-setup-database.ps1` scrie aliasul și în `tnsnames.ora` al
> Oracle Home-ului tocmai pentru asta. Verifică `D:\DMPDIR\script_master.log` și
> `SCHEMA.versiune`, nu statusul jobului. Ghidul complet:
> [`../../../docs/lectii-actualizare-roa-alias-tns.md`](../../../docs/lectii-actualizare-roa-alias-tns.md).
Serverul ROMFAST de update e documentat în
[`../../vm201-windows/docs/vm201-roa-update-server.md`](../../vm201-windows/docs/vm201-roa-update-server.md).

View File

@@ -364,6 +364,69 @@ NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
Write-LogSuccess "sqlnet.ora configured at $sqlnetOra"
Write-Log "Old client compatibility enabled (SQLNET.ALLOWED_LOGON_VERSION=8)"
# Gazda pentru aliasurile TNS: IP-ul din LAN, nu localhost, ca acelasi
# fisier sa functioneze si copiat pe statiile de lucru.
$gazdaTns = Get-ServerLanIPv4
if (-not $gazdaTns) {
$gazdaTns = $env:COMPUTERNAME
Write-LogWarning "Nu am putut determina IP-ul din LAN; folosesc numele masinii ($gazdaTns) in tnsnames.ora."
}
$roaAliasBlock = @"
# Aliasul ROA - necesar si serverului, nu doar statiilor. Vezi comentariul din
# 01-setup-database.ps1 si docs/lectii-actualizare-roa-alias-tns.md.
ROA =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = $gazdaTns)(PORT = $Port))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = $ServiceName)
)
)
"@
# Aliasul ROA trebuie sa existe SI in tnsnames.ora al Oracle Home-ului,
# nu doar in cel din TNS_ADMIN (instantclient).
#
# PACK_UPDATE (actualizarea ROA) genereaza D:\DMPDIR\script_master.sql si
# lanseaza un sqlplus EXTERN care incepe cu
# CONNECT CONTAFIN_ORACLE/...@<NOM_FIRME.NUME_SERVER>
# adica, in practica, @ROA. Scriptul are WHENEVER SQLERROR EXIT, deci
# iese la prima linie daca aliasul nu se rezolva - iar jobul
# UPDATEROA_ZILNIC raporteaza TOTUSI SUCCEEDED, pentru ca el doar
# lanseaza procesul si se termina in ~5 secunde.
#
# sqlplus-ul lansat de baza mosteneste mediul serviciului Oracle. Daca
# instanta a pornit INAINTE ca TNS_ADMIN de masina sa existe - cazul
# normal la o instalare noua, unde variabila o scriem noi mai jos -
# serviciul nu are TNS_ADMIN si cade pe tnsnames.ora de aici. Fara
# aliasul de mai jos: ORA-12154, si actualizarea ROA nu se aplica
# niciodata, complet tacut.
# Constatat la VADECO pe 2026-08-28, dupa migrare: actualizarea nu
# rulase niciodata pe serverul acela. Detalii in
# docs/lectii-actualizare-roa-alias-tns.md.
$homeTnsNames = Join-Path $networkAdmin "tnsnames.ora"
if (Test-Path $homeTnsNames) {
$stampHomeTns = Get-Date -Format 'yyyyMMdd_HHmmss'
Copy-Item $homeTnsNames "$homeTnsNames.bak_$stampHomeTns" -Force
# Scot un eventual alias ROA existent (rulare anterioara, alt IP) si
# il rescriu, ca operatia sa fie idempotenta. Restul fisierului -
# XE, LISTENER_XE, ORACLR_CONNECTION_DATA - ramane neatins: sunt
# generate de Oracle si folosite de extproc si de inregistrarea la
# listener.
# Sterg si comentariile lipite imediat deasupra lui "ROA =" (fara
# rand gol intre): sunt antetul blocului nostru si, altfel, s-ar
# acumula cate o copie la fiecare rulare. Un rand gol opreste
# potrivirea, deci antetul fisierului ramane intact.
$continutTns = [regex]::Replace((Get-Content $homeTnsNames -Raw),
'(?ms)(^[ \t]*#[^\r\n]*\r?\n)*^[ \t]*ROA[ \t]*=.*?(?=^[ \t]*[A-Za-z0-9_\.]+[ \t]*=|\z)', '')
$continutTns = $continutTns.TrimEnd() + "`r`n`r`n" + $roaAliasBlock
} else {
$continutTns = "# tnsnames.ora - generat de 01-setup-database.ps1`r`n`r`n" + $roaAliasBlock
}
Set-Content -Path $homeTnsNames -Value $continutTns -Encoding ASCII
Write-LogSuccess "tnsnames.ora (Oracle Home): alias ROA -> ${gazdaTns}:$Port/$ServiceName"
# Daca exista TNS_ADMIN la nivel de masina, ACELA castiga - si pentru
# clienti, si pentru procesele bazei, care mostenesc variabilele de
# masina la pornirea serviciului. Instalarea ROAClient il pune sa arate
@@ -404,12 +467,8 @@ NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
# instantclient-ului, aliasul nu se mai rezolva, instanta
# nu se inregistreaza la listener si TOTI clientii iau
# ORA-12514 - cu baza sus si listenerul pornit.
$gazdaTns = Get-ServerLanIPv4
if (-not $gazdaTns) {
$gazdaTns = $env:COMPUTERNAME
Write-LogWarning "Nu am putut determina IP-ul din LAN; folosesc numele masinii ($gazdaTns) in tnsnames.ora."
}
# $gazdaTns e calculat mai sus, o singura data, ca aliasul ROA
# sa fie identic in ambele fisiere.
$tnsNames = Join-Path $tnsAdminFull "tnsnames.ora"
if (Test-Path $tnsNames) {
$aliasuriVechi = @([regex]::Matches((Get-Content $tnsNames -Raw),