feat(oracle): instalare ROA in doua faze, licente, IIS si export zilnic

Adauga FAZA1.cmd/FAZA2.cmd, care despart migrarea in partea care se poate
face in timpul programului (contafin, obiecte SYS, sinonime, licente, IIS)
si partea de seara (schemele de firma). Scripturi noi: 09 pentru licentele
din SYS.AUTH_SERII/AUTH_DETALII, 10 pentru publicarea D:\ROAUPDATE in IIS,
11 pentru exportul zilnic cu backupora.exe, drop-contafin pentru reimport.

backupora.exe si sabloanele sale intra in repo ca sa fie kitul autonom.
Pasul 07 primeste verificarile corespunzatoare pentru licente, IIS si task.

Nerulat inca pe o baza reala - vezi docs/handoff_instalare-doua-faze.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
This commit is contained in:
Marius
2026-08-25 20:57:23 +03:00
parent 7fce925349
commit 5a746990ce
18 changed files with 3446 additions and 854 deletions

View File

@@ -0,0 +1,528 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Pregateste exportul zilnic al bazei: D:\ROA\EXPORT_ORADMP cu backupora.exe,
setari.ini, schema.txt si task-ul zilnic din Windows Task Scheduler.
.DESCRIPTION
Ce face, in ordine:
1. Creeaza D:\ROA\EXPORT_ORADMP (+ subdirectorul LOG).
2. Copiaza backupora.exe si config.fpw din kit (backup\).
3. Genereaza setari.ini din backup\setari.ini.template, inlocuind
marcajele {{...}} cu valorile reale ale instalarii.
4. Genereaza schema.txt cu schemele de exportat, in formatul cerut de
backupora.exe: SCHEMA;PAROLA@SERVICIU, cate una pe linie.
CONTAFIN_ORACLE + firmele active din CONTAFIN_ORACLE.NOM_FIRME
(parolele se citesc din NOM_FIRME.parola).
Alternativ, il copiaza de pe serverul vechi (-SchemaFromPath).
5. Creeaza obiectul Oracle DIRECTORY BACKUP_ORACLE catre acelasi
director, ca Data Pump sa poata scrie acolo, si da drepturi
serviciului Oracle pe folder.
6. Inregistreaza un task zilnic in Windows Task Scheduler.
Formatul lui setari.ini NU e cimentat in cod: sablonul e un fisier de
date, iar scriptul doar substituie marcajele.
ATENTIE la doua capcane ale lui backupora.exe, verificate in sursa lui
(main.prg):
- programul SCRIE in ini-ul implicit cheia "delete_backups_olther_xdays"
(cu typo) dar CITESTE "delete_backups_older_xdays". Sablonul o are pe
cea corecta. Nu o "corecta" inapoi.
- alege intre exportul clasic si Data Pump dupa NUMELE executabilului din
oracleexpfile. Ca sa foloseasca expdp, fisierul trebuie sa se cheme
"expdp.exe"; de aceea aratam catre <OracleHome>\bin\expdp.exe.
Dump-urile ajung in <BackupPath>\<AAAALLZZ>\ - backupora.exe creeaza singur
subdirectorul pe zi.
.PARAMETER ExportPath
Directorul in care sta backupora.exe. Implicit D:\ROA\EXPORT_ORADMP.
.PARAMETER BackupPath
Unde ajung dump-urile. Implicit acelasi cu ExportPath, deci
D:\ROA\EXPORT_ORADMP\<AAAALLZZ>\. Pe instalarile mai vechi de la clienti
valoarea uzuala e C:\BACKUP_ORACLE - daca vrei sa pastrezi conventia aia,
da-o explicit.
.PARAMETER ContafinPassword
Parola CONTAFIN_ORACLE, pentru linia lui din schema.txt.
Implicit ROMFASTSOFT.
.PARAMETER OracleHome
Oracle home. Autodetectat daca lipseste.
.PARAMETER ServiceName
Serviciul bazei. Implicit XEPDB1.
.PARAMETER SystemPassword
Parola SYSTEM/SYS. Implicit romfastsoft.
.PARAMETER SchemaFromPath
Cale (locala sau UNC) catre un schema.txt existent, de regula de pe
serverul vechi: \\server-vechi\d$\ROA\EXPORT_ORADMP\schema.txt
Daca e dat si fisierul e citibil, se copiaza in loc sa se genereze.
.PARAMETER RetentionDays
Cate zile se pastreaza dump-urile. Ajunge in setari.ini. Implicit 7.
.PARAMETER TaskTime
Ora rularii zilnice, format HH:mm. Implicit 22:30.
.PARAMETER TaskName
Numele task-ului din Task Scheduler. Implicit "ROA Export Oracle".
.PARAMETER TaskUser
Contul sub care ruleaza task-ul. Implicit SYSTEM.
.PARAMETER SkipTask
Nu crea task-ul zilnic; doar directorul, fisierele si obiectul DIRECTORY.
.PARAMETER SkipSchema
Nu genera si nu copia schema.txt (il completezi manual dupa).
.PARAMETER SchemaOnly
Regenereaza doar schema.txt si iese. Nu atinge setari.ini, backupora.exe
sau task-ul. Asa se reia pasul dupa faza 2, cand firmele exista in
NOM_FIRME, fara sa pierzi corecturile facute manual in setari.ini.
.EXAMPLE
.\11-setup-backup-export.ps1
Varianta obisnuita, cu schema.txt generat din NOM_FIRME.
.EXAMPLE
.\11-setup-backup-export.ps1 -SchemaFromPath "\\10.0.0.5\d$\ROA\EXPORT_ORADMP\schema.txt"
Preia schema.txt de pe serverul vechi, exact cum era acolo.
.EXAMPLE
.\11-setup-backup-export.ps1 -TaskTime "23:00" -RetentionDays 14
Alta ora si alta retentie.
.NOTES
File Name : 11-setup-backup-export.ps1
Prerequisite : drepturi de administrator; backup\backupora.exe prezent in kit
Copyright 2026 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$ExportPath = "D:\ROA\EXPORT_ORADMP",
[Parameter(Mandatory = $false)]
[string]$BackupPath,
[Parameter(Mandatory = $false)]
[string]$ContafinPassword = "ROMFASTSOFT",
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[string]$SchemaFromPath,
[Parameter(Mandatory = $false)]
[int]$RetentionDays = 7,
[Parameter(Mandatory = $false)]
[ValidatePattern('^\d{1,2}:\d{2}$')]
[string]$TaskTime = "22:30",
[Parameter(Mandatory = $false)]
[string]$TaskName = "ROA Export Oracle",
[Parameter(Mandatory = $false)]
[string]$TaskUser = "SYSTEM",
[Parameter(Mandatory = $false)]
[switch]$SkipTask,
[Parameter(Mandatory = $false)]
[switch]$SkipSchema,
[Parameter(Mandatory = $false)]
[switch]$SchemaOnly
)
$ErrorActionPreference = "Stop"
. (Join-Path $PSScriptRoot "lib\logging-functions.ps1")
. (Join-Path $PSScriptRoot "lib\oracle-functions.ps1")
$configFile = Join-Path $PSScriptRoot "..\config.ps1"
if (Test-Path $configFile) {
. $configFile
if (-not $PSBoundParameters.ContainsKey('OracleHome') -and $Config.OracleHome) { $OracleHome = $Config.OracleHome }
if (-not $PSBoundParameters.ContainsKey('ServiceName') -and $Config.ServiceName) { $ServiceName = $Config.ServiceName }
if (-not $PSBoundParameters.ContainsKey('SystemPassword') -and $Config.SystemPassword) { $SystemPassword = $Config.SystemPassword }
}
$stamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$logDir = Join-Path $PSScriptRoot "..\logs"
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
Initialize-LogFile -LogPath (Join-Path $logDir "11-setup-backup-export_$stamp.log") -ScriptName "11-setup-backup-export.ps1"
$kitBackupDir = Join-Path $PSScriptRoot "..\backup"
function Test-Administrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
<#
Scrie schema.txt: lista schemelor pe care le exporta backupora.exe.
Fie copiaza fisierul de pe serverul vechi, fie il genereaza din
CONTAFIN_ORACLE.NOM_FIRME. Se apeleaza si din fluxul complet, si din
-SchemaOnly (reluarea de dupa faza 2, cand firmele exista).
#>
function New-SchemaFile {
param(
[string]$SchemaFile,
[string]$SourcePath,
[string]$OraHome,
[string]$Service,
[string]$Password,
[string]$ContafinPwd
)
Write-LogSection "schema.txt"
if ($SourcePath) {
if (Test-Path $SourcePath) {
Copy-Item -Path $SourcePath -Destination $SchemaFile -Force
$n = @(Get-Content $SchemaFile | Where-Object { $_.Trim() -ne '' }).Count
Write-LogSuccess "Copiat de pe serverul vechi: $n linii"
Write-LogWarning "Verifica-l: parolele si numele serviciului din el sunt cele de pe"
Write-LogWarning "serverul VECHI. Daca difera, corecteaza-le sau regenereaza cu -SchemaOnly."
return
}
Write-LogWarning "Nu pot citi $SourcePath. Generez schema.txt din NOM_FIRME."
}
Write-Log "Citesc schemele si parolele din CONTAFIN_ORACLE.NOM_FIRME..."
# Formatul cerut de backupora.exe (vezi schema.tmpl):
# SCHEMA;PAROLA@SERVICIU
# Delimitatorul e ';', nu '|' - alegem alt separator la SELECT ca sa nu se
# confunde daca o parola ar contine ';'.
$sql = @"
SET PAGESIZE 10000 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500
SELECT schema || '~' || parola
FROM CONTAFIN_ORACLE.NOM_FIRME
WHERE sters = 0
AND schema IS NOT NULL
ORDER BY schema;
EXIT
"@
$rez = Invoke-SqlPlus -OracleHome $OraHome -ServiceName $Service `
-Username "SYSTEM" -Password $Password -SqlCommand $sql -Silent
$firme = @()
foreach ($linie in ($rez -split "`n")) {
$linie = $linie.Trim()
if ($linie -match '^([A-Z0-9_]+)~(.*)$') {
$schema = $Matches[1]
$parola = $Matches[2].Trim()
if (-not $parola) { $parola = "ROMFASTSOFT" }
$firme += "$schema;$parola@$Service"
}
}
# CONTAFIN_ORACLE nu e in NOM_FIRME, dar trebuie exportat primul: fara el,
# dump-urile de firma nu se pot reimporta (NOM_FIRME tine parolele si
# maparea firma -> schema).
$linii = @("CONTAFIN_ORACLE;$ContafinPwd@$Service") + ($firme | Sort-Object -Unique)
Set-Content -Path $SchemaFile -Value ($linii -join "`r`n") -Encoding ASCII
Write-LogSuccess "Generat: $SchemaFile (CONTAFIN_ORACLE + $($firme.Count) firme)"
Write-LogWarning "Fisierul contine parole in clar - asa il cere backupora.exe."
Write-LogWarning "Nu il copia in afara serverului si nu il pune in kit."
if ($firme.Count -eq 0) {
Write-LogWarning "NOM_FIRME nu are nicio firma activa."
Write-LogWarning "In faza 1 e normal - reia cu -SchemaOnly dupa faza 2."
}
}
try {
Write-LogSection "Export zilnic Oracle (EXPORT_ORADMP)"
# -SchemaOnly nu scrie in Task Scheduler, deci nu cere administrator.
if (-not $SchemaOnly -and -not (Test-Administrator)) {
throw "Scriptul are nevoie de drepturi de administrator (creeaza un task in Task Scheduler)."
}
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
if (-not $BackupPath) { $BackupPath = $ExportPath }
Write-Log "Director program: $ExportPath"
Write-Log "Dump-uri in: $BackupPath\<AAAALLZZ>\"
# ------------------------------------------------------------------
# Reluare doar pentru schema.txt (dupa faza 2, cand firmele exista).
# Nu atinge setari.ini, backupora.exe sau task-ul.
# ------------------------------------------------------------------
if ($SchemaOnly) {
if (-not (Test-Path $ExportPath)) {
throw "$ExportPath nu exista. Ruleaza intai scriptul fara -SchemaOnly."
}
New-SchemaFile -SchemaFile (Join-Path $ExportPath "schema.txt") -SourcePath $SchemaFromPath `
-OraHome $oraHome -Service $ServiceName -Password $SystemPassword `
-ContafinPwd $ContafinPassword
Write-LogSection "Gata (SchemaOnly)"
Close-LogFile
exit 0
}
# ------------------------------------------------------------------
# 1. Directoare
# ------------------------------------------------------------------
Write-LogSection "Directoare"
$drive = Split-Path -Qualifier $ExportPath
if ($drive -and -not (Test-Path $drive)) {
throw "Discul $drive nu exista. Da alta cale cu -ExportPath."
}
$logSubDir = Join-Path $ExportPath "LOG"
foreach ($d in @($ExportPath, $logSubDir, $BackupPath)) {
if (-not (Test-Path $d)) {
New-Item -ItemType Directory -Path $d -Force | Out-Null
Write-LogSuccess "Creat: $d"
} else {
Write-Log "Exista: $d"
}
}
# Data Pump scrie cu contul serviciului Oracle, nu cu al tau. Fara
# dreptul asta, expdp da ORA-39002 la deschiderea fisierului.
$oracleServices = @(Get-Service -Name "Oracle*XE*" -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "OracleService*" })
foreach ($svc in $oracleServices) {
$cont = "NT SERVICE\$($svc.Name)"
foreach ($tinta in (@($ExportPath, $BackupPath) | Select-Object -Unique)) {
$null = & icacls.exe $tinta /grant "${cont}:(OI)(CI)F" /T /Q 2>&1
if ($LASTEXITCODE -eq 0) {
Write-LogSuccess "Drepturi depline pentru $cont pe $tinta"
} else {
Write-LogWarning "icacls pentru $cont pe $tinta a returnat codul $LASTEXITCODE"
}
}
}
if ($oracleServices.Count -eq 0) {
Write-LogWarning "Nu am gasit niciun serviciu OracleService*. Verifica manual drepturile pe $ExportPath."
}
# ------------------------------------------------------------------
# 2. backupora.exe + config.fpw
# ------------------------------------------------------------------
# config.fpw e configul runtime VFP (SCREEN=OFF, RESOURCE=OFF). Fara el,
# backupora.exe ar deschide o fereastra si ar astepta - inacceptabil
# pentru un task programat care ruleaza fara sesiune interactiva.
Write-LogSection "backupora.exe"
$tintaExe = Join-Path $ExportPath "backupora.exe"
foreach ($fis in @('backupora.exe', 'config.fpw', 'setari.ini.tmpl', 'schema.tmpl', 'changelog_backupora.txt')) {
$sursa = Join-Path $kitBackupDir $fis
$tinta = Join-Path $ExportPath $fis
if (Test-Path $sursa) {
Copy-Item -Path $sursa -Destination $tinta -Force
$dim = [math]::Round((Get-Item $tinta).Length / 1KB, 1)
Write-LogSuccess "Copiat: $fis ($dim KB)"
}
elseif ($fis -eq 'backupora.exe') {
if (Test-Path $tinta) {
Write-LogWarning "backup\backupora.exe lipseste din kit, dar exista deja $tinta. Il las cum e."
}
else {
Write-LogError "Lipseste backup\backupora.exe din kit SI din $ExportPath."
Write-LogError "Fara el, task-ul zilnic nu are ce rula."
Write-LogError "Pune backupora.exe in kit, in directorul backup\, si reconstruieste kitul."
throw "backupora.exe lipseste."
}
}
else {
Write-LogDebug "backup\$fis lipseste din kit - optional, se continua."
}
}
# ------------------------------------------------------------------
# 3. setari.ini
# ------------------------------------------------------------------
Write-LogSection "setari.ini"
$sablon = Join-Path $kitBackupDir "setari.ini.template"
$tintaIni = Join-Path $ExportPath "setari.ini"
if (-not (Test-Path $sablon)) {
throw "Lipseste backup\setari.ini.template din kit."
}
if (Test-Path $tintaIni) {
$backupIni = Join-Path $ExportPath "setari.ini.bak_$stamp"
Copy-Item -Path $tintaIni -Destination $backupIni -Force
Write-LogWarning "setari.ini exista deja; l-am salvat ca $(Split-Path -Leaf $backupIni) inainte sa il rescriu."
}
# backupora.exe alege exp vs expdp dupa numele executabilului, deci
# aratam direct catre expdp.exe din Oracle home. Stub-ul de 0 octeti din
# directorul programului (asa apare pe instalarile vechi) nu ar exporta nimic.
$expdpExe = Join-Path $oraHome "bin\expdp.exe"
if (-not (Test-Path $expdpExe)) {
Write-LogWarning "Nu gasesc $expdpExe. Verifica manual cheia oracleexpfile din setari.ini."
}
# Calea fizica a directorului Oracle DMPDIR, pentru cheile datapumpdir*.
$dmpDirPath = "C:\DMPDIR"
$dmpDirName = "DMPDIR"
try {
$r = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "sys" -Password $SystemPassword -AsSysdba -Silent -SqlCommand @"
SET PAGESIZE 0 FEEDBACK OFF HEADING OFF VERIFY OFF
SELECT 'DMPDIR=' || directory_path FROM dba_directories WHERE directory_name = 'DMPDIR';
EXIT
"@
if ($r -match 'DMPDIR=(.+)') { $dmpDirPath = $Matches[1].Trim() }
}
catch {
Write-LogDebug "Nu am putut citi DMPDIR: $($_.Exception.Message)"
}
$schemaFile = Join-Path $ExportPath "schema.txt"
$inlocuiri = @{
'{{ORACLE_HOME}}' = $oraHome
'{{DB_SERVICE}}' = $ServiceName
'{{EXPORT_DIR}}' = $ExportPath
'{{BACKUP_PATH}}' = $BackupPath
'{{SCHEMA_FILE}}' = $schemaFile
'{{RETENTION_DAYS}}' = "$RetentionDays"
'{{EXPDP_EXE}}' = $expdpExe
'{{DMPDIR_PATH}}' = $dmpDirPath
'{{DMPDIR_NAME}}' = $dmpDirName
'{{DATA_GENERARII}}' = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
}
$continut = Get-Content -Path $sablon -Raw
foreach ($cheie in $inlocuiri.Keys) {
$continut = $continut.Replace($cheie, $inlocuiri[$cheie])
}
Set-Content -Path $tintaIni -Value $continut -Encoding ASCII
Write-LogSuccess "Generat: $tintaIni"
$ramase = [regex]::Matches($continut, '\{\{[A-Z_]+\}\}')
if ($ramase.Count -gt 0) {
$lista = ($ramase | ForEach-Object { $_.Value } | Select-Object -Unique) -join ", "
Write-LogWarning "Marcaje nesubstituite in setari.ini: $lista"
Write-LogWarning "Completeaza-le manual sau adauga-le in tabelul de inlocuiri din scriptul asta."
}
# ------------------------------------------------------------------
# 4. schema.txt
# ------------------------------------------------------------------
if (-not $SkipSchema) {
New-SchemaFile -SchemaFile $schemaFile -SourcePath $SchemaFromPath `
-OraHome $oraHome -Service $ServiceName -Password $SystemPassword `
-ContafinPwd $ContafinPassword
}
else {
Write-Log "Sar peste schema.txt (-SkipSchema). Completeaza-l manual in $ExportPath."
}
# ------------------------------------------------------------------
# 5. Obiectul Oracle DIRECTORY
# ------------------------------------------------------------------
Write-LogSection "Obiectul DIRECTORY BACKUP_ORACLE"
$dirSql = @"
SET FEEDBACK ON SERVEROUTPUT ON VERIFY OFF
CREATE OR REPLACE DIRECTORY BACKUP_ORACLE AS '$ExportPath';
GRANT READ, WRITE ON DIRECTORY BACKUP_ORACLE TO SYSTEM;
GRANT READ, WRITE ON DIRECTORY BACKUP_ORACLE TO CONTAFIN_ORACLE;
SET PAGESIZE 0 HEADING OFF FEEDBACK OFF
SELECT 'DIRECTORY=' || directory_path FROM dba_directories WHERE directory_name = 'BACKUP_ORACLE';
EXIT
"@
$rezDir = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "sys" -Password $SystemPassword -AsSysdba -SqlCommand $dirSql
if ($rezDir -match "DIRECTORY=(.+)") {
Write-LogSuccess "BACKUP_ORACLE -> $($Matches[1].Trim())"
} else {
Write-LogWarning "Nu am putut confirma obiectul DIRECTORY BACKUP_ORACLE."
Write-LogDebug $rezDir
}
# ------------------------------------------------------------------
# 6. Task zilnic
# ------------------------------------------------------------------
if (-not $SkipTask) {
Write-LogSection "Task zilnic in Windows Task Scheduler"
$existent = $null
try { $existent = Get-ScheduledTask -TaskName $TaskName -ErrorAction Stop } catch { }
if ($existent) {
Write-LogWarning "Task-ul '$TaskName' exista deja; il inlocuiesc."
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
}
$actiune = New-ScheduledTaskAction -Execute $tintaExe -WorkingDirectory $ExportPath
$declansator = New-ScheduledTaskTrigger -Daily -At $TaskTime
$principal = New-ScheduledTaskPrincipal -UserId $TaskUser -LogonType ServiceAccount -RunLevel Highest
$setari = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries `
-StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 6)
Register-ScheduledTask -TaskName $TaskName -Action $actiune -Trigger $declansator `
-Principal $principal -Settings $setari `
-Description "Export zilnic al schemelor ROA in $ExportPath (backupora.exe)" | Out-Null
Write-LogSuccess "Task '$TaskName' creat, zilnic la $TaskTime, sub contul $TaskUser"
Write-Log "Rulare de proba: Start-ScheduledTask -TaskName ""$TaskName"""
Write-Log "Stare: Get-ScheduledTaskInfo -TaskName ""$TaskName"""
}
else {
Write-Log "Sar peste task-ul zilnic (-SkipTask)"
}
# ------------------------------------------------------------------
Write-LogSection "Gata"
Write-Log "Director program: $ExportPath"
Write-Log "Executabil: $tintaExe"
Write-Log "Config: $tintaIni"
if (-not $SkipSchema) { Write-Log "Scheme: $schemaFile" }
Write-Log "Dump-uri in: $BackupPath\<AAAALLZZ>\"
Write-Log "DIRECTORY: BACKUP_ORACLE"
if (-not $SkipTask) { Write-Log "Task zilnic: $TaskName la $TaskTime" }
Write-Log ""
Write-LogWarning "Verifica manual prima rulare inainte sa pleci de la client:"
Write-LogWarning " Start-ScheduledTask -TaskName ""$TaskName"""
Write-LogWarning "apoi uita-te in $logSubDir si vezi ca s-au scris dump-urile."
Close-LogFile
exit 0
}
catch {
Write-LogError $_.Exception.Message
Write-LogDebug $_.ScriptStackTrace
Close-LogFile
exit 1
}