NLVMUG 16 maart 2017
Breng jouw PowerCli script naar een hoger (sneller) niveau Bouke Groenescheij Jume BV
Bouke Groenescheij Eigenaar / Consultant / Trainer Jume BV vsphere / VRO / PowerCLI / API / DevOPS W: www.jume.nl E: bouke@jume.nl T: @boukeg F: 06-21873858
Waarom deze sessie? Versnelling van je scripts Toename in robuustheid 100% controlle over ALLE method & properties Eenvoudige vertaling andere programmeertalen Verlaging van belasting op vcenter en server/werkstation Omdat het leuk en leerzaam is
Agenda get-blabla -> get-view viewtype blabla Properties & Filters voor get-view Methods vs. Properties MoRef & vsphere API + Onyx COTL Methode Array / Hashtable Connectie naar meerdere vcenters + issues & oplossing Jobs Voorbeelden Vragen
Get-VM / Get-VMHost / Get-Cluster / Get-Folder / Get-Datacenter / Get-... Cmdlets zijn eenvoudig in gebruik, altijd volledig, leggen relaties en doen error-checking. Dat doet get-view niet!!! $vmsview = get-view -ViewType "VirtualMachine" Accepted types: ClusterComputeResource, ComputeResource, Datacenter, Datastore, DistributedVirtualPortgroup, DistributedVirtualSwitch, Folder, HostSystem, Network, OpaqueNetwork, ResourcePool, StoragePod, VirtualApp, VirtualMachine, VmwareDistributedVirtualSwitch
Get-view -Property Haalt alleen de benodigde properties op Beschikbare properties: get-view -viewtype "VirtualMachine" get-member? {$_.MemberType -eq "Property"} Properties kunnen properties bevatten
Get-view -Filter Filter op een property Op basis van @{<string>,<string>} hash Bij meerdere properties een AND Zoekterm is RegEx!!! Voorbeelden get-view -ViewType "VirtualMachine" -Filter @{"Name" = "-a"} -Filter @{"Name" = "^Photon-A5A3jILeE$"} -Filter @{"Runtime.PowerState" = "poweredoff";"runtime.host" = "host-9"} -Filter @{"Name" = "^Photon-A5A3jILeE$ ^Photon-83X9bxiv3$"}
Methods vs. Properties Properties zijn eigenschappen (waarden) Methods zijn acties get-view -viewtype "..." get-member? {$_.MemberType -eq "Method"}
Methods/Properties vs. MoRef browser (API) Methods & Properties komen grotendeels overeen met de vsphere API call Ook te zien via de MoRef Browser ALLES kan dus gedaan worden via het verkregen object met get-view!
MoRef vs. Relaties Ieder object in vcenter heeft een uniek id (MoRef) Relatie tussen de verschillende componenten is relatief met MoRef id als key Datacenter <-> Cluster <-> Host <-> VM, Folder <-> <VIObj> Kijk naar properties zoals Parent Of Child Get-View Id <MoRef>
Relatie leggen met Array vs Hashtable Array is een lijst van objecten (met properties & methods) $array = @() $array += "Eric Sloof" $array += "Bouke Groenescheij $array[0] Eric Sloof Hashtable is een key-value pair $hash = @{} $hash.add("eric","eric Sloof") $hash.add("bouke","bouke Groenescheij") $hash."bouke" Bouke Groenescheij
Kracht van hashtable Supersnel Laag resource verbruik Kan objecten bevatten (zowel key als value) Heeft unieke keys $vmsviewhash = @{} $vmsview ForEach-Object {$vmsviewhash.add($_.moref,$_)} Persoonlijk gebruik ik zo veel mogelijk hashtables!!!
COTL Collect Once Then Loop Verzamel alle data in 1 keer, hergebruik deze objecten Voorbeelden volgen
Connectie naar meerdere vcenters MoRef is uniek binnen vcenter MoRef is niet altijd uniek bij meerdere vcenters Issue met hashtable: Issue met array icm where-object Meer compare operators nodig
Oplossing voor meerdere vcenters Naar MoRef is altijd Client beschikbaar ServiceUrl gebruiken icm MoRef
Method gedrag Bij gelijkwaardige objecten in dezelfde state is de method direct beschikbaar: Niet zo: $objects % {$_.Method} Maar zo: $objects.method Als een _Task van een method beschibaar is, gebruik deze Zo: $objects.method_task Methods worden sequentieel uitgevoerd!!!
vsphere API Object inheritance vsphere API respecteert OOP Object inheritance (overerving) Check SDK Documentation: https://www.vmware.com/support/developer/vc-sdk/ Voorbeeld: $allmacs = ($thevmsview.config.hardware.device Where-Object {$_ -is [VMware.Vim.VirtualVmxnet3]}).MacAddress $allmacs = ($thevmsview.config.hardware.device Where-Object {$_ -is [VMware.Vim.VirtualEthernetCard]}).MacAddress
VIObjectByVIView $cat = Get-TagCategory "Phase" $thevmviews = get-view -ViewType "VirtualMachine" -filter @{"Name"="^Photon-29z7SnOxA$"} $thevms = $thevmviews Get-VIObjectByVIView $mytagassignment = Get-TagAssignment $thevms -Category $cat Toch een VIObject nodig voor bepaalde cmdlets?
Jobs Gebruik jobs voor parallel processing Een job draait in eigen memory space Initialiseren van PowerCLI is nodig Jobs komen met kosten (cpu / memory) Voorkeur is scripts aan te roepen vanuit scriptblock Gebruik SessionSecret om vanuit de job direct in vcenter in te loggen
foreach ($HostView in $HostsView) { $rescanjob = { Jobs if (!(Get-Module -Name VMware.VimAutomation.Core) -and (Get-Module -ListAvailable -Name VMware.VimAutomation.Core)) { } Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue connect-viserver $args[0] -session $args[1] -WarningAction:Ignore -ErrorAction:Stop out-null try { Write-Host "Info - Rescanning host: $($args[2])" $esxhostview = Get-View -ViewType "hostsystem" -Property "ConfigManager.StorageSystem" -Filter @{"Name" = "^" + $args[2] + "$"} } } } catch { } $cmss = get-view $esxhostview.configmanager.storagesystem -Property "availablefield" $cmss.rescanallhba() Write-Host "Info - Something went wrong while rescanning host: $($args[2])" Write-Host "Info - Script ended with arguments: vcenter:$($args[0]), esxhost:$($args[2])" $vcenter = ($HostView.Client.ServiceUrl).split("/")[2] $session = $HostView.Client.SessionSecret $esxhost = $HostView.Name start-job -argumentlist $vcenter,$session,$esxhost -scriptblock $rescanjob out-null
Onyx Specs kunnen lastig zijn te definieren Project Onyx helpt hierbij https://labs.vmware.com/flings/onyx-for-the-web-client
Voorbeelden get-vm one-liner naar get-view https://ict-freak.nl/2009/11/17/powercli-one-liner-to-get-vms-clusters-esxhosts-and-datastores/ Array vs. Hashtable relaties Methods Types Bonus: group-object cmdlet Job Specs: 2 vcenters, 3 hosts, 1000 VMs, 10 datastores
Get-VM Select-Object Name, ` @{N="Cluster";E={(Get-Cluster -VM $_ Select-Object "Name").Name}}, ` @{N="HAEnabled";E={(Get-Cluster -VM $_ Select-Object "HAEnabled").HAEnabled}}, ` @{N="DRSEnabled";E={(Get-Cluster -VM $_ Select-Object "DRSEnabled").DRSEnabled}}, ` @{N="ESX Host";E={(Get-VMHost -VM $_ Select-Object "Name").Name}}, ` @{N="PowerState";E={(Get-VMHost -VM $_ Select-Object "PowerState").PowerState}}, ` @{N="Model";E={(Get-VMHost -VM $_ Select-Object "Model").Model}}, ` @{N="Datastore";E={(Get-Datastore -VM $_ Select-Object "Name").Name}}, ` @{N="FreeSpaceGB";E={(Get-Datastore -VM $_ Select-Object "FreeSpaceGB").FreeSpaceGB}}, ` @{N="FileSystemVersion";E={(Get-Datastore -VM $_ Select-Object "FileSystemVersion").FileSystemVersion}} ` Export-Csv -NoTypeInformation result-langzaam.2.csv
Resultaten TotalSeconds : 520,9315386
$vmsview = get-view -ViewType "VirtualMachine" $computesview = get-view -ViewType "ComputeResource" Jobs $hostsview = get-view -viewtype "HostSystem" $datastoreview = get-view -viewtype "Datastore" $results = @() foreach ($vmview in $vmsview) { $row = "" Select-Object "Name","Cluster","HAEnabled","DRSEnabled","ESX Host","PowerState","Model","Datastore","FreeSpaceGB","FileSystemVersion" $row.name = $vmview.name $hostobj = $hostsview Where-Object {$_.MoRef -eq $vmview.runtime.host -and $_.Client.ServiceUrl -eq $vmview.client.serviceurl} $row."esx Host" = $hostobj.name $row."powerstate" = $hostobj.runtime.powerstate $row."model" = $hostobj.hardware.systeminfo.model $hostparentobj = $computesview where-object {$_.Moref -eq $hostobj.parent -and $_.Client.ServiceUrl -eq $vmview.client.serviceurl} if ($hostparentobj -is [VMware.Vim.ClusterComputeResource]) { $row.cluster = $hostparentobj.name $row.haenabled = $hostparentobj.configuration.dasconfig.enabled $row.drsenabled = $hostparentobj.configuration.drsconfig.enabled } else { $row.cluster = $null $row.haenabled = $null $row.drsenabled = $null } $datastores = @() $datastoresfree = @() $datastoresversion = @() foreach ($ds in $vmview.datastore) { $dsview = ($datastoreview where-object {$_.moref -eq $ds -and $_.Client.ServiceUrl -eq $vmview.client.serviceurl}) $datastores += $dsview.name $datastoresfree += $dsview.info.freespace / 1Gb $datastoresversion += $dsview.info.vmfs.version }
Resultaten TotalSeconds : 9,4216488 (CPU te laag om verandering te zien...) Na optimilisaties: Hashtable Beperkte Properties TotalSeconds : 1,0042037 518x sneller!!!
Bonus Group-Object $poweredon = @() $poweredoff = @() $unknown = @() foreach ($vmview in $vmsview) { if ($vmview.runtime.powerstate -eq "poweredon") { $poweredon += $vmview } elseif ($vmview.runtime.powerstate -eq "poweredoff") { $poweredoff += $vmview } else { $unknown += $vmview } }
Bonus Group-Object $vmsview = get-view -ViewType "VirtualMachine" $groupedvmsview = $vmsview Group-Object -Property {$_.Config.Template} -AsHashTable -AsString
Bonus Group-Object Met 1000 VMs weinig verschil Met 13000+ 12x sneller!
Job (master-job) $HostsView = $esxhostview = Get-View -ViewType "hostsystem" -Property "name" foreach ($HostView in $HostsView) { $rescanjob = { set-location $args[0] $scriptpath = $args[0] powershell -command "$($scriptpath)\job-slave.ps1 -vcenter $($args[1]) -session $($args[2]) -esxhost $($args[3])" } $scriptpath = split-path -parent $MyInvocation.MyCommand.Definition $vcenter = ($HostView.Client.ServiceUrl).split("/")[2] $session = $HostView.Client.SessionSecret $esxhost = $HostView.Name start-job -argumentlist $scriptpath,$vcenter,$session,$esxhost -scriptblock $rescanjob out-null }
Job (slave-job) param($vcenter,$session,$esxhost) Write-Host "Info - Script starts with arguments: vcenter:$($vcenter), esxhost:$($esxhost)" if (!(Get-Module -Name VMware.VimAutomation.Core) -and (Get-Module -ListAvailable -Name VMware.VimAutomation.Core)) { Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue } connect-viserver $vcenter -session $session -WarningAction:Ignore -ErrorAction:Stop out-null try { Write-Host "Info - Rescanning host: $($esxhost)" $esxhostview = Get-View -ViewType "hostsystem" -Property "ConfigManager.StorageSystem" -Filter @{"Name" = "^" + $esxhost + "$"} $cmss = get-view $esxhostview.configmanager.storagesystem -Property "availablefield" $cmss.rescanallhba() } catch { Write-Host "Info - Something went wrong while rescanning host: $($esxhost)" } Write-Host "Info - Script ended with arguments: vcenter:$($vcenter), esxhost:$($esxhost)"
Job (master-job) $somejobsrunning = $true do { Write-Host "Some rescan jobs are still running" Get-Job Receive-Job $jobs = Get-Job $groupedjobs = $jobs Group-Object "State" if ($groupedjobs.values.count -eq 1 -and $groupedjobs.name -eq "Completed") { $somejobsrunning = $false } Start-Sleep 1 } while ($somejobsrunning) Get-Job Receive-Job Get-Job Remove-Job
Bonus tips Check out Visual Studio Code!!! https://blogs.vmware.com/powercli/2015/02/get-view-part-1- introduction.html https://blogs.vmware.com/powercli/2015/02/get-view-part-2- views-extension-data.html https://blogs.vmware.com/powercli/2015/06/get-view-part-3- peformance-really-much-different.html
Vragen