Hi to all the scripting guru's out there,
I'm putting together a DR solution for our VM's, we are currently using the IBM Storwize V7000 with Remote Copy to replicate some Datastores.
Now I have done some extensive testing and found that when you perform a switch from PROD to DR there is a a bit of a process to get the VM's up and running.
1. I have to do a full rescan of the HBAs. Under storage adapters you can see the assigned storage devices as mounted, however you still need to go to Storage and go the the "Add Storage" wizard to readd the Datastore with the option resignaturing the volume. So this part isn't so painful except it appends a different naming convention to the datastore name, example a datastore named prd_lun100 gets named snap-5a18365a-prd_lun100 so I have to rename the datastore back to the default.
2. I have to go through the datastores and add every virtual machine into inventory which is very tedious, and the very part I need to automate.
I tried this one liner, which I found here -> http://www.wooditwork.com/2011/08/11/adding-vmx-files-to-vcenter-inventory-with-powercli-gets-even-e...
New
-VM
-VMFilePath
"[prd_lun100] SERVER01/SERVER01.vmx"
-VMHost
"VMHost01.local"
If possible I would like to expand on this, in the following ways:
1. Automate adding the datastores with the correct naming convention, by using either the naa identifier of the LUN or LUN ID#, possibly pull this info from a CSV list.
2. Add VM as per the one liner above but from a CSV list of some sort, however add is to a DRS Cluster rather ESXi Host, if possible prioritize adding VMs by some sort of groups flag in the CSV.
3. Power on VMs based on a priority.
I would really really appreciate if some one can help with this, I know probably a big ask, but scripting is not my forte and wouldn't know where to start.
That shouldn't be too difficult.
Read the filenames from a CSV file and then check for each VMX file you find if it is in the list.
Something like this
$targetVMX = Import-Csv C:\vmxnames.csv -UseCulture
$Cluster = "LON_PROD1"
$Datastores = "lonservers*"
$VMFolder = "LondonAppServers"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1
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) { if($targetVMX -contains $VMXFile){ New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $Folder -RunAsync
} } }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
OK so I test this which works well, but if someone can help with modifying it so it pulls the VMX info from a list would suite me better
$Cluster
=
"LON_PROD1"
$Datastores
=
"lonservers*"
$VMFolder
=
"LondonAppServers"
$ESXHost
= Get
-Cluster
$Cluster
| Get
-VMHost
|
select
-First
1
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
$Folder
-RunAsync
}
}
What exactly do you mean by pulling the VMX info from a list ?
Do you want to provide a list of VM names and only register the corresponding VMX files ?
Note that this will only work if the DisplayName in the VMX is the same as the filename of the VMX file.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
Thanks for your reponse, yes was thinking a list like
List
[V7K_LUN60] SRV102/SRV102.vmx
That shouldn't be too difficult.
Read the filenames from a CSV file and then check for each VMX file you find if it is in the list.
Something like this
$targetVMX = Import-Csv C:\vmxnames.csv -UseCulture
$Cluster = "LON_PROD1"
$Datastores = "lonservers*"
$VMFolder = "LondonAppServers"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1
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) { if($targetVMX -contains $VMXFile){ New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $Folder -RunAsync
} } }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc,
Would posible to have the VMs power on in the same script or would have to have 2 script and run it after this one completes?
I need to be able to power on and answer the question about keeping the UUID
If you remove the RunAsync parameter on the New-VM cmdlet, you should be able to insert your 2 lines to start and asnwer in the same block.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc, I will gave that a try.
Sorry just one more dumb question, I tried the CSV list modified script but it didnt work, its possible the CSV is formatted in the correct way, do mind explaining how should be?
The blank in the VMX filename probably causes a problem.
Use the Get-Content cmdlet instead, like this
$targetVMX = Get-Content C:\vmxnames.csv
The rest of the script should stay the same
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks again, I will give that a try
Hi Luc,
I must not be creating the CSV list correctly, it doesn't do anything. On the other hand the other script which adds all vms from specified datastores works well, I have even appended the start-vm and answer question as you suggested. but some reason i get some errors in the task list, it does work but wondering if the script requires some tweaks, please see screenshot. I have attached both scripts as well.
Could it be that some of these VMs are already powered on ?
That's what the error seems to suggest.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
No I'm testing it on 5 vms, each time it test it I power them off and remove it from inventory.
Are the Tasks in the screenshot from 1 run of the script ?
I see the same VM being powered on multiple times.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
Yes I just run the script once, it appears to be trying to start a vm that is already in the process of powering on.
Sent from my iPhone
There seem to be several errors that appear.
Is the script you are using the one you included in a previous post ?
Otherwise attach the latest version.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
I actually power off and unregister all the vm's NSTESTPC, SRV100, SRV101, SRV102, SRV103 prior to running the script. I even browse the datastore move those VM's into another directory, to simulate the question. I have attached the script in this post.
What I thisk would be good is registering and powering on VMs based on a list, that way I can group the powering on of VM based on priority, im not sure if that would be easier. i just don't understand why it work but shows errors.
You were retrieving all the VMs in that folder, not just the VM you just registered.
Try it like this (I made some other changes as well)
$Cluster = "V7000 Cluster"
$Datastores = get-datastore snap*$DatastoreNames*
$VMFolder = "DR_Folder"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1
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) { $vm = New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder
if($vm.PowerState -ne "PoweredOn"){ $vm = Start-VM -VM $vm
} while($vm.PowerState -ne "PoweredOn"){ sleep 5
$vm = Get-VM $vm.Name
} Get-VMQuestion -VM $vm | Set-VMQuestion -Option "I moved it" -Confirm:$false
} } }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
Thanks for your time with this, I wish there were some way I could repay you??
Anyway the last script doesn't run, I get the following error. Also just to clarify does $VMFolder specify what folder in the inventory to add the VM to?
PowerCLI C:\scripts> .\poor-man-SRM.ps1