# DeployCenter - Chargement et validation des profils de partitionnement # Les profils PSD1 sont des fichiers de données ; ils ne contiennent aucun code exécuté. function Get-DeployCenterPartitionProfileNames { [CmdletBinding()] param([Parameter(Mandatory=$true)][string]$ProfilesRoot) if (-not (Test-Path -LiteralPath $ProfilesRoot -PathType Container)) { return @() } $names = @() foreach ($file in (Get-ChildItem -LiteralPath $ProfilesRoot -Filter '*.psd1' -File -ErrorAction SilentlyContinue)) { if ($file.BaseName -match '^[A-Za-z0-9_-]+$') { $names += $file.BaseName } } return @($names | Sort-Object -Unique) } function Import-DeployCenterPartitionProfile { [CmdletBinding()] param( [Parameter(Mandatory=$true)][string]$ProfilesRoot, [Parameter(Mandatory=$true)][string]$ProfileName ) if ($ProfileName -notmatch '^[A-Za-z0-9_-]+$') { throw "Nom de profil invalide : $ProfileName" } $path = Join-Path $ProfilesRoot ($ProfileName + '.psd1') if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw "Profil introuvable : $ProfileName" } $profile = Import-PowerShellDataFile -LiteralPath $path foreach ($key in @('Id','Name','Description','Firmware','PartitionStyle','Partitions')) { if (-not $profile.ContainsKey($key)) { throw "Le profil '$ProfileName' ne contient pas la clé '$key'." } } if ([string]$profile.Id -ne $ProfileName) { throw "L'identifiant du profil '$ProfileName' ne correspond pas au nom du fichier." } if (@($profile.Partitions).Count -lt 2) { throw "Le profil '$ProfileName' doit définir au moins deux partitions." } if (@($profile.Partitions | Where-Object { [string]$_.Role -eq 'Windows' }).Count -ne 1) { throw "Le profil '$ProfileName' doit définir exactement une partition Windows." } $userInputPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'UserInputGB' }) $remainderPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'RemainderAfterInputs' }) $remainingPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'Remaining' }) if ($userInputPartitions.Count -gt 0) { if ($remainderPartitions.Count -ne 1 -or $remainingPartitions.Count -gt 0) { throw "Le profil '$ProfileName' doit associer les saisies utilisateur à une partition de reste unique." } } elseif ($remainingPartitions.Count -ne 1 -or [string]$profile.Partitions[-1].Size.Policy -ne 'Remaining') { throw "Le profil '$ProfileName' doit placer une unique partition utilisant l'espace restant en dernière position." } foreach ($partition in $profile.Partitions) { foreach ($key in @('Name','Role','FileSystem','Size')) { if (-not $partition.ContainsKey($key)) { throw "Une partition du profil '$ProfileName' ne contient pas la clé '$key'." } } if (-not $partition.Size.ContainsKey('Policy')) { throw "La taille d'une partition du profil '$ProfileName' ne définit pas Policy." } switch ([string]$partition.Size.Policy) { 'FixedMB' { if ([int]$partition.Size.Value -le 0) { throw "Une taille fixe du profil '$ProfileName' doit être supérieure à zéro." } } 'ImageSizePlusFreeSpace' { if ([int]$partition.Size.FreeSpaceMB -lt 250) { throw "La marge libre WinRE du profil '$ProfileName' doit être d'au moins 250 Mo." } if ([int]$partition.Size.PreviewMB -le 0) { throw "Le profil '$ProfileName' doit définir une réserve PreviewMB pour estimer la capacité disponible." } } 'UserInputGB' { if ([int]$partition.Size.MinimumGB -le 0 -or [int]$partition.Size.DefaultPercent -le 0 -or [int]$partition.Size.DefaultPercent -ge 100) { throw "La saisie de taille utilisateur du profil '$ProfileName' doit définir MinimumGB et un DefaultPercent entre 1 et 99." } if ([string]::IsNullOrWhiteSpace([string]$partition.Size.Label)) { throw "La saisie de taille utilisateur du profil '$ProfileName' doit définir Label." } } 'RemainderAfterInputs' { if ([double]$partition.Size.MinimumGB -lt 0 -or [string]::IsNullOrWhiteSpace([string]$partition.Size.Label)) { throw "La partition de reste du profil '$ProfileName' doit définir un MinimumGB non négatif et un Label." } } 'Remaining' { } default { throw "Politique de taille inconnue dans le profil '$ProfileName' : $($partition.Size.Policy)" } } } return $profile } function Get-DeployCenterPartitionSizingCapacity { [CmdletBinding()] param( [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Profile, [Parameter(Mandatory=$true)][long]$DiskSizeBytes ) $reservedMB = 0.0 foreach ($partition in $Profile.Partitions) { switch ([string]$partition.Size.Policy) { 'FixedMB' { $reservedMB += [double]$partition.Size.Value } default { if ($partition.Size.ContainsKey('PreviewMB')) { $reservedMB += [double]$partition.Size.PreviewMB } } } } $capacityBytes = $DiskSizeBytes - [long][math]::Ceiling($reservedMB * 1MB) if ($capacityBytes -le 0) { throw "Le disque est trop petit pour les réserves du profil '$($Profile.Name)'." } return [pscustomobject]@{ UsableBytes = [long]$capacityBytes UsableGB = [math]::Round(($capacityBytes / 1GB), 1) ReservedMB = [math]::Ceiling($reservedMB) } } Export-ModuleMember -Function Get-DeployCenterPartitionProfileNames, Import-DeployCenterPartitionProfile, Get-DeployCenterPartitionSizingCapacity