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
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.
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.
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
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())
$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
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
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
}
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,
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
Hi LucD,
Exactly, its working now.
I really appreciate your help!
Regards,
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
}
}
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
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
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,
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
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
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!
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
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
}