VMFSIncrease.psm1
function Get-VmfsDatastoreInfo { [CmdletBinding(SupportsShouldProcess = $True)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] [PSObject]$Datastore ) Process { if ($Datastore -is [String]) { $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue } if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) { Write-Error 'Invalid value for Datastore.' return } if ($Datastore.Type -ne 'VMFS') { Write-Error "$($Datastore.Name) is not a VMFS datastore" return } # Get the Datastore System Manager from an ESXi that has the Datastore $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem foreach ($extent in $Datastore.ExtensionData.Info.Vmfs.Extent) { $lun = $esx.Config.StorageDevice.ScsiLun | where{ $_.CanonicalName -eq $extent.DiskName } $hdPartInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) $hdPartInfo[0].Layout.Partition | %{ New-Object PSObject -Property ([ordered]@{ Datastore = $Datastore.Name CanonicalName = $lun.CanonicalName Model = "$($lun.Vendor.TrimEnd(' ')).$($lun.Model.TrimEnd(' ')).$($lun.Revision.TrimEnd(' '))" DiskSizeGB = $hdPartInfo[0].Layout.Total.BlockSize * $hdPartInfo[0].Layout.Total.Block / 1GB DiskBlocks = $hdPartInfo[0].Layout.Total.Block DiskBlockMB = $hdPartInfo[0].Layout.Total.BlockSize/1MB PartitionFormat = $hdPartInfo[0].Spec.PartitionFormat Partition = if ($_.Partition -eq '') { '<free>' }else{ $_.Partition } Used = $extent.Partition -eq $_.Partition Type = $_.Type PartitionSizeGB = [math]::Round(($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize / 1GB, 1) PartitionBlocks = $_.End.Block - $_.Start.Block + 1 PartitionBlockMB = $_.Start.BlockSize/1MB Start = $_.Start.Block End = $_.End.Block }) } } } } function Get-VmfsDatastoreIncrease { [CmdletBinding(SupportsShouldProcess = $True)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] [PSObject]$Datastore ) Process { if ($Datastore -is [String]) { $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue } if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) { Write-Error 'Invalid value for Datastore.' return } if ($Datastore.Type -ne 'VMFS') { Write-Error "$($Datastore.Name) is not a VMFS datastore" return } # Get the Datastore System Manager from an ESXi that has the Datastore $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem $hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem $extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName $hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef) foreach ($disk in $hScsiDisk) { $partInfo = $hsSys.RetrieveDiskPartitionInfo($disk.DeviceName) $partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB if ($extents -contains $disk.CanonicalName) { $incType = 'Expand' $vmfsExpOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) $PartMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB } else { $incType = 'Extend' $vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $disk.DevicePath, $null) $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB } New-Object PSObject -Property ([ordered]@{ Datastore = $Datastore.Name CanonicalName = $disk.CanonicalName Model = "$($disk.Vendor.TrimEnd(' ')).$($disk.Model.TrimEnd(' ')).$($disk.Revision.TrimEnd(' '))" DiskSizeGB = $partInfo[0].Layout.Total.BlockSize * $partInfo[0].Layout.Total.Block / 1GB DiskBlocks = $partInfo[0].Layout.Total.Block DiskBlockMB = $partInfo[0].Layout.Total.BlockSize/1MB AvailableGB = [math]::Round($partMax - $partUsed, 2) Type = $incType }) } } } function New-VmfsDatastoreIncrease { [CmdletBinding(SupportsShouldProcess = $True)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] [PSObject]$Datastore, [int]$IncreaseSizeGB, [Parameter(Position = 1)] [string]$CanonicalName, [Parameter(Mandatory = $true, ParameterSetName = 'Expand')] [switch]$Expand, [Parameter(Mandatory = $true, ParameterSetName = 'ExTend')] [switch]$Extend ) Process { if ($Datastore -is [String]) { $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue } if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) { Write-Error 'Invalid value for Datastore.' return } if ($Datastore.Type -ne 'VMFS') { Write-Error "$($Datastore.Name) is not a VMFS datastore" return } # Get the Datastore System Manager from an ESXi that has the Datastore $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem $hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem $extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName $hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef) # Expand or Extend switch ($PSCmdlet.ParameterSetName) { 'Expand' { $expOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) if ($CanonicalName) { $dsOpt = $expOpt | where{ $_.Spec.Extent.DiskName -eq $CanonicalName } } else { $dsOpt = $expOpt | Sort-Object -Property { $_.Spec.Extent.Diskname } | select -first 1 } if ($IncreaseSizeGB -ne 0) { $lun = $hScsiDisk | where{ $_.CanonicalName -eq $dsOpt.Spec.Extent.DiskName } $partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB $partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB if (($partMax - $partUsed) -ge $IncreaseSizeGB) { $spec = $dsOpt.Spec $spec.Partition.Partition[0].EndSector -= ([math]::Floor(($partMax - $partUsed - $IncreaseSizeGB) * 1GB/512)) } else { Write-Error "Requested expand size $($IncreaseSizeGB)GB not available on $($lun.CanonicalName)" return } } else { $spec = $dsOpt.Spec } $hdSys.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef, $spec) } 'Extend' { if ($CanonicalName) { $lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName -and $_.CanonicalName -eq $CanonicalName } } else { $lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName } | Sort-Object -Property CanonicalName | select -First 1 } if (!$lun) { Write-Error "No valid LUN provided or found for extent" return } $vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $lun.DevicePath, $null) if ($IncreaseSizeGB -ne 0) { $partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | Measure-Object -Sum | select -ExpandProperty Sum)/1GB if ($partMax -ge $IncreaseSizeGB) { $spec = $vmfsExtOpt[0].Spec $spec.Partition.Partition[0].EndSector = $spec.Partition.Partition[0].StartSector + [math]::Floor($IncreaseSizeGB * 1GB / 512) } else { Write-Error "No valid LUN for extent with $($IncreaseSizeGB)GB space found" return } } else { $spec = $vmfsExtOpt.Spec } $hdSys.ExtendVmfsDatastore($Datastore.ExtensionData.MoRef, $spec) } } } } Export-ModuleMember -Function Get-VmfsDatastoreInfo,Get-VmfsDatastoreIncrease,New-VmfsDatastoreIncrease |