================================================================================
WSFC + SQL Server 2017 -> Windows Server 2025 + SQL Server 2025
Automatisierungspaket - STRATEGIE B: In-Place Rolling Re-Image
================================================================================

Strategie:
----------
Die 3 vorhandenen VMware-VMs (SQLN01, SQLN02, SQLN03) werden weiterverwendet:
- vCenter-VM-Objekte (UUID, MAC, Folder, Tags, Permissions) bleiben erhalten
- Hostnames bleiben unveraendert (kein sp_dropserver/sp_addserver noetig)
- Pro Knoten: VM-Disks DETACH (bleiben als Backup) -> neue Disks -> OS-Install
- Reihenfolge: SQLN03 (Sec2) -> SQLN02 (Sec1) -> SQLN01 (Ex-Primary)
- Uebergang via Distributed AG (DAG_MIGRATION)
- AG-Name AG_PROD_NEW bleibt (BEWUSST kein Drop+Create wegen Risiko)
- Final-Rename: nur Cluster + Listener (Listener-IP wird wiederverwendet)

Zentrale Konfiguration:
-----------------------
Alle Skripte lesen Parameter aus EINER Datei:
  Config.psd1          Hauptkonfiguration (kein Klartext fuer Secrets)
  00-LoadConfig.ps1    Loader + Validierung + Helper-Functions

Vor erstem Lauf:
  1. Config.psd1 oeffnen, alle 'CHANGE-ME' und realen Werte (Hostnames,
     vCenter, IPs, Service-Accounts, Witness, ISO-Pfade) eintragen.
  2. Secret-Vault einrichten (Microsoft.PowerShell.SecretManagement empfohlen):

     Install-Module Microsoft.PowerShell.SecretManagement
     Install-Module Microsoft.PowerShell.SecretStore
     Register-SecretVault -Name 'WSFC-Migration-Vault' `
         -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
     Set-Secret -Name SQL2025_SA_PWD       -Secret (Read-Host -AsSecureString)
     Set-Secret -Name SQL2025_SVC_SQL_PWD  -Secret (Read-Host -AsSecureString)
     Set-Secret -Name SQL2025_SVC_AGT_PWD  -Secret (Read-Host -AsSecureString)
     Set-Secret -Name SQL2025_CERT_ENCRYPTION_PWD -Secret (Read-Host -AsSecureString)
     Set-Secret -Name SQL2025_CLOUD_WITNESS_KEY   -Secret (Read-Host -AsSecureString)

  3. Safety-Gates in Config:
     Safety.AllowProduction              = $true   (vor Cutover/Rename)
     Safety.AcceptPhase2SPOFRisk         = $true   (vor Phase 2 - SQLN02 Re-Image)
     Safety.AcceptNoRollbackAfterCutover = $true   (vor Cutover - kein SQL2017-Failback)

  4. Autounattend-ISO fuer Windows Server 2025 mit Hostname-Logik vorbereiten
     (so dass je VM der Hostname aus der VM-Hardware gelesen wird oder per
      manueller VM-spezifischer ISO).

Ausfuehrungsreihenfolge:
------------------------

  PHASE 0 - Pre-Migration (einmalig):
    .\01-Preflight-Assessment.ps1
      - DBCC/Backup-Verify/Inventory
      - Witness auf altem Cluster nachruesten (war 'none')
      - VM-Inventar exportieren
      - Optional: Cold-Clone aller VMs als Rollback-Anker

  PHASE 1 - Re-Image SQLN03 (Sec2 - niedrigstes Risiko):
    .\02-Evict-Node.ps1       -NodeName SQLN03
    .\03-Reimage-VMShell.ps1  -NodeName SQLN03
    .\04-Configure-Windows.ps1 -NodeName SQLN03
    .\05-Install-SQL.ps1      -NodeName SQLN03
    .\06-Build-NewCluster.ps1 -NodeName SQLN03 -CreateNewCluster
    .\07-Create-AG-DAG.ps1    -NodeName SQLN03 -CreateNewAG

  PHASE 2 - Re-Image SQLN02 (Sec1 - HIGH-RISK SPOF):
    !! AcceptPhase2SPOFRisk = $true !!
    !! Frische Backup-Verifikation direkt davor !!
    .\02-Evict-Node.ps1       -NodeName SQLN02
    .\03-Reimage-VMShell.ps1  -NodeName SQLN02
    .\04-Configure-Windows.ps1 -NodeName SQLN02
    .\05-Install-SQL.ps1      -NodeName SQLN02
    .\06-Build-NewCluster.ps1 -NodeName SQLN02
    .\07-Create-AG-DAG.ps1    -NodeName SQLN02

  PHASE 2.5 - Server-Scope-Objekte migrieren:
    .\08-Migrate-Logins-Jobs.ps1
    .\09-Monitor-Sync.ps1                          # bis Queue = 0

  PHASE 3 - Cutover (WARTUNGSFENSTER!):
    !! AllowProduction = $true !!
    !! AcceptNoRollbackAfterCutover = $true !!
    Apps stoppen oder Read-Only
    .\10-Cutover.ps1

  PHASE 4 - Re-Image SQLN01 (Ex-Primary):
    .\02-Evict-Node.ps1       -NodeName SQLN01 -ForcePrimary
    .\03-Reimage-VMShell.ps1  -NodeName SQLN01
    .\04-Configure-Windows.ps1 -NodeName SQLN01
    .\05-Install-SQL.ps1      -NodeName SQLN01
    .\06-Build-NewCluster.ps1 -NodeName SQLN01
    .\07-Create-AG-DAG.ps1    -NodeName SQLN01

  PHASE 4.5 - Altumgebung abbauen (manuell):
    - Alter Cluster SQLCL01 ist mit Eviction von SQLN01 in Phase 4 zerfallen
    - DNS-Eintrag SQLLST01 loeschen
    - AD-CNO SQLCL01 + VCO SQLLST01 loeschen (falls Reste)
    - IP 10.10.10.50 freigeben

  PHASE 5 - Rename auf Original-Namen:
    .\11-Rename-Resources.ps1
      - Listener: SQLLST01N -> SQLLST01 mit IP 10.10.10.50
      - Cluster:  SQLCL01N -> SQLCL01
      - AG-Name bleibt AG_PROD_NEW
      - SPN-Bereinigung + Neu-Setzen + Duplicate-Check

  PHASE 6 - Acceptance:
    Invoke-Pester -Path .\12-Acceptance.Tests.ps1 -Output Detailed

Voraussetzungen auf der Steuerungs-Workstation:
-----------------------------------------------
  PowerShell 7.4+
  Module:
    Install-Module dbatools         -Scope CurrentUser
    Install-Module VMware.PowerCLI  -Scope CurrentUser
    Install-Module Pester           -MinimumVersion 5.5 -Scope CurrentUser
    Install-Module Microsoft.PowerShell.SecretManagement -Scope CurrentUser
    Install-Module Microsoft.PowerShell.SecretStore      -Scope CurrentUser
  RSAT:
    Install-WindowsFeature RSAT-Clustering, RSAT-AD-PowerShell

Sicherheits-Hinweise:
---------------------
  - Config.psd1 enthaelt NUR Namen/IPs/Pfade, KEINE Passwoerter.
  - Secrets bleiben im Vault und werden nur im RAM dekodiert (SecureString).
  - Cutover + Rename verlangen AllowProduction.
  - Phase 2 verlangt zusaetzlich AcceptPhase2SPOFRisk (SPOF).
  - Cutover verlangt AcceptNoRollbackAfterCutover (Point of no return).
  - Alte VMDKs werden DETACHED (nicht geloescht) - bleiben als Backup im Datastore.
  - AD-Computer-Accounts werden RESETTET (nicht geloescht) - ACLs/SPNs/Memberships bleiben.
  - Transcripts unter Paths.TranscriptDir = revisionssicher.

Rollback-Hinweise:
------------------
  - Vor Cutover: Re-Attach der alten VMDKs in vCenter UND Reset des
    AD-Computer-Account-Passworts via 'reset' im OS (lokaler Admin) noetig.
  - Nach Cutover: Kein realistischer Failback auf SQL 2017 mehr - nur Restore
    aus Backup auf die alten VMDKs UND vorheriger Sicherung der neuen DBs.
  - Empfohlen: Cold-Clone vor Phase 1 (Config.ReImage.CloneAsBackup = $true).

    Quellenverweise: siehe Upgrade_Plan_SQL2025_WS2025.html (Abschnitt 16).
