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>
328 lines
10 KiB
PowerShell
328 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
|
|
)
|
|
|
|
$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 = "C:\DMPDIR"
|
|
if (-not (Test-Path -Path $dmpDir)) {
|
|
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
|
|
}
|
|
|
|
New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $dmpDir
|
|
|
|
# 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
|
|
}
|