Files
ROMFASTSQL/proxmox/lxc108-oracle/roa-windows-setup/scripts/06-add-company.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

334 lines
10 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Add a new company schema to ROA Oracle.
.DESCRIPTION
Creates a new company user/schema with either:
- Import from a template DMP file
- Empty schema with basic structures
.PARAMETER CompanyName
Schema name for the new company. Required. Must be uppercase alphanumeric.
.PARAMETER Password
Password for the new company schema. Default: ROMFASTSOFT
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER TemplateDump
Optional path to a template DMP file to import.
.PARAMETER TemplateSchema
Schema name in the template DMP file if different from target (for remap).
.PARAMETER Force
Drop and recreate if user already exists.
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWCOMPANY"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "FIRMA2024" -Password "SecurePass123"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWFIRMA" -TemplateDump "C:\dumps\FIRMANOUA.dmp" -TemplateSchema "FIRMANOUA"
.NOTES
File Name : 06-add-company.ps1
Prerequisite : Run 04-create-synonyms-grants.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^[A-Z0-9_]+$')]
[string]$CompanyName,
[Parameter(Mandatory = $false)]
[string]$Password = "ROMFASTSOFT",
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[ValidateScript({ Test-Path $_ })]
[string]$TemplateDump,
[Parameter(Mandatory = $false)]
[string]$TemplateSchema,
[Parameter(Mandatory = $false)]
[switch]$Force,
# Calea fizica a directorului Oracle DMPDIR, asa cum a fost pusa la instalare.
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR"
)
$ErrorActionPreference = 'Stop'
# Ensure company name is uppercase
$CompanyName = $CompanyName.ToUpper()
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\06-add-company_${CompanyName}_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "06-add-company.ps1"
try {
Write-LogSection "Adding New Company: $CompanyName"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Check if user already exists
Write-Log "Checking if user $CompanyName exists..."
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
if ($userExists) {
if ($Force) {
Write-LogWarning "User $CompanyName exists. Dropping due to -Force flag..."
$dropSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
DROP USER $CompanyName CASCADE;
SELECT 'USER_DROPPED' FROM dual;
EXIT;
"@
$dropResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $dropSql
if ($dropResult -match "USER_DROPPED") {
Write-Log "User $CompanyName dropped"
}
else {
throw "Failed to drop user $CompanyName"
}
}
else {
throw "User $CompanyName already exists. Use -Force to drop and recreate."
}
}
# Create user
Write-LogSection "Creating User $CompanyName"
$createUserSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
PROMPT Creating user $CompanyName...
CREATE USER $CompanyName
IDENTIFIED BY "$Password"
DEFAULT TABLESPACE ROA
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT;
PROMPT Granting role privileges...
GRANT CONNECT TO $CompanyName;
GRANT RESOURCE TO $CompanyName;
PROMPT Granting system privileges...
GRANT CREATE MATERIALIZED VIEW TO $CompanyName;
GRANT CREATE PROCEDURE TO $CompanyName;
GRANT CREATE SEQUENCE TO $CompanyName;
GRANT CREATE TABLE TO $CompanyName;
GRANT CREATE TRIGGER TO $CompanyName;
GRANT CREATE VIEW TO $CompanyName;
GRANT DEBUG CONNECT SESSION TO $CompanyName;
GRANT SELECT ANY TABLE TO $CompanyName;
GRANT CREATE TYPE TO $CompanyName;
GRANT UNLIMITED TABLESPACE TO $CompanyName;
COMMIT;
SELECT 'USER_CREATED' FROM dual;
EXIT;
"@
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql
if ($createResult -match "USER_CREATED") {
Write-LogSuccess "User $CompanyName created successfully"
}
else {
Write-LogError "Failed to create user"
Write-LogDebug $createResult
throw "User creation failed"
}
# Import from template if specified
if ($TemplateDump) {
Write-LogSection "Importing from Template"
Write-Log "Template dump: $TemplateDump"
# Determine template schema for remapping
if (-not $TemplateSchema) {
$TemplateSchema = [System.IO.Path]::GetFileNameWithoutExtension($TemplateDump).ToUpper()
Write-Log "Assuming template schema: $TemplateSchema"
}
# Setup DMPDIR
$dmpDir = $DmpDir
if (-not (Test-Path -Path $dmpDir)) {
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
}
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."
}
# Copy dump to DMPDIR
$dumpFileName = Split-Path -Path $TemplateDump -Leaf
$targetDumpPath = Join-Path $dmpDir $dumpFileName
if ($TemplateDump -ne $targetDumpPath) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $TemplateDump -Destination $targetDumpPath -Force
}
# Run import with remap
Write-Log "Running impdp..."
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
$importLogFile = "${CompanyName}_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$connString = "SYSTEM/`"$SystemPassword`"@$ServiceName"
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"remap_schema=$TemplateSchema`:$CompanyName",
"table_exists_action=REPLACE"
)
$arguments = $impdpParams -join " "
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$importStart = Get-Date
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$importDuration = (Get-Date) - $importStart
Write-Log "Import completed in $([math]::Round($importDuration.TotalMinutes, 2)) minutes"
if ($process.ExitCode -eq 0) {
Write-LogSuccess "Template imported successfully"
}
else {
Write-LogWarning "Import completed with warnings (exit code: $($process.ExitCode))"
}
# Clean up copied dump file
if ($TemplateDump -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
}
}
# Get final object count
Write-LogSection "Verifying Schema"
$counts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$totalObjects = if ($counts['TOTAL']) { $counts['TOTAL'] } else { 0 }
$invalidObjects = if ($counts['INVALID']) { $counts['INVALID'] } else { 0 }
Write-Log "Total objects: $totalObjects"
if ($invalidObjects -gt 0) {
Write-LogWarning "Invalid objects: $invalidObjects"
# Recompile
Write-Log "Recompiling invalid objects..."
$recompileSql = @"
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('$CompanyName', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
# Recheck
$recheckCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$recheckInvalid = if ($recheckCounts['INVALID']) { $recheckCounts['INVALID'] } else { 0 }
if ($recheckInvalid -lt $invalidObjects) {
Write-LogSuccess "Recompilation fixed $($invalidObjects - $recheckInvalid) objects"
}
}
# Test connection with new user
Write-Log "Testing connection as $CompanyName..."
if (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Username $CompanyName -Password $Password) {
Write-LogSuccess "Connection test successful"
}
else {
Write-LogWarning "Could not connect as $CompanyName"
}
# Summary
Write-LogSection "Company Added"
Write-LogSuccess "Company $CompanyName added successfully!"
Write-Log ""
Write-Log "Summary:"
Write-Log " Schema name: $CompanyName"
Write-Log " Service: $ServiceName"
Write-Log " Objects: $totalObjects"
if ($TemplateDump) {
Write-Log " Template: $TemplateDump"
}
Write-Log ""
Write-Log "Connection string:"
Write-Log " $CompanyName/$Password@$ServiceName"
Close-LogFile -Success $true
exit 0
}
catch {
Write-LogError "Failed to add company: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}