I changed the structure of the functions to improve performance when working with large numbers of datastores and hosts. I also added more verbose progress bars so that the user would be more aware of what the scripts were doing at any given time.
246 lines
9.3 KiB
PowerShell
246 lines
9.3 KiB
PowerShell
<#
|
|
.SYNOPSIS Datastore Functions
|
|
.DESCRIPTION A collection of functions to manipulate datastore Mount + Attach status
|
|
.EXAMPLE Get-Datastore | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
|
|
.EXAMPLE Get-Datastore IX2ISCSI01 | Unmount-Datastore
|
|
.EXAMPLE Get-Datastore IX2ISCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Mount-Datastore
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Detach-Datastore
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Attach-datastore
|
|
.EXAMPLE Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize
|
|
.NOTES Written by Alan Renouf, originally published at https://blogs.vmware.com/vsphere/2012/01/automating-datastore-storage-device-detachment-in-vsphere-5.html
|
|
.NOTES May 2017: Modified by Jason Coleman (virtuallyjason.blogspot.com), to improve performance when dealing with a large number of hosts and datastores
|
|
#>
|
|
Function Get-HostViews {
|
|
[CmdletBinding()]
|
|
Param (
|
|
$Datastore
|
|
)
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
#Build the array of Datastore Objects
|
|
if (-not $Datastore) {
|
|
$allDatastores = Get-Datastore
|
|
}
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allHosts = @()
|
|
$DShostsKeys = $allDatastores.extensiondata.host.key.value | sort | get-unique -asstring
|
|
$DShosts = foreach ($thisKey in $DShostsKeys) {($allDatastores.extensiondata.host | ? {$_.key.value -eq $thisKey})[0]}
|
|
$i = 1
|
|
foreach ($DSHost in $DSHosts){
|
|
write-progress -activity "Collecting ESXi Host Views" -status "Querying $($dshost.key)..." -percentComplete ($i++/$DSHosts.count*100)
|
|
$hostObj = "" | select keyValue,hostView,storageSys
|
|
$hostObj.hostView = get-view $DSHost.key
|
|
$hostObj.keyValue = $DSHost.key.value
|
|
$hostObj.storageSys = Get-View $hostObj.hostView.ConfigManager.StorageSystem
|
|
$allHosts += $hostObj
|
|
}
|
|
write-progress -activity "Collecting ESXi Host Views" -completed
|
|
$allHosts
|
|
}
|
|
}
|
|
|
|
Function Get-DatastoreMountInfo {
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(ValueFromPipeline=$true)]
|
|
$Datastore
|
|
)
|
|
#Roll back up an unrolled array from a pipeline
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
$AllInfo = @()
|
|
#Build the array of Datastore Objects
|
|
if (-not $Datastore) {
|
|
$allDatastores = Get-Datastore
|
|
}
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
|
|
|
|
#Build the array of custom Host Objects
|
|
$allHosts = Get-HostViews -datastore $allDatastores
|
|
$output = @()
|
|
$i = 1
|
|
foreach ($dsHost in $allHosts){
|
|
write-progress -activity "Checking Datastore access" -status "Checking $($dshost.hostview.name)..." -percentComplete ($i++ / $allHosts.count * 100)
|
|
#Get all devices on the host that match the list of $allDatastoreNAAs
|
|
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun
|
|
foreach ($device in $devices){
|
|
if ($allDatastoreNAAs -contains $device.canonicalName){
|
|
#Record information about this device/host combo
|
|
$thisDatastore = $alldatastores | ? {$_.ExtensionData.Info.vmfs.extent[0].diskname -eq $device.canonicalName}
|
|
$hostviewDSAttachState = ""
|
|
if ($device.operationalState[0] -eq "ok") {
|
|
$hostviewDSAttachState = "Attached"
|
|
} elseif ($device.operationalState[0] -eq "off") {
|
|
$hostviewDSAttachState = "Detached"
|
|
} else {
|
|
$hostviewDSAttachState = $device.operationalstate[0]
|
|
}
|
|
$Info = "" | Select Datastore, VMHost, Lun, Mounted, State
|
|
$Info.VMHost = $dsHost.hostview.name
|
|
$Info.Datastore = $thisDatastore.name
|
|
$Info.Lun = $device.canonicalName
|
|
$Info.mounted = ($thisDatastore.extensiondata.host | ? {$_.key.value -eq $dshost.keyvalue}).mountinfo.mounted
|
|
$Info.state = $hostviewDSAttachState
|
|
$output += $info
|
|
}
|
|
}
|
|
}
|
|
write-progress -activity "Checking Datastore access" -completed
|
|
$output
|
|
}
|
|
}
|
|
|
|
Function Detach-Datastore {
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(ValueFromPipeline=$true)]
|
|
$Datastore
|
|
)
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
|
|
$allHosts = Get-HostViews -datastore $allDatastores
|
|
$j = 1
|
|
foreach ($dsHost in $allHosts){
|
|
#Get all devices on the host that match the list of $allDatastoreNAAs
|
|
write-progress -id 1 -activity "Detaching Datastores" -status "Removing device(s) from $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
|
|
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun | ? {$allDatastoreNAAs -contains $_.canonicalName}
|
|
$i = 1
|
|
foreach ($device in $devices){
|
|
write-progress -parentid 1 -activity "Detaching Datastores" -status "Removing device: $(($allDatastores | ? {$_.ExtensionData.Info.vmfs.extent[0].diskname -eq $device.canonicalName}).name)" -percentComplete ($i++ / $allDatastoreNAAs.count * 100)
|
|
$LunUUID = $Device.Uuid
|
|
$dsHost.storageSys.DetachScsiLun($LunUUID);
|
|
}
|
|
}
|
|
write-progress -activity "Detaching Datastores" -completed
|
|
}
|
|
}
|
|
|
|
Function Attach-Datastore {
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(ValueFromPipeline=$true)]
|
|
$Datastore
|
|
)
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allDatastoreNAAs = foreach ($ds in $allDatastores) {$ds.ExtensionData.Info.vmfs.extent[0].diskname}
|
|
$allHosts = Get-HostViews -datastore $allDatastores
|
|
$j = 1
|
|
foreach ($dsHost in $allHosts){
|
|
#Get all devices on the host that match the list of $allDatastoreNAAs
|
|
write-progress -id 1 -activity "Attaching Datastores" -status "Attaching devices to $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
|
|
$devices = $dsHost.storagesys.StorageDeviceInfo.ScsiLun
|
|
$i = 1
|
|
foreach ($device in $devices){
|
|
write-progress -parentid 1 -activity "Attaching Datastores" -status "Attaching device: $($Device.Uuid)" -percentComplete ($i++ / $devices.count * 100)
|
|
if ($allDatastoreNAAs -contains $device.canonicalName){
|
|
$LunUUID = $Device.Uuid
|
|
$dsHost.storageSys.AttachScsiLun($LunUUID);
|
|
}
|
|
}
|
|
}
|
|
write-progress -activity "Attaching Datastores" -completed
|
|
}
|
|
}
|
|
|
|
Function Unmount-Datastore {
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(ValueFromPipeline=$true)]
|
|
$Datastore
|
|
)
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allHosts = Get-HostViews -datastore $allDatastores
|
|
$j = 1
|
|
foreach ($dsHost in $allHosts){
|
|
write-progress -id 1 -activity "Unmounting Datastores" -status "Unmounting devices from $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
|
|
$i = 1
|
|
foreach ($ds in $allDatastores){
|
|
write-progress -parentid 1 -activity "Unmounting Datastores" -status "Unmounting device: $($ds.name)" -percentComplete ($i++ / $allDatastores.count * 100)
|
|
$dsHost.storageSys.UnmountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
|
|
}
|
|
}
|
|
write-progress -activity "Unmounting Datastores" -completed
|
|
}
|
|
}
|
|
|
|
Function Mount-Datastore {
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(ValueFromPipeline=$true)]
|
|
$Datastore
|
|
)
|
|
Begin{
|
|
$allDatastores = @()
|
|
}
|
|
Process {
|
|
$allDatastores += $Datastore
|
|
}
|
|
End {
|
|
$allDatastores = $allDatastores | ? {$_.pstypenames -contains "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl"}
|
|
if (-not $allDatastores){
|
|
Throw "No Datastores found.`nIs ""$Datastore"" a Datastore Object?"
|
|
}
|
|
$allHosts = Get-HostViews -datastore $allDatastores
|
|
$j = 0
|
|
foreach ($dsHost in $allHosts){
|
|
write-progress -activity "Mounting Datastores" -status "Mounting devices to $($dsHost.hostview.name)" -percentComplete ($j++ / $allHosts.count * 100)
|
|
$i = 1
|
|
foreach ($ds in $allDatastores){
|
|
write-progress -activity "Mounting Datastores" -status "Mounting device: $($DS.ExtensionData.Info.vmfs.uuid)" -percentComplete ($i++ / $allDatastores.count * 100)
|
|
$dsHost.storageSys.MountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);
|
|
}
|
|
}
|
|
write-progress -activity "Mounting Datastores" -completed
|
|
}
|
|
}
|