VMware Cloud Community
sabmo
Enthusiast
Enthusiast

Mount Replicated LUNs

Hi Team,

I am trying to mount the replicated LUN(s) at a DR Site via PowerCLI Script. but getting some errors:

Can someone please help?

Here is the script:

#prompt for ClusterName

$cluster = Read-Host "Please enter the Cluster name"

Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba

ForEach($esx in $cluster){

      # Check for unresolved UUID

      $VMHost = Get-VMHost

      $HstSys = Get-View $esx.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

      # Resolve UUID for each on each ESXi host in the cluster

      $HstSSys = Get-view $esx.StorageInfo

      $UnresVols | %{

           $Extent = $_.Extent

           $DevicePath = $Extent.DevicePath

           $ResSpec = New-Object Vmware.Vim.HostUnresolvedVmfsResolutionSpec[](1)

           $ResSpec[0].ExtentDevicePath = $DevicePath

           $ResSpec[0].UuidResolution = “forceMount”

           $HstSSys.ResolveMultipleUnresolvedVmfsVolumes($ResSpec)

      }

      # Rescan for VMFS volumes

      #$esx | Get-VMHostStorage -RescanVmfs

   Get-VMHostStorage -VMHost $VMHost -RescanVmfs

}

Here is the output:

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is

null or empty. Supply an argument that is not null or empty and then try the

command again.

At C:\Citi_Scripts\MountLUNs.ps1:48 char:26

+       $HstSys = Get-View $esx.id

+                          ~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingVal

   idationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is

null or empty. Supply an argument that is not null or empty and then try the

command again.

At C:\Citi_Scripts\MountLUNs.ps1:49 char:28

+       $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingVal

   idationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

You cannot call a method on a null-valued expression.

At C:\Citi_Scripts\MountLUNs.ps1:50 char:22

+       $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

+                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is

null or empty. Supply an argument that is not null or empty and then try the

command again.

At C:\Citi_Scripts\MountLUNs.ps1:53 char:27

+       $HstSSys = Get-view $esx.StorageInfo

+                           ~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingVal

   idationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

Tags (3)
20 Replies
ssbkang
Enthusiast
Enthusiast

Hi,

I used to use esxcli command to mount replicated VMFS Volume, this is a simpler way of doing it.

Please do some testing before applying the script to the Production environment.

------------------------------------------------------------------------------------------------------------------------------------------------------------------

Script:

$esxcli = Get-EsxCli -VMHost (Get-VMHost -Name)

#Foreach replicated VMFS Volumes, using existing signature:

foreach ($vmfs in $esxcli.storage.vmfs.snapshot.list())

{

     $esxcli.storage.vmfs.snapshot.mount($false, $vmfs.VolumeName, $null)

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------

I suggest you to run $esxcli.storage.vmfs.snapshot.list() to see how it outputs.

From the above, I think you will be able to write up a script that meets your requirement.

Hope this helps,

Steven.

0 Kudos
Grzesiekk
Expert
Expert

you do not have $esx variable in your script.

      $VMHost = Get-VMHost

      $HstSys = Get-View $esx.id

So i guess you want to find $esx and replace it with $VMHost.

--- @blog https://grzegorzkulikowski.info
0 Kudos
sabmo
Enthusiast
Enthusiast

Hi Steven,

The irony is, we do not have a test environment where we can test this script, not sure if this would work with an iSCSI LUN.

Also, to stimulate, can we unmount the datastore and use the script to force mount it using the same signature?

The requirements are simple, need to mount the replicated volumes onto the ESXi hosts are the DR site.

Your thoughts please.

Regards,

Mohammed

0 Kudos
sabmo
Enthusiast
Enthusiast

Shouldn't it assume the $esxi variable from the foreach loop.

ForEach($esx in $cluster){

      # Check for unresolved UUID

      $VMHost = Get-VMHost

      $HstSys = Get-View $esx.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

Do you the below should work?

ForEach($esx in $cluster){

      # Check for unresolved UUID

      $VMHost = Get-Cluster $Cluster | Get-VMHost

      $HstSys = Get-View $VMHost.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

0 Kudos
Grzesiekk
Expert
Expert

$cluster = Read-Host "Please enter the Cluster name"

  Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba

This part is wrong as the $cluster is a string so

$clustername=Read-Host "Please enter the Cluster name"

$cluster=get-cluster -name $clustername

Then this loop

ForEach($esx in $cluster){

      # Check for unresolved UUID

      $VMHost = Get-VMHost

      $HstSys = Get-View $esx.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

Is still wrong as it should be

$hostsincluster=get-vmhost -Location $cluster

ForEach($esx in $hostsincluster){

      # Check for unresolved UUID

      #$VMHost = Get-VMHost  -> that is not needed as it's in the $esx now so

      $VMhost=$esx

      $HstSys = Get-View $esx.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

Greg

--- @blog https://grzegorzkulikowski.info
0 Kudos
ssbkang
Enthusiast
Enthusiast

Hi Mohammed,


It's going to work for iSCSI as you are simply mounting existing VMFS Volume (the raw disk is formatted and created as VMFS).

Unmounting won't work, I've tried this myself in the past to see if this could be tested. Eventually, I had to setup a test mirror.


I used the script above to migrate some virtual machines + DR situation, I don't see a problem with it.

I think a test mirror should be setup, no matter how the script is written, even like a 1GB of mirrored disk should be fine!


-Steven



0 Kudos
sabmo
Enthusiast
Enthusiast

Here's the updated script:

#prompt for ClusterName

$clustername = Read-Host "Please enter the Cluster name"

$cluster = Get-Cluster -name $clustername

Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba

$hostsincluster = Get-VMHost -Location $cluster

ForEach($esx in $hostsincluster){

     

   # Check for unresolved UUID

      $VMHost = $esx

      $HstSys = Get-View $esx.id

      $HstDsSys = Get-View $HstSys.ConfigManager.DatastoreSystem

      $UnresVols = @($HstDsSys.QueryUnresolvedVmfsVolumes())

      # Resolve UUID for each on each ESXi host in the cluster

   $HstSSys = Get-view $esx.StorageInfo

      $UnresVols | %{

           $Extent = $_.Extent

           $DevicePath = $Extent.DevicePath

           $ResSpec = New-Object Vmware.Vim.HostUnresolvedVmfsResolutionSpec[](1)

           $ResSpec[0].ExtentDevicePath = $DevicePath

           $ResSpec[0].UuidResolution = “forceMount”

           $HstSSys.ResolveMultipleUnresolvedVmfsVolumes($ResSpec)

      }

      # Rescan for VMFS volumes

      $VMHost | Get-VMHostStorage -RescanVmfs

  

}

0 Kudos
andysza01
Contributor
Contributor

Hi guys,

I have been using the small script listed above to mount datastores in a DR site. It has been working fine! But the problem is, the loop below will only work with one ESXi host per time, and then I need your help with a new foreach loop fuction to execute the same command listed below but in all ESXi hosts members of my cluster. I have been trying different ways but unfortunately without success.

You help is really appreciated!

$esxHosts = Get-VMHost -Location $cluster | Sort Name

foreach ($vmfs in $esxcli.storage.vmfs.snapshot.list())

{

     $esxcli.storage.vmfs.snapshot.mount($false, $vmfs.VolumeName, $null)

}

Regards,

0 Kudos
LucD
Leadership
Leadership

You mean like this

foreach($esx in (Get-VMHost -Location $cluster)){
   
$esxcli = Get-EsxCli -VMHost $esx
   
foreach ($vmfs in $esxcli.storage.vmfs.snapshot.list()){
       
$esxcli.storage.vmfs.snapshot.mount($false, $vmfs.VolumeName, $null)
    }
}


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

andysza01
Contributor
Contributor

Hi LucD,

Exactly, its working now.

I really appreciate your help!

Regards,

0 Kudos
andysza01
Contributor
Contributor

HI LuCD,

One more question if you don't mind. The same part of your code I am trying to include a foreach for ESXi Hosts as well, so in this case instead of to work with only one ESXhost the foreach would work with all ESXi hosts members of the cluster.

I have been trying to include something like:  Get-VMHost -Location $cluster | select Name, but its not woking

thank you again!

$Datastores = "prod*"

$ESXHost =

foreach($Datastore in Get-Datastore $Datastores) {

   # Set up Search for .VMX Files in Datastore

   $ds = Get-Datastore -Name $Datastore | %{Get-View $_.Id}

   $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec

   $SearchSpec.matchpattern = "*.vmx"

   $dsBrowser = Get-View $ds.browser

   $DatastorePath = "[" + $ds.Summary.Name + "]"

   # Find all .VMX file paths in Datastore, filtering out ones with .snapshot (Useful for NetApp NFS)

   $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path}

   #Register all .vmx Files as VMs on the datastore

   foreach($VMXFile in $SearchResult) {

      New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync

   }

}

0 Kudos
LucD
Leadership
Leadership

This line

foreach($esx in (Get-VMHost -Location $cluster)){

already loops through all the ESXi hosts in the cluster.


Or do you mean something else ?


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

0 Kudos
andysza01
Contributor
Contributor

Hi LucD,

The foreach($esx in (Get-VMHost -Location $cluster)){ for the first question is working fine and all datastores are up and running. Now, I am trying to add all VMs to the inventory using the script listed below. This script used to work in a non-cluster environment, but now I am getting weird errors... 


$Datastores = "prod*"

$ESXHost = Get-VMHost -Location $cluster | select -First 1

$VMFolder = “dr01”

 

foreach($Datastore in Get-Datastore $Datastores) {

   # Set up Search for .VMX Files in Datastore

   $ds = Get-Datastore -Name $Datastore | %{Get-View $_.Id}

   $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec

   $SearchSpec.matchpattern = "*.vmx"

   $dsBrowser = Get-View $ds.browser

   $DatastorePath = "[" + $ds.Summary.Name + "]"

   # Find all .VMX file paths in Datastore, filtering out ones with .snapshot (Useful for NetApp NFS)

   $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path}

   #Register all .vmx Files as VMs on the datastore

   foreach($VMXFile in $SearchResult) {

      New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync

   }

}

ERROR:

New-VM : Cannot validate argument on parameter 'VMFilePath'. The argument is nu

ll or empty. Supply an argument that is not null or empty and then try the comm

and again.

At C:\Users\test\Desktop\VMware DR\loop_foreach.ps1:20 char:25

+       New-VM -VMFilePath <<<<  $VMXFile -VMHost $ESXHost -Location $VMFolder

-RunAsync

    + CategoryInfo          : InvalidData: (:) [New-VM], ParameterBindingValid

   ationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.NewVM

0 Kudos
andysza01
Contributor
Contributor

Hi LucD,

I got it. it was a wrong command/information that I was passing to the VMFolder variable.

Everything is green! up and running.

thank you again for you answers!

Regards,

0 Kudos
LucD
Leadership
Leadership

Does this mean that you have datastores that are not shared between all the nodes in that cluster ?

Otherwise only 1 node should be sufficient.

You could also try the slightly different version from my VMX Raiders Revisited post.


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

andysza01
Contributor
Contributor

Hi LucD,

I do have datastores shared between all the nodes in the cluster and one node is sufficient to boot all VMs.

Thank you for sharing the VMX Raiders Revisited, its great and is working fine.

Thank you again!

Regards

Andy

0 Kudos
andysza01
Contributor
Contributor

Hi LucD,

I have a quick question. As part of this script I am looking for a way to use get-view in combination with get-datastore to search for VMFS datastore status.

I am working with this great script as found here in our community. This script will mount all datastores, but I am looking for a way to include an if/else statement to check the status of the datastore. So, if the datastore is mounted jump to another part of the code, if not run the Function Mount-Datastore listed below.

Function Mount-Datastore {

        [CmdletBinding()]

        Param (

                [Parameter(ValueFromPipeline=$true)]

                $Datastore

        )

        Process {

                if (-not $Datastore) {

                        Write-Host "No Datastore defined as input"

                        Break

                } else {

                        Foreach ($ds in $Datastore) {

                                $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

                                if ($ds.ExtensionData.Host) {

                                        $attachedHosts = $ds.ExtensionData.Host

                                        Foreach ($VMHost in $attachedHosts) {

                                                $hostview = Get-View $VMHost.Key

                                                $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

                                                Write-Host "Mounting VMFS Datastore $($DS.Name) on host $($hostview.Name)..."

                                                $StorageSys.MountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);

                                        }

                                }

                        }

                }

        }

}

Get-Datastore $Datastores | Mount-Datastore

}

else {

    Write-Host "The VMware Datastores $Datastores already are mounted!." -ForegroundColor Green

}

thanks for your help!

0 Kudos
LucD
Leadership
Leadership

Have a look at William's post called Automating Datastore/Storage Device Detachment in vSphere 5.

With the Get-DatastoreMountInfo function in there you easily check on the mount status of a datastore.


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

0 Kudos
andysza01
Contributor
Contributor

Hi LucD, Sure.

I have combined those nice scripts and included more filters on at... Now ,I am getting the status of each datastore (if they are mounted or not). So, I am looking for a simple if/else statement that will mount all datastores with "false" output. For example, if "False" mount them, if not jump to another part of the script...

See below. thank you for your help

$Datastores = Get-Datastore | where {$_.Type -eq "VMFS"} | Select Name,@{N="NAA";E={$_.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName}} | Where-Object {$_.NAA -like "naa.*"}  | Select -ExpandProperty Name | sort Name

if ($Datastores -eq $null) {

Function Mount-Datastore {

        [CmdletBinding()]

        Param (

                [Parameter(ValueFromPipeline=$true)]

                $Datastore

        )

        Process {

                if (-not $Datastore) {

                        Write-Host "No Datastore defined as input"

                        Break

                } else {

                        Foreach ($ds in $Datastore) {

                                $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

                                if ($ds.ExtensionData.Host) {

                                        $attachedHosts = $ds.ExtensionData.Host

                                        Foreach ($VMHost in $attachedHosts) {

                                                $hostview = Get-View $VMHost.Key

                                                $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

                                                Write-Host "Mounting VMFS Datastore $($DS.Name) on host $($hostview.Name)..."

                                                $StorageSys.MountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);

                                        }

                                }

                        }

                }

        }

}

Get-Datastore $Datastores | Mount-Datastore

} else {

Function Get-DatastoreMountInfo {

    [CmdletBinding()]

    Param (

        [Parameter(ValueFromPipeline=$true)]

        $Datastore

    )

    Process {

        $AllInfo = @()

        if (-not $Datastore) {

            $Datastore = Get-Datastore

        }

        Foreach ($ds in $Datastore) { 

            if ($ds.ExtensionData.info.Vmfs) {

                $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].diskname

                if ($ds.ExtensionData.Host) {

                    $attachedHosts = $ds.ExtensionData.Host

                    Foreach ($VMHost in $attachedHosts) {

                        $hostview = Get-View $VMHost.Key

                        $hostviewDSState = $VMHost.MountInfo.Mounted

                        $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

                        $devices = $StorageSys.StorageDeviceInfo.ScsiLun

                        Foreach ($device in $devices) {

                            $Info = "" | Select Datastore, VMHost, Lun, Mounted, State

                            if ($device.canonicalName -eq $hostviewDSDiskName) {

                                $hostviewDSAttachState = ""

                                if ($device.operationalState[0] -eq "ok") {

                                    $hostviewDSAttachState = "Attached"                           

                                } elseif ($device.operationalState[0] -eq "off") {

                                    $hostviewDSAttachState = "Detached"                           

                                } else {

                                    $hostviewDSAttachState = $device.operationalstate[0]

                                }

                                $Info.Datastore = $ds.Name

                                $Info.Lun = $hostviewDSDiskName

                                $Info.VMHost = $hostview.Name

                                $Info.Mounted = $HostViewDSState

                                $Info.State = $hostviewDSAttachState

                                $AllInfo += $Info

                            }

                        }

                       

                    }

                }

            }

        }

        $AllInfo

    }

}

Get-Datastore $Datastores | Get-DatastoreMountInfo | Select -ExpandProperty Mounted

}

pastedImage_4.png

0 Kudos