Hello,
I need some help writing a script to rename vm's and change the network connection to the correct vlan, based on input of a csv file. Only the vm display name in vcenter needs to be changed (vmdk's will be renamed aftwards by peforming a svmotion)
csv will look like this:
oldname,newname,tobevlan
vm1,tag-vm1,vlan4
vm2,tag-vm2,vlan7
vm3,tag-vm3,vlan4
I'm already using LucD's script to import vm's based on a csv. Now I need to add this part the to script. I need to import a large number of vm's place on a few datastores. There are some vm's that don't need to be imported, so I use a csv to import only the needed one's. After the registration of the vm's, they all need to be renamed and network connection should be changed.
Thanks for your help.
Regards,
Christophe
You can try something like this
############################################################################################################################### # CSV file layout # # VMXPath,oldname,newname,vlan # "[ds] VM1/VM1.vmx",VM1,newVM1,net1 # "[ds] VM2/VM2.vmx",VM2,newVM2,net2 # "[ds] VM3/VM3.vmx",VM3,newVM3,net3 # "[ds] VM4/VM4.vmx",VM4,newVM4,net4 # ############################################################################################################################### $vms = Import-Csv D:\temp\import-vm.csv -UseCulture
$targetVMX = $vms | Select -ExpandProperty VMXPath
$Cluster = "CLUSTER_01"
$Datastores = "*_DATASTORE"
$VMFolder = "TESTFOLDER"
$ResourcePool = "TestRP"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | Get-Random
foreach($Datastore in Get-Datastore $Datastores) { # 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 $VMFolder -ResourcePool $ResourcePool -RunAsync
} } } foreach($vm in $vms){ Get-VM $($vm.oldname) | Set-vm -name $($vm.newname) -confirm:$false | Get-NetworkAdapter | Set-NetworkAdapter -Networkname $($vm.vlan) -confirm:$false
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
At the very core/basic level
get-vm oldname | set-vm -name newname
Did you need help getting the info from the csv... or is the above good for what you need?
I actually need help from getting the info from the csv.
I know this is the command to change the name: get-vm oldname | set-vm -name newname
But I need a script that reads the complete cvs and change all the vm names.
It would look something like this
$csv=Import-CSV "csvname"
FOREACH ($row in $csv)
{ Get-VM $($row.oldname) | Set-vm -name $($row.newname) -confirm:$false }
Something like that...You should definitely test with a small csv first to make sure it does what you want.. there some adjustments to it that could be made for speed, but this should do the job.
Thank you very much. This works. Now I can continue working on my script to integrate this part.
Can I add Set-NetworkAdapter -NetworkName in the same line?
Like this?
FOREACH ($row in $csv)
{ Get-VM $($row.oldname) | Set-vm -name $($row.newname) | Set-NetworkAdapter -Networkname $($row.tobevlan) -confirm:$false
}
Is this correct?
I think it should work but with a slight modification
{ Get-VM $($row.oldname) | Set-vm -name $($row.newname) | Get-NetworkAdapter | Set-NetworkAdapter -Networkname $($row.tobevlan) -confirm:$false
}
Thanks again CRAD14 for your help.
I now have one script that adds vm's to the vCenter inventory with info from a CSV (thank you LucD for the script)
###############################################################################################################################
$targetVMX = Get-Content D:\temp\import-vm.csv
$Cluster = "CLUSTER_01"
$Datastores = "*_DATASTORE"
$VMFolder = "TESTFOLDER"
$ResourcePool = "TestRP"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | Get-Random
foreach($Datastore in Get-Datastore $Datastores) {
# 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 $VMFolder -ResourcePool $ResourcePool -RunAsync
}
}
}
###############################################################################################################################
import-vm.csv content:
[01_DATASTORE] TESTVM03/TESTVM03.vmx
[02_DATASTORE] TESTVM02/TESTVM02.vmx
[03_DATASTORE] TESTVM01/TESTVM01.vmx
And I have another script that changes the display name of the vm with info from another CSV (thank you CRAD14 for the script)
###############################################################################################################################
$csv=Import-CSV "d:\temp\renamevm.csv"
FOREACH ($row in $csv)
{ Get-VM $($row.oldname) | Set-vm -name $($row.newname) -confirm:$false | Get-NetworkAdapter | Set-NetworkAdapter -Networkname $($row.vlan) -confirm:$false
}
###############################################################################################################################
renamevm.csv content:
oldname,newname,vlan
TESTVM01,sn123-TESTVM01,Testvlan1
TESTVM02,sn124-TESTVM02,Testvlan3
TESTVM03,sn125-TESTVM03,Testvlan5
Is it possible to combine both scripts into one script and using only one CSV-file?
The goal of this script is to register a number of vm's, change the display name and network with info from just one CSV-file.
If you have all the data in one csv, you could honestly, just place all the code in one ps1 file and run it.
I'm struggling with this because I don't have a header in the first CSV file. If I add a header for the vmx path, what do I have to change so that
foreach($VMXFile in $SearchResult) {
if($targetVMX -contains $VMXFile){.................
keeps working?
Essentially...
The way that the first script calls the csv, with the get-content, you should be fine to add the headers and pretty much anything else you want
if i add anything to the first CSV, the first script won't run
for example: if i add, oldname,newname,vlan behind the vmx in the CSV, the script will only add the vmx without anything behind it to the inventory
[01_DATASTORE] TESTVM03/TESTVM03.vmx,TESTVM03,sn123-TESTV03,vlan5
[02_DATASTORE] TESTVM02/TESTVM02.vmx
[03_DATASTORE] TESTVM01/TESTVM01.vmx
You can try something like this
############################################################################################################################### # CSV file layout # # VMXPath,oldname,newname,vlan # "[ds] VM1/VM1.vmx",VM1,newVM1,net1 # "[ds] VM2/VM2.vmx",VM2,newVM2,net2 # "[ds] VM3/VM3.vmx",VM3,newVM3,net3 # "[ds] VM4/VM4.vmx",VM4,newVM4,net4 # ############################################################################################################################### $vms = Import-Csv D:\temp\import-vm.csv -UseCulture
$targetVMX = $vms | Select -ExpandProperty VMXPath
$Cluster = "CLUSTER_01"
$Datastores = "*_DATASTORE"
$VMFolder = "TESTFOLDER"
$ResourcePool = "TestRP"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | Get-Random
foreach($Datastore in Get-Datastore $Datastores) { # 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 $VMFolder -ResourcePool $ResourcePool -RunAsync
} } } foreach($vm in $vms){ Get-VM $($vm.oldname) | Set-vm -name $($vm.newname) -confirm:$false | Get-NetworkAdapter | Set-NetworkAdapter -Networkname $($vm.vlan) -confirm:$false
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hello Luc, thanks for your reply.
When I try your solution, I get the following error: Select-Object : property "VMXPath" cannot be found....
Apparently there's an issue with $targetVMX = $vms | Select -ExpandProperty VMXPath
any ideas?
Did you follow the layout of the CSV file as I placed in the comments on top ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
yes the layout is the same.
when I run $csv = Import-csv D:\temp\import-vm3.csv -UseCulture
i get this error:
Import-Csv : Cannot process argument because the value of argument "name" is invalid. Change the value of the "name" ar
gument and run the operation again.
At line:1 char:18
+ $csv = Import-csv <<<< D:\temp\import-vm3.csv -UseCulture
+ CategoryInfo : InvalidArgument: (:) [Import-Csv], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.ImportCsvCommand
It must have something to do with delimiters or blanks??
Does that CSV file exist ?
Does
Import-csv D:\temp\import-vm3.csv
return all the rows in the CSV file ?
Can you show the content of the CSV file ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
yes the CSV exists (i created a new one for testing)
import-csv D:\temp\import-vm3.csv returns all row of the CSV:
VMXPath oldname newname vlan
------- ------- ------- ----
[02_DATASTORE] Empty2/Empt... Empty2 100-Empty2 vlan1
[03_DATASTORE] Empty3/Empt... Empty3 101-Empty3 vlan1
[03_DATASTORE] Empty4/Empt... Empty4 102-Empty4 vlan2
[02_DATASTORE] Empty5/Empt... Empty5 103-Empty5 vlan1
Content of CSV:
VMXPath,oldname,newname,vlan
"[02_DATASTORE] Empty2/Empty2.vmx",Empty2,100-Empty2,vlan1
"[03_DATASTORE] Empty3/Empty3.vmx",Empty3,101-Empty3,vlan1
"[03_DATASTORE] Empty4/Empty4.vmx",Empty4,102-Empty4,vlan2
"[02_DATASTORE] Empty5/Empty5.vmx",Empty5,103-Empty5,vlan1
Import-Csv : Cannot process argument because the value of argument "name" is invalid. Change the value of the "name" ar
gument and run the operation again.
was caused by a blank line in the CSV.
When i run the script now i still get this error:
Select-Object : Property "VMXPath" cannot be found.
At line:1 char:27
+ $targetVMX = $csv | select <<<< -ExpandProperty VMXPath
+ CategoryInfo : InvalidArgument: (@{VMXPath,oldna...x-Empty2,Delta}:PSObject) [Select-Object], PSArgumen
tException
+ FullyQualifiedErrorId : ExpandPropertyNotFound,Microsoft.PowerShell.Commands.SelectObjectCommand
In my script that line said
$targetVMX = $vms | select -ExpandProperty VMXPath
Did you change the first line (the one with the Import-Csv) as well ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
does it matter if i use $vms or $csv? as long as I use everywhere in the script...