105 lines
5.7 KiB
PowerShell
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
|