14 Replies Latest reply on Apr 19, 2019 2:56 AM by LucD

    Unmount datastores if unused and dettach them based on NAA

    momox1 Novice

      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.

        • 1. Re: Unmount datastores if unused and dettach them based on NAA
          LucD Guru
          Community WarriorsUser ModeratorsvExpert

          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?

          • 2. Re: Unmount datastores if unused and dettach them based on NAA
            momox1 Novice

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

             

            Thank you

            • 3. Re: Unmount datastores if unused and dettach them based on NAA
              LucD Guru
              User ModeratorsvExpertCommunity Warriors

              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"

              }

              • 4. Re: Unmount datastores if unused and dettach them based on NAA
                momox1 Novice

                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.

                • 5. Re: Unmount datastores if unused and dettach them based on NAA
                  LucD Guru
                  vExpertUser ModeratorsCommunity Warriors

                  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"

                  }

                   

                  • 6. Re: Unmount datastores if unused and dettach them based on NAA
                    momox1 Novice

                    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

                    • 7. Re: Unmount datastores if unused and dettach them based on NAA
                      momox1 Novice

                      found it on another of your posts^^

                       

                      Thank you

                       

                      VMware PowerCLI Forum - VMware {code}

                      • 8. Re: Unmount datastores if unused and dettach them based on NAA
                        LucD Guru
                        User ModeratorsCommunity WarriorsvExpert

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

                        • 9. Re: Unmount datastores if unused and dettach them based on NAA
                          momox1 Novice

                          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

                          • 10. Re: Unmount datastores if unused and dettach them based on NAA
                            LucD Guru
                            User ModeratorsCommunity WarriorsvExpert

                            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"

                               }

                               }

                            }

                            • 11. Re: Unmount datastores if unused and dettach them based on NAA
                              momox1 Novice

                              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"

                               

                                 }

                               

                                 }

                               

                              }

                              • 12. Re: Unmount datastores if unused and dettach them based on NAA
                                LucD Guru
                                Community WarriorsvExpertUser Moderators

                                What is Get-DatastoreUnmountStatus -Datastore $ds returning?

                                • 13. Re: Unmount datastores if unused and dettach them based on NAA
                                  momox1 Novice

                                  null

                                   

                                  datastore3.png

                                   

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

                                  • 14. Re: Unmount datastores if unused and dettach them based on NAA
                                    LucD Guru
                                    User ModeratorsvExpertCommunity Warriors

                                    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.