Files
DeployCenter/Modules/Partitioning.psm1
T

105 lines
5.7 KiB
PowerShell

# 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