Files
Omika/infra/deploy/Install-OmikaServices.ps1
T
2026-10-23 18:46:50 +02:00

253 lines
9.7 KiB
PowerShell

# ============================================================
# Omika - Installation de TOUS les services Windows (orchestrateur)
# ============================================================
# CIBLE : Windows Server 2025 (SRV-OMIKA), PowerShell ADMINISTRATEUR.
# NE PAS executer depuis le poste de developpement.
#
# Ce script ne fait plus le travail lui-meme : il appelle, DANS L'ORDRE, un
# script dedie par deploiement. Chaque service reste installable seul.
#
# 1. Install-OmikaApi.ps1 (spool JSONL de l'API)
# 2. Install-OmikaWorker.ps1
# 3. Install-OmikaDiagnosticsApi.ps1 (spool central) [optionnel]
# 4. Install-OmikaDiagnosticsWorker.ps1 (lit les 2 spools)
# 5. Install-OmikaDiagnosticsWeb.ps1
# 6. Install-OmikaLanguesApi.ps1 [optionnel]
#
# POURQUOI CET ORDRE : les ACL inter-services (le Worker Diagnostics lit le
# spool produit par l'API et celui produit par l'API centrale) ne peuvent etre
# posees que si le dossier existe deja. L'ancien script monolithique posait les
# ACL en bloc et IGNORAIT SILENCIEUSEMENT les dossiers absents ; ici, le
# proprietaire du dossier est installe AVANT ses lecteurs.
#
# CE QUE CE SCRIPT NE FAIT PAS :
# - AUCUN demarrage de service (doctrine : activation != demarrage).
# - AUCUN secret ecrit, AUCUNE regle firewall, AUCUN IIS, AUCUNE base modifiee.
#
# PREREQUIS MANUELS :
# - Comptes locaux dedies crees + droit « Ouvrir une session en tant que
# service » (chaque script le verifie et avertit).
# - Publications copiees dans <InstallRoot>\Apps (Install-OmikaServerFiles.ps1).
#
# IDEMPOTENT - prend en charge -WhatIf.
#
# EXEMPLES :
# .\Install-OmikaServices.ps1
# .\Install-OmikaServices.ps1 -WhatIf
# .\Install-OmikaServices.ps1 -InclureLangues -PortLangues 5099
# .\Install-OmikaServices.ps1 -SansDiagnosticsApi # serveur mono-serveur
# .\Install-OmikaServices.ps1 -Desinstaller
# ============================================================
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[string]$InstallRoot = 'C:\Omika',
# --- Noms de services ----------------------------------------------------
[string]$ApiServiceName = 'OmikaApi',
[string]$WorkerServiceName = 'OmikaWorker',
[string]$DiagServiceName = 'OmikaDiagnosticsWorker',
[string]$DiagWebServiceName = 'OmikaDiagnosticsWeb',
[string]$DiagApiServiceName = 'OmikaDiagnosticsApi',
[string]$LanguesServiceName = 'OmikaLanguesApi',
# --- Comptes de service (jamais LocalSystem, jamais un compte humain) ----
[string]$ApiAccount = '.\svc_omika_api',
[string]$WorkerAccount = '.\svc_omika_worker',
[string]$DiagAccount = '.\svc_omika_diag',
[string]$DiagWebAccount = '.\svc_omika_diagweb',
[string]$DiagApiAccount = '.\svc_omika_diagapi',
[string]$LanguesAccount = '.\svc_omika_langues',
[ValidateSet('Manual', 'Automatic', 'Disabled')]
[string]$StartupType = 'Manual',
# --- Perimetre -----------------------------------------------------------
# Le service Langues n'existe que si la traduction hors ligne mobile est deployee.
[switch]$InclureLangues,
# Sur un serveur MONO-SERVEUR, l'API centrale de diagnostics est inutile
# (l'API metier ecrit son JSONL localement, sans forwarding).
[switch]$SansDiagnosticsApi,
# Port loopback a verifier avant de le fixer dans ASPNETCORE_URLS (§6bis).
[ValidateRange(0, 65535)]
[int]$PortLangues = 0,
# --- Rollback ------------------------------------------------------------
[switch]$Desinstaller
)
$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot 'Omika.Deploy.Common.psm1') -Force
# Le module a son propre etat de session : $WhatIfPreference ne s'y propage pas.
$Simulation = [bool]$WhatIfPreference
try {
Assert-OmikaAdmin
Write-OmikaStep 'Perimetre du deploiement'
# --- Composition de la sequence -----------------------------------------
$sequence = New-Object System.Collections.Generic.List[object]
$sequence.Add(@{
Script = 'Install-OmikaApi.ps1'
Libelle = 'OmikaApi'
Parametres = @{
InstallRoot = $InstallRoot
ServiceName = $ApiServiceName
Account = $ApiAccount
StartupType = $StartupType
}
})
$sequence.Add(@{
Script = 'Install-OmikaWorker.ps1'
Libelle = 'OmikaWorker'
Parametres = @{
InstallRoot = $InstallRoot
ServiceName = $WorkerServiceName
Account = $WorkerAccount
StartupType = $StartupType
}
})
if (-not $SansDiagnosticsApi) {
$sequence.Add(@{
Script = 'Install-OmikaDiagnosticsApi.ps1'
Libelle = 'OmikaDiagnosticsApi'
Parametres = @{
InstallRoot = $InstallRoot
ServiceName = $DiagApiServiceName
Account = $DiagApiAccount
AccountWorker = $DiagAccount
StartupType = $StartupType
}
})
}
else {
Write-OmikaInfo 'OmikaDiagnosticsApi EXCLU (-SansDiagnosticsApi).'
}
$sequence.Add(@{
Script = 'Install-OmikaDiagnosticsWorker.ps1'
Libelle = 'OmikaDiagnosticsWorker'
Parametres = @{
InstallRoot = $InstallRoot
ServiceName = $DiagServiceName
Account = $DiagAccount
AccountApi = $ApiAccount
AccountDiagApi = $DiagApiAccount
StartupType = $StartupType
}
})
$sequence.Add(@{
Script = 'Install-OmikaDiagnosticsWeb.ps1'
Libelle = 'OmikaDiagnosticsWeb'
Parametres = @{
InstallRoot = $InstallRoot
ServiceName = $DiagWebServiceName
Account = $DiagWebAccount
StartupType = $StartupType
}
})
if ($InclureLangues) {
$parametresLangues = @{
InstallRoot = $InstallRoot
ServiceName = $LanguesServiceName
Account = $LanguesAccount
StartupType = $StartupType
}
if ($PortLangues -gt 0) { $parametresLangues['Port'] = $PortLangues }
$sequence.Add(@{
Script = 'Install-OmikaLanguesApi.ps1'
Libelle = 'OmikaLanguesApi'
Parametres = $parametresLangues
})
}
else {
Write-OmikaInfo 'OmikaLanguesApi EXCLU (ajoutez -InclureLangues pour l''installer).'
}
$mode = 'INSTALLATION'
if ($Desinstaller) { $mode = 'DESINSTALLATION' }
if ($Simulation) { $mode += ' (SIMULATION -WhatIf)' }
Write-OmikaInfo ("{0} - {1} service(s) dans la sequence" -f $mode, $sequence.Count)
# --- Execution -----------------------------------------------------------
$resultats = @()
foreach ($etape in $sequence) {
$nomService = [string]$etape.Parametres['ServiceName']
$cheminScript = Join-Path $PSScriptRoot $etape.Script
if (-not (Test-Path -LiteralPath $cheminScript)) {
Write-OmikaFail ("Script introuvable : {0} (service {1} ignore)" -f $etape.Script, $nomService)
$resultats += [pscustomobject]@{ Service = $nomService; Resultat = 'SCRIPT ABSENT' }
continue
}
$parametres = $etape.Parametres.Clone()
$parametres['WhatIf'] = $Simulation
if ($Desinstaller) { $parametres['Desinstaller'] = $true }
& $cheminScript @parametres
$code = $LASTEXITCODE
if ($code -eq 0) {
$resultats += [pscustomobject]@{ Service = $nomService; Resultat = 'OK' }
}
else {
$resultats += [pscustomobject]@{ Service = $nomService; Resultat = ("ECHEC (code $code)") }
}
}
# --- Recapitulatif -------------------------------------------------------
Write-Host ''
Write-Host '=== RECAPITULATIF ===' -ForegroundColor Cyan
foreach ($ligne in $resultats) {
$couleur = 'Red'
if ($ligne.Resultat -eq 'OK') { $couleur = 'Green' }
Write-Host (" {0,-26} {1}" -f $ligne.Service, $ligne.Resultat) -ForegroundColor $couleur
}
Write-Host ''
Write-Host 'Etat reel des services :' -ForegroundColor Cyan
$noms = @($sequence | ForEach-Object { [string]$_.Parametres['ServiceName'] })
Get-Service | Where-Object { $noms -contains $_.Name } |
Select-Object Name, Status, StartType | Format-Table -AutoSize
$echecs = @($resultats | Where-Object { $_.Resultat -ne 'OK' })
Write-Host ''
if ($echecs.Count -eq 0) {
Write-Host 'ACTIVATION TERMINEE (services MANUAL + STOPPED).' -ForegroundColor Green
Write-Host 'AUCUN service demarre : le demarrage reste une action MANUELLE.' -ForegroundColor Yellow
Write-Host ''
Write-Host 'Ordre de demarrage (consommateurs avant producteurs) :' -ForegroundColor Yellow
Write-Host ' OmikaDiagnosticsWorker -> OmikaDiagnosticsWeb -> OmikaDiagnosticsApi -> OmikaWorker -> OmikaApi' -ForegroundColor Yellow
}
else {
Write-Host ("ACTIVATION INCOMPLETE : {0} etape(s) en echec." -f $echecs.Count) -ForegroundColor Red
Write-Host 'Corrigez chaque echec, puis relancez ce script (idempotent).' -ForegroundColor Red
}
Write-Host ''
Write-Host 'RAPPELS (jamais automatises ici) :' -ForegroundColor Yellow
Write-Host ' - Injecter les secrets par service (voir les rappels de chaque script).'
Write-Host ' - Verifier le provider OLE DB PCSOFT.HFSQL (64 bits) enregistre.'
Write-Host ' - Installer LibreOffice si la generation PDF des rapports est utilisee.'
Write-Host ' - Appliquer les migrations PostgreSQL 001 -> 010 (retention incluse) avant demarrage.'
if ($echecs.Count -gt 0) { exit 1 }
exit 0
}
catch {
Write-OmikaFail $_.Exception.Message
exit 1
}