VMware Cloud Community
momox1
Contributor
Contributor

Unmount datastores if unused and dettach them based on NAA

Hello,

I dont know if it has already been done. I would like to get some help on a script that unmounts all empty/unused datastores and dettaches them if already unmounted or in maintenance.

I would like to get the NAA of the unmounted datastores before dettaching them. Storage Array /vmware Checking purposes...

Thank you for your help.

Tags (1)
Reply
0 Kudos
14 Replies
LucD
Leadership
Leadership

Unmounting and detaching is shown in Datastore Mount/Unmount Detach/Attach functions

But how would you determine that a datastore is empty and/or unused?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

I meant If there is no VMs or vmdks hosted on the datatastore. It is possible?

Thank you

Reply
0 Kudos
LucD
Leadership
Leadership

You could do something like this.

It looks if there are VMs on the datastore or VMDK (and ignores eventual orphaned VMDK).
Can you chekc if that would find your empty and/or unused datastores?

$dsName = 'MyDS'

$ds = Get-Datastore -Name $dsName

$vm = Get-VM -Datastore $ds


$vmVmdk = (Get-VM | Get-HardDisk).FileName

New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root '\' | Out-Null

$vmdk = (Get-ChildItem -Path DS: -Recurse -Include '*.vmdk' | where{$vmVmdk -notcontains $_.DatastoreFullPath}).DatastoreFullPath

Remove-PSDrive -Name DS -Confirm:$false


if(-not $vm -and -not $vmdk){

   Write-Host "Datastore $dsName is empty"

}

else{

   Write-Host "Datastore $dsName is not empty"

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

great!! it does the work, now I have to add the function to unmount and dettach that datastore...

As soon as  i get it done I will post it here.

Feel free to share some code if already done.

Thank you for your support.

Reply
0 Kudos
LucD
Leadership
Leadership

If you use the functions I pointed to earlier, it would just be adding some lines when the datastore is empty.

$dsName = 'MyDS'

$ds = Get-Datastore -Name $dsName


$vm = Get-VM -Datastore $ds


$vmVmdk = (Get-VM | Get-HardDisk).FileName

New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root '\' | Out-Null

$vmdk = (Get-ChildItem -Path DS: -Recurse -Include '*.vmdk' | Where-Object { $vmVmdk -notcontains $_.DatastoreFullPath }).DatastoreFullPath

Remove-PSDrive -Name DS -Confirm:$false


if (-not $vm -and -not $vmdk)

{

   Get-DatastoreMountInfo -Datastore $ds

  Unmount-Datastore -Datastore $ds

  Detach-Datastore -Datastore $ds

}

else

{

   Write-Host "Datastore $dsName is not empty"

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

HI LucD,

Is there any way to create a loop so I can check all vcenter's datastores without having to specify the datastore name at the begining?

Thank you

Reply
0 Kudos
momox1
Contributor
Contributor

found it on another of your posts^^

Thank you

VMware PowerCLI Forum - VMware {code}

Reply
0 Kudos
LucD
Leadership
Leadership

Great!
Feel free to ask if you have further questions.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

last questions , I promise^^

Do you see an easy way to merge the check if datastore is umountable fonction ( Test if the datastore can be unmounted - LucD notes ) with the unmount it and dettached if true.

An easy way to run it over all vCenter's datastores and if it's unmountable do it and dettach it?

Thank you

Reply
0 Kudos
LucD
Leadership
Leadership

Try something like this

function Get-DatastoreUnmountStatus

{

   <#

.SYNOPSIS  Check if a datastore can be unmounted.

.DESCRIPTION The function checks a number of prerequisites

that need to be met to be able to unmount a datastore.

.NOTES  Author: Luc Dekens

.PARAMETER Datastore

The datastore for which you want to chekc the conditions.

You can pass the name of the datastore or the Datastore

object returned by Get-Datastore

.EXAMPLE

PS> Get-DatastoreUnmountStatus -Datastore DS1

.EXAMPLE

PS> Get-Datastore | Get-DatastoreUnmountStatus

#>

   param(

   [CmdletBinding()]

   [Parameter(Mandatory = $true, ValueFromPipeline = $true)]

   [PSObject[]]$Datastore

   )

   process

   {

   foreach ($ds in $Datastore)

   {

   if ($ds.GetType().Name -eq "string")

   {

   $ds = Get-Datastore -Name $ds

   }

   $parent = Get-View $ds.ExtensionData.Parent

   New-Object PSObject -Property @{

   Datastore = $ds.Name

   # No Virtual machines

   NoVM = $ds.ExtensionData.VM.Count -eq 0

   # Not in a Datastore Cluster

   NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]

   # Not managed by sDRS

   NosDRS = & {

   if ($parent -is [VMware.Vim.StoragePod])

   {

   !$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled

   }

   else { $true }

   }

   # SIOC disabled

   NoSIOC = !$ds.StorageIOControlEnabled

   # No HA heartbeat

   NoHAheartbeat = & {

   $hbDatastores = @()

   $cls = Get-View -ViewType ClusterComputeResource -Property Host |

   Where-Object { $_.Host -contains $ds.ExtensionData.Host[0].Key }

   if ($cls)

   {

   $cls | % {

   (   $_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | % {

   $hbDatastores += $_.Datastore

   }

   }

   $hbDatastores -notcontains $ds.ExtensionData.MoRef

   }

   else { $true }

   }

   # No vdSW file

   NovdSwFile = & {

   New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-Null

   $result = Get-ChildItem -Path ds:\ -Recurse |

   Where-Object { $_.Name -match '.dvsData' }

   Remove-PSDrive -Name ds -Confirm:$false

   if ($result) { $false }else { $true }

   }

   # No scratch partition

   NoScratchPartition = & {

   $result = $true

   $ds.ExtensionData.Host | % { Get-View $_.Key } | % {

   $diagSys = Get-View $_.ConfigManager.DiagnosticSystem

   $dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | % { $_.DiskName }

   if ($dsDisks -contains $diagSys.ActivePartition.Id.DiskName)

   {

   $result = $false

   }

   }

   $result

   }

   }

   }

   }

}


Get-Datastore -PipelineVariable ds |

ForEach-Object -Process {

   $result = Get-DatastoreUnmountStatus -Datastore $ds

   if (($result.PSObject.Properties | Where-Object { $_.Name -match "^No" }).Value -notcontains $false)

   {

   $vm = Get-VM -Datastore $ds

   $vmVmdk = (Get-VM | Get-HardDisk).FileName

   New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root '\' | Out-Null

   $vmdk = (Get-ChildItem -Path DS: -Recurse -Include '*.vmdk' | Where-Object { $vmVmdk -notcontains $_.DatastoreFullPath }).DatastoreFullPath

   Remove-PSDrive -Name DS -Confirm:$false

   if (-not $vm -and -not $vmdk)

   {

   Get-DatastoreMountInfo -Datastore $ds

  Unmount-Datastore -Datastore $ds

  Detach-Datastore -Datastore $ds

   }

   else

   {

   Write-Host "Datastore $dsName is not empty"

   }

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

Hola

I have commented all the checks except the VM and scratch check, I have a datastore empty,  but still getting the datastore is not empty result.

any hint?

Thank you

function Get-DatastoreUnmountStatus

{

   <#

.SYNOPSIS  Check if a datastore can be unmounted.

.DESCRIPTION The function checks a number of prerequisites

that need to be met to be able to unmount a datastore.

.NOTES  Author: Luc Dekens

.PARAMETER Datastore

The datastore for which you want to chekc the conditions.

You can pass the name of the datastore or the Datastore

object returned by Get-Datastore

.EXAMPLE

PS> Get-DatastoreUnmountStatus -Datastore DS1

.EXAMPLE

PS> Get-Datastore | Get-DatastoreUnmountStatus

#>

   param(

   [CmdletBinding()]

   [Parameter(Mandatory = $true, ValueFromPipeline = $true)]

   [PSObject[]]$Datastore

   )

   process

   {

   foreach ($ds in $Datastore)

   {

   if ($ds.GetType().Name -eq "string")

   {

   $ds = Get-Datastore -Name $ds

   }

   $parent = Get-View $ds.ExtensionData.Parent

   New-Object PSObject -Property @{

   Datastore = $ds.Name

   # No Virtual machines

   NoVM = $ds.ExtensionData.VM.Count -eq 0

<#

   # Not in a Datastore Cluster

   NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]

   # Not managed by sDRS

   NosDRS = & {

   if ($parent -is [VMware.Vim.StoragePod])

   {

   !$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled

   }

   else { $true }

   }

   # SIOC disabled

   NoSIOC = !$ds.StorageIOControlEnabled

   # No HA heartbeat

   NoHAheartbeat = & {

   $hbDatastores = @()

   $cls = Get-View -ViewType ClusterComputeResource -Property Host |

   Where-Object { $_.Host -contains $ds.ExtensionData.Host[0].Key }

   if ($cls)

   {

   $cls | % {

   (   $_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | % {

   $hbDatastores += $_.Datastore

   }

   }

   $hbDatastores -notcontains $ds.ExtensionData.MoRef

   }

   else { $true }

   }

   # No vdSW file

   NovdSwFile = & {

   New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-Null

   $result = Get-ChildItem -Path ds:\ -Recurse |

   Where-Object { $_.Name -match '.dvsData' }

   Remove-PSDrive -Name ds -Confirm:$false

   if ($result) { $false }else { $true }

   }

#>

   # No scratch partition

   NoScratchPartition = & {

   $result = $true

   $ds.ExtensionData.Host | % { Get-View $_.Key } | % {

   $diagSys = Get-View $_.ConfigManager.DiagnosticSystem

   $dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | % { $_.DiskName }

   if ($dsDisks -contains $diagSys.ActivePartition.Id.DiskName)

   {

   $result = $false

   }

   }

   $result

   }

   }

   }

   }

}

Get-Datastore -PipelineVariable ds |

ForEach-Object -Process {

   $result = Get-DatastoreUnmountStatus -Datastore $ds

   if (($result.PSObject.Properties | Where-Object { $_.Name -match "^No" }).Value -notcontains $false)

   {

   $vm = Get-VM -Datastore $ds

   $vmVmdk = (Get-VM | Get-HardDisk).FileName

   New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root '\' | Out-Null

   $vmdk = (Get-ChildItem -Path DS: -Recurse -Include '*.vmdk' | Where-Object { $vmVmdk -notcontains $_.DatastoreFullPath }).DatastoreFullPath

   Remove-PSDrive -Name DS -Confirm:$false

   if (-not $vm -and -not $vmdk)

   {

   Get-DatastoreMountInfo -Datastore $ds

  Unmount-Datastore -Datastore $ds

  Detach-Datastore -Datastore $ds

   }

   else

   {

   Write-Host "Datastore $dsName is not empty"

   }

   }

}

Reply
0 Kudos
LucD
Leadership
Leadership

What is Get-DatastoreUnmountStatus -Datastore $ds returning?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
momox1
Contributor
Contributor

null

datastore3.png

And when I get the statusMount of the empty datastore is validating the NoVm and no Scratch

Reply
0 Kudos
LucD
Leadership
Leadership

Looks like the $ds variable is empty.

The limited output is mots probably due to the fact the the output doesn't fit on the console.

Pipe the result to Format-List.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos