Add ROA Oracle Database Windows setup scripts with old client support
PowerShell scripts for setting up Oracle 21c/XE with ROA application: - Automated tablespace, user creation and imports - sqlnet.ora config for Instant Client 11g/ODBC compatibility - Oracle 21c read-only Home path handling (homes/OraDB21Home1) - Listener restart + 10G password verifier for legacy auth - Tested on VM 302 with CONTAFIN_ORACLE schema import Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,424 @@
|
||||
#Requires -Version 5.1
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Batch import company schemas from Data Pump dump files.
|
||||
|
||||
.DESCRIPTION
|
||||
Imports company schemas from dump files. CRITICAL: Reads passwords from
|
||||
CONTAFIN_ORACLE.NOM_FIRME table to ensure correct authentication.
|
||||
|
||||
For each company:
|
||||
1. Queries NOM_FIRME for schema name and password
|
||||
2. Finds matching DMP file in DumpDirectory
|
||||
3. Creates user with password from NOM_FIRME
|
||||
4. Runs impdp to import schema
|
||||
5. Logs progress
|
||||
|
||||
.PARAMETER DumpDirectory
|
||||
Directory containing company DMP files. Required.
|
||||
|
||||
.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 ParallelJobs
|
||||
Number of parallel import jobs. Default: 2
|
||||
|
||||
.PARAMETER Companies
|
||||
Optional array of specific company names to import. If not specified, imports all.
|
||||
|
||||
.PARAMETER DryRun
|
||||
Show what would be imported without actually importing.
|
||||
|
||||
.EXAMPLE
|
||||
.\05-import-companies.ps1 -DumpDirectory "C:\dumps\companies"
|
||||
|
||||
.EXAMPLE
|
||||
.\05-import-companies.ps1 -DumpDirectory "D:\backups" -Companies "FIRMA1","FIRMA2"
|
||||
|
||||
.EXAMPLE
|
||||
.\05-import-companies.ps1 -DumpDirectory "C:\dumps" -DryRun
|
||||
|
||||
.NOTES
|
||||
File Name : 05-import-companies.ps1
|
||||
Prerequisite : Run 04-create-synonyms-grants.ps1 first
|
||||
Copyright 2024 : ROMFAST
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript({ Test-Path $_ -PathType Container })]
|
||||
[string]$DumpDirectory,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$OracleHome,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ServiceName = "XEPDB1",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$SystemPassword = "romfastsoft",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[int]$ParallelJobs = 2,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string[]]$Companies,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Source library functions
|
||||
. "$PSScriptRoot\lib\logging-functions.ps1"
|
||||
. "$PSScriptRoot\lib\oracle-functions.ps1"
|
||||
|
||||
# Initialize logging
|
||||
$logPath = Join-Path $PSScriptRoot "..\logs\05-import-companies_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
||||
Initialize-LogFile -LogPath $logPath -ScriptName "05-import-companies.ps1"
|
||||
|
||||
try {
|
||||
Write-LogSection "Batch Import Company Schemas"
|
||||
|
||||
if ($DryRun) {
|
||||
Write-LogWarning "DRY RUN MODE - No changes will be made"
|
||||
}
|
||||
|
||||
# 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"
|
||||
|
||||
# Get company list from NOM_FIRME
|
||||
Write-LogSection "Reading Company List from NOM_FIRME"
|
||||
|
||||
$companySql = @"
|
||||
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;
|
||||
"@
|
||||
|
||||
$companyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $companySql -Silent
|
||||
|
||||
# Parse company data
|
||||
$companyData = @{}
|
||||
foreach ($line in $companyResult -split "`n") {
|
||||
$line = $line.Trim()
|
||||
if ($line -match "^([A-Z0-9_]+)\|(.*)$") {
|
||||
$schema = $Matches[1]
|
||||
$password = $Matches[2]
|
||||
if (-not $password) { $password = "ROMFASTSOFT" }
|
||||
$companyData[$schema] = $password
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Found $($companyData.Count) companies in NOM_FIRME"
|
||||
|
||||
if ($companyData.Count -eq 0) {
|
||||
Write-LogWarning "No companies found in NOM_FIRME"
|
||||
Close-LogFile -Success $true
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Filter companies if specified
|
||||
if ($Companies) {
|
||||
$filteredData = @{}
|
||||
foreach ($company in $Companies) {
|
||||
$companyUpper = $company.ToUpper()
|
||||
if ($companyData.ContainsKey($companyUpper)) {
|
||||
$filteredData[$companyUpper] = $companyData[$companyUpper]
|
||||
}
|
||||
else {
|
||||
Write-LogWarning "Company $companyUpper not found in NOM_FIRME"
|
||||
}
|
||||
}
|
||||
$companyData = $filteredData
|
||||
Write-Log "Filtered to $($companyData.Count) companies"
|
||||
}
|
||||
|
||||
# Find matching dump files
|
||||
Write-LogSection "Scanning Dump Files"
|
||||
|
||||
$dumpFiles = Get-ChildItem -Path $DumpDirectory -Filter "*.dmp" -File
|
||||
Write-Log "Found $($dumpFiles.Count) DMP files in $DumpDirectory"
|
||||
|
||||
# Match companies with dump files
|
||||
$importList = @()
|
||||
$notFoundList = @()
|
||||
|
||||
foreach ($schema in $companyData.Keys) {
|
||||
# Try to find matching dump file (case-insensitive)
|
||||
$matchingFile = $dumpFiles | Where-Object {
|
||||
$_.BaseName -ieq $schema -or
|
||||
$_.BaseName -imatch "^$schema[_\.]" -or
|
||||
$_.BaseName -imatch "^${schema}$"
|
||||
} | Select-Object -First 1
|
||||
|
||||
if ($matchingFile) {
|
||||
$importList += [PSCustomObject]@{
|
||||
Schema = $schema
|
||||
Password = $companyData[$schema]
|
||||
DumpFile = $matchingFile.FullName
|
||||
DumpSize = [math]::Round($matchingFile.Length / 1MB, 2)
|
||||
}
|
||||
}
|
||||
else {
|
||||
$notFoundList += $schema
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Companies to import: $($importList.Count)"
|
||||
if ($notFoundList.Count -gt 0) {
|
||||
Write-LogWarning "Companies without matching dump file: $($notFoundList.Count)"
|
||||
foreach ($schema in $notFoundList) {
|
||||
Write-Log " - $schema (no DMP file found)"
|
||||
}
|
||||
}
|
||||
|
||||
if ($importList.Count -eq 0) {
|
||||
Write-LogWarning "No companies to import"
|
||||
Close-LogFile -Success $true
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Display import plan
|
||||
Write-LogSection "Import Plan"
|
||||
|
||||
$totalSize = ($importList | Measure-Object -Property DumpSize -Sum).Sum
|
||||
Write-Log "Total data to import: $totalSize MB"
|
||||
Write-Log ""
|
||||
Write-Log "Companies to import:"
|
||||
foreach ($item in $importList) {
|
||||
Write-Log " - $($item.Schema): $($item.DumpFile) ($($item.DumpSize) MB)"
|
||||
}
|
||||
|
||||
if ($DryRun) {
|
||||
Write-LogSection "Dry Run Complete"
|
||||
Write-Log "Would import $($importList.Count) company schemas"
|
||||
Close-LogFile -Success $true
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Ensure DMPDIR exists
|
||||
$dmpDir = "C:\DMPDIR"
|
||||
if (-not (Test-Path -Path $dmpDir)) {
|
||||
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Process each company
|
||||
Write-LogSection "Importing Companies"
|
||||
|
||||
$successCount = 0
|
||||
$failCount = 0
|
||||
$startTime = Get-Date
|
||||
|
||||
foreach ($item in $importList) {
|
||||
Write-LogSection "Importing $($item.Schema)"
|
||||
|
||||
try {
|
||||
# Check if user already exists
|
||||
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Password $SystemPassword -SchemaName $item.Schema
|
||||
|
||||
if ($userExists) {
|
||||
Write-Log "User $($item.Schema) already exists"
|
||||
|
||||
# Get current object count
|
||||
$beforeCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Password $SystemPassword -SchemaName $item.Schema
|
||||
|
||||
$beforeTotal = if ($beforeCounts['TOTAL']) { $beforeCounts['TOTAL'] } else { 0 }
|
||||
Write-Log "Existing objects: $beforeTotal"
|
||||
}
|
||||
else {
|
||||
# Create user
|
||||
Write-Log "Creating user $($item.Schema)..."
|
||||
|
||||
$createUserSql = @"
|
||||
SET ECHO OFF FEEDBACK ON VERIFY OFF
|
||||
|
||||
CREATE USER $($item.Schema)
|
||||
IDENTIFIED BY "$($item.Password)"
|
||||
DEFAULT TABLESPACE ROA
|
||||
TEMPORARY TABLESPACE TEMP
|
||||
PROFILE DEFAULT;
|
||||
|
||||
GRANT CONNECT TO $($item.Schema);
|
||||
GRANT RESOURCE TO $($item.Schema);
|
||||
GRANT CREATE MATERIALIZED VIEW TO $($item.Schema);
|
||||
GRANT CREATE PROCEDURE TO $($item.Schema);
|
||||
GRANT CREATE SEQUENCE TO $($item.Schema);
|
||||
GRANT CREATE TABLE TO $($item.Schema);
|
||||
GRANT CREATE TRIGGER TO $($item.Schema);
|
||||
GRANT CREATE VIEW TO $($item.Schema);
|
||||
GRANT DEBUG CONNECT SESSION TO $($item.Schema);
|
||||
GRANT SELECT ANY TABLE TO $($item.Schema);
|
||||
GRANT CREATE TYPE TO $($item.Schema);
|
||||
GRANT UNLIMITED TABLESPACE TO $($item.Schema);
|
||||
|
||||
COMMIT;
|
||||
SELECT 'USER_CREATED' FROM dual;
|
||||
EXIT;
|
||||
"@
|
||||
|
||||
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql -Silent
|
||||
|
||||
if ($createResult -match "USER_CREATED") {
|
||||
Write-LogSuccess "User $($item.Schema) created"
|
||||
}
|
||||
else {
|
||||
throw "Failed to create user $($item.Schema)"
|
||||
}
|
||||
}
|
||||
|
||||
# Copy dump file to DMPDIR if not already there
|
||||
$dumpFileName = Split-Path -Path $item.DumpFile -Leaf
|
||||
$targetDumpPath = Join-Path $dmpDir $dumpFileName
|
||||
|
||||
if ($item.DumpFile -ne $targetDumpPath) {
|
||||
Write-Log "Copying dump file to DMPDIR..."
|
||||
Copy-Item -Path $item.DumpFile -Destination $targetDumpPath -Force
|
||||
}
|
||||
|
||||
# Run import
|
||||
Write-Log "Running impdp for $($item.Schema)..."
|
||||
|
||||
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
|
||||
$importLogFile = "$($item.Schema)_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
||||
|
||||
$connString = "SYSTEM/`"$SystemPassword`"@$ServiceName"
|
||||
|
||||
# Check if dump has different schema name (remapping needed)
|
||||
$remapParam = ""
|
||||
$dumpBaseName = [System.IO.Path]::GetFileNameWithoutExtension($dumpFileName).ToUpper()
|
||||
if ($dumpBaseName -ne $item.Schema) {
|
||||
$remapParam = "remap_schema=$dumpBaseName`:$($item.Schema)"
|
||||
Write-Log "Schema remap: $dumpBaseName -> $($item.Schema)"
|
||||
}
|
||||
|
||||
$impdpParams = @(
|
||||
"`"$connString`"",
|
||||
"directory=DMPDIR",
|
||||
"dumpfile=$dumpFileName",
|
||||
"logfile=$importLogFile",
|
||||
"schemas=$($item.Schema)",
|
||||
"table_exists_action=REPLACE"
|
||||
)
|
||||
|
||||
if ($remapParam) {
|
||||
$impdpParams += $remapParam
|
||||
}
|
||||
|
||||
$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"
|
||||
|
||||
# Verify import
|
||||
$afterCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Password $SystemPassword -SchemaName $item.Schema
|
||||
|
||||
$afterTotal = if ($afterCounts['TOTAL']) { $afterCounts['TOTAL'] } else { 0 }
|
||||
$afterInvalid = if ($afterCounts['INVALID']) { $afterCounts['INVALID'] } else { 0 }
|
||||
|
||||
Write-Log "Objects after import: $afterTotal"
|
||||
|
||||
if ($afterInvalid -gt 0) {
|
||||
Write-LogWarning "Invalid objects: $afterInvalid"
|
||||
|
||||
# Recompile
|
||||
$recompileSql = @"
|
||||
BEGIN
|
||||
DBMS_UTILITY.COMPILE_SCHEMA('$($item.Schema)', FALSE);
|
||||
END;
|
||||
/
|
||||
EXIT;
|
||||
"@
|
||||
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
||||
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
|
||||
}
|
||||
|
||||
if ($process.ExitCode -eq 0) {
|
||||
Write-LogSuccess "$($item.Schema) imported successfully ($afterTotal objects)"
|
||||
$successCount++
|
||||
}
|
||||
else {
|
||||
Write-LogWarning "$($item.Schema) import completed with warnings"
|
||||
$successCount++
|
||||
}
|
||||
|
||||
# Clean up copied dump file
|
||||
if ($item.DumpFile -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
|
||||
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-LogError "Failed to import $($item.Schema): $_"
|
||||
$failCount++
|
||||
}
|
||||
}
|
||||
|
||||
$totalDuration = (Get-Date) - $startTime
|
||||
|
||||
# Summary
|
||||
Write-LogSection "Import Complete"
|
||||
|
||||
Write-LogSuccess "Company import batch completed!"
|
||||
Write-Log ""
|
||||
Write-Log "Summary:"
|
||||
Write-Log " Total companies: $($importList.Count)"
|
||||
Write-Log " Successful: $successCount"
|
||||
Write-Log " Failed: $failCount"
|
||||
Write-Log " Total duration: $([math]::Round($totalDuration.TotalMinutes, 2)) minutes"
|
||||
Write-Log ""
|
||||
|
||||
if ($notFoundList.Count -gt 0) {
|
||||
Write-Log "Companies skipped (no dump file):"
|
||||
foreach ($schema in $notFoundList) {
|
||||
Write-Log " - $schema"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log ""
|
||||
Write-Log "Next steps:"
|
||||
Write-Log " 1. Run 07-verify-installation.ps1 to verify all schemas"
|
||||
|
||||
Close-LogFile -Success ($failCount -eq 0)
|
||||
exit $(if ($failCount -eq 0) { 0 } else { 1 })
|
||||
}
|
||||
catch {
|
||||
Write-LogError "Import failed: $_"
|
||||
Write-LogError $_.ScriptStackTrace
|
||||
Close-LogFile -Success $false
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user