Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten 

Fréier oder spéider kënnt all VMware System Administrateur fir Routine Aufgaben ze automatiséieren. Et fänkt alles mat der Kommandozeil un, da kënnt PowerShell oder VMware PowerCLI.

Loosst eis soen datt Dir PowerShell e bësse méi wäit beherrscht hutt wéi ISE ze lancéieren an Standard cmdlets vu Moduler ze benotzen déi funktionnéieren wéinst "eng Aart vu Magie". Wann Dir ufänkt virtuell Maschinnen an Honnerte ze zielen, fannt Dir datt Skripte, déi op enger klenger Skala hëllefen, merkbar méi lues op enger grousser Skala lafen. 

An dëser Situatioun wäerten 2 Tools hëllefen:

  • PowerShell Runspaces - eng Approche déi Iech erlaabt d'Ausféierung vu Prozesser an getrennten thread ze paralleliséieren; 
  • Get-View - eng Basis PowerCLI Funktioun, en Analog vu Get-WMIObject a Windows. Dëst cmdlet zitt net Objete begleet Entitéite, mee kritt Informatiounen a Form vun engem einfachen Objet mat einfachen Daten Zorte. A ville Fäll kënnt et méi séier eraus.

Als nächst wäert ech kuerz iwwer all Tool schwätzen a Beispiller vu Gebrauch weisen. Loosst eis spezifesch Scripten analyséieren a kucken wéini dat eent besser funktionnéiert wéi dat anert. Gitt!

Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten

Éischt Etapp: Runspace

Also, Runspace ass fir parallel Veraarbechtung vun Aufgaben ausserhalb vum Haaptmodul entworf. Natierlech kënnt Dir en anere Prozess starten, deen e bësse Gedächtnis, Prozessor, asw. Awer fir Scripte fir zéngdausende vun Objeten ass et néideg.

Dir kënnt hei ufänken ze léieren: 
Ufank vun der Benotzung vu PowerShell Runspaces: Deel 1

Wat gëtt d'Benotzung vun Runspace:

  • Geschwindegkeet andeems d'Lëscht vun ausgefouerten Kommandoen limitéiert ass,
  • parallel Ausféierung vun Aufgaben,
  • Sécherheet.

Hei ass e Beispill vum Internet wann Runspace hëlleft:

"Storage Contestatioun ass eng vun den haardsten Metriken fir a vSphere ze verfolgen. Bannen vCenter kënnt Dir net just goen a kucken wéi eng VM méi Späicherressourcen verbraucht. Glécklecherweis kënnt Dir dës Donnéeën a Minutte sammelen dank PowerShell.
Ech wäert e Skript deelen, deen VMware System Administrateuren erlaabt séier uechter vCenter ze sichen an eng Lëscht vu VMs mat Daten iwwer hiren Duerchschnëttsverbrauch ze kréien.  
D'Schrëft benotzt PowerShell Runspaces fir all ESXi Host fir Konsuminformatioun vu sengen eegene VMs an engem separaten Runspace ze sammelen an direkt d'Réalisatioun ze berichten. Dëst erlaabt PowerShell Aarbechtsplazen direkt zouzemaachen, anstatt duerch Hosten ze iteréieren an op jidderee waart fir seng Ufro ofzeschléissen.

Source: Wéi Virtuell Maschinn I / O op engem ESXi Dashboard ze weisen

Am Fall hei drënner ass Runspace net méi nëtzlech:

"Ech probéieren e Skript ze schreiwen, dee vill Daten aus engem VM sammelt an nei Donnéeën schreift wann néideg. De Problem ass datt et zimmlech vill VMs sinn, a 5-8 Sekonnen ginn op enger Maschinn verbruecht. 

Source: Multithreading PowerCLI mat RunspacePool

Hei braucht Dir Get-View, loosst eis weidergoen. 

Zweet Etapp: Get-View

Fir ze verstoen firwat Get-View nëtzlech ass, ass et derwäert ze erënneren wéi cmdlets allgemeng funktionnéieren. 

Cmdlets sinn néideg fir bequem Informatiounen ze kréien ouni de Besoin API Referenz Bicher ze studéieren an déi nächst Rad nei erfannen. Wat an den alen Deeg honnert oder zwee Zeilen Code geholl huet, PowerShell erlaabt Iech mat engem Kommando ze maachen. Mir bezuelen fir dës Kamoudheet mat Vitesse. Et gëtt keng Magie an de cmdlets selwer: datselwecht Skript, awer op engem nidderegen Niveau, geschriwwen vun de kompetente Hänn vun engem Meeschter aus sonnegen Indien.

Elo, zum Verglach mam Get-View, loosst eis de Get-VM cmdlet huelen: et gëtt Zougang zu der virtueller Maschinn a bréngt e kompositen Objet zréck, dat heescht, et befestegt aner verwandte Objekter un: VMHost, Datastore, etc.  

Get-View op senger Plaz füügt näischt onnéideg un de zréckginn Objet. Ausserdeem erlaabt et eis strikt ze spezifizéieren wéi eng Informatioun mir brauchen, wat den Outputobjekt méi einfach mécht. Am Windows Server am Allgemengen an am Hyper-V besonnesch ass de Get-WMIObject cmdlet en direkten Analog - d'Iddi ass genau d'selwecht.

Get-View ass onbequem fir Routine Operatiounen op Punktobjekter. Mä wann et drëms geet, fir dausende an zéngdausende vun Objeten, et huet kee Präis.

Dir kënnt méi am VMware Blog liesen: Aféierung fir Get-View

Elo weisen ech Iech alles mat engem richtege Fall. 

Schreift e Skript fir e VM ze lueden

Enges Daags huet mäi Kolleg mech gefrot fir säi Skript ze optimiséieren. D'Aufgab ass eng gemeinsam Routine: Fannt all VMs mat engem duplizéierte Cloud.uuid Parameter (jo, dëst ass méiglech wann Dir e VM am vCloud Director klonet). 

Déi offensichtlech Léisung déi am Kapp kënnt ass:

  1. Kritt eng Lëscht vun all VMs.
  2. Parse d'Lëscht iergendwéi.

D'Original Versioun war dëst einfach Skript:

function Get-CloudUUID1 {
   # Получаем список всех ВМ
   $vms = Get-VM
   $report = @()

   # Обрабатываем каждый объект, получая из него только 2 свойства: Имя ВМ и Cloud UUID.
   # Заносим данные в новый PS-объект с полями VM и UUID
   foreach ($vm in $vms)
   {
       $table = "" | select VM,UUID

       $table.VM = $vm.name
       $table.UUID = ($vm | Get-AdvancedSetting -Name cloud.uuid).Value
          
       $report += $table
   }
# Возвращаем все объекты
   $report
}
# Далее РУКАМИ парсим полученный результат

Alles ass extrem einfach a kloer. Et kann an e puer Minutten mat enger Kaffispaus geschriwwe ginn. Schrauwen d'Filtratioun an et ass fäerdeg.

Mee loosst eis d'Zäit moossen:

Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten

Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten

2 Minutten 47 Sekonnen wann Dir bal 10k VMs veraarbecht. E Bonus ass d'Feele vu Filteren an de Besoin fir d'Resultater manuell ze sortéieren. Natierlech erfuerdert de Skript Optimisatioun.

Runspaces sinn déi éischt fir d'Rettung ze kommen, wann Dir gläichzäiteg Host-Metriken vu vCenter musst kréien oder Zéngdausende vun Objete veraarbechten. Loosst eis kucken wat dës Approche bréngt.

Maacht déi éischt Geschwindegkeet un: PowerShell Runspaces

Déi éischt Saach, déi fir dëst Skript am Kapp kënnt ass d'Loop net sequenziell auszeféieren, awer a parallele thread, all d'Donnéeën an een Objet sammelen a filteren. 

Awer et gëtt e Problem: PowerCLI erlaabt eis net vill onofhängeg Sessiounen op vCenter opzemaachen a wäert e witzege Feeler werfen:

You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server.

Fir dëst ze léisen, musst Dir als éischt Sessiounsinformatioun am Stream passéieren. Loosst eis drun erënneren datt PowerShell mat Objekter funktionnéiert déi als Parameter entweder un eng Funktioun oder un e ScriptBlock weidergeleet kënne ginn. Loosst eis d'Sessioun a Form vun esou engem Objet passéieren, $global:DefaultVIServers ëmgoen (Connect-VIServer mam -NotDefault Schlëssel):

$ConnectionString = @()
foreach ($vCenter in $vCenters)
   {
       try {
           $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -AllLinked -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
       }
       catch {
           if ($er.Message -like "*not part of a linked mode*")
           {
               try {
                   $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
               }
               catch {
                   throw $_
               }
              
           }
           else {
               throw $_
           }
       }
   }

Loosst eis elo Multithreading duerch Runspace Pools implementéieren.  

Den Algorithmus ass wéi follegt:

  1. Mir kréien eng Lëscht vun all VMs.
  2. Parallel Baachen kréie mir Wollek.uuid.
  3. Mir sammelen Daten aus Streamen an een Objet.
  4. Mir filteren den Objet andeems Dir et nom Wäert vum CloudUUID Feld gruppéiert: déi wou d'Zuel vun eenzegaartege Wäerter méi wéi 1 ass, sinn d'VMs déi mir sichen.

Als Resultat kréien mir de Skript:


function Get-VMCloudUUID {
   param (
       [string[]]
       [ValidateNotNullOrEmpty()]
       $vCenters = @(),
       [int]$MaxThreads,
       [System.Management.Automation.PSCredential]
       [System.Management.Automation.Credential()]
       $Credential
   )

   $ConnectionString = @()

   # Создаем объект с сессионным ключом
   foreach ($vCenter in $vCenters)
   {
       try {
           $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -AllLinked -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
       }
       catch {
           if ($er.Message -like "*not part of a linked mode*")
           {
               try {
                   $ConnectionString += Connect-VIServer -Server $vCenter -Credential $Credential -NotDefault -Force -ErrorAction stop -WarningAction SilentlyContinue -ErrorVariable er
               }
               catch {
                   throw $_
               }
              
           }
           else {
               throw $_
           }
       }
   }

   # Получаем список всех ВМ
   $Global:AllVMs = Get-VM -Server $ConnectionString

   # Поехали!
   $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
   $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
   $RunspacePool.ApartmentState = "MTA"
   $RunspacePool.Open()
   $Jobs = @()

# ScriptBlock с магией!)))
# Именно он будет выполняться в потоке
   $scriptblock = {
       Param (
       $ConnectionString,
       $VM
       )

       $Data = $VM | Get-AdvancedSetting -Name Cloud.uuid -Server $ConnectionString | Select-Object @{N="VMName";E={$_.Entity.Name}},@{N="CloudUUID";E={$_.Value}},@{N="PowerState";E={$_.Entity.PowerState}}

       return $Data
   }
# Генерируем потоки

   foreach($VM in $AllVMs)
   {
       $PowershellThread = [PowerShell]::Create()
# Добавляем скрипт
       $null = $PowershellThread.AddScript($scriptblock)
# И объекты, которые передадим в качестве параметров скрипту
       $null = $PowershellThread.AddArgument($ConnectionString)
       $null = $PowershellThread.AddArgument($VM)
       $PowershellThread.RunspacePool = $RunspacePool
       $Handle = $PowershellThread.BeginInvoke()
       $Job = "" | Select-Object Handle, Thread, object
       $Job.Handle = $Handle
       $Job.Thread = $PowershellThread
       $Job.Object = $VM.ToString()
       $Jobs += $Job
   }

# Ставим градусник, чтобы наглядно отслеживать выполнение заданий
# И здесь же прибиваем отработавшие задания
   While (@($Jobs | Where-Object {$_.Handle -ne $Null}).count -gt 0)
   {
       $Remaining = "$($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).object)"

       If ($Remaining.Length -gt 60) {
           $Remaining = $Remaining.Substring(0,60) + "..."
       }

       Write-Progress -Activity "Waiting for Jobs - $($MaxThreads - $($RunspacePool.GetAvailableRunspaces())) of $MaxThreads threads running" -PercentComplete (($Jobs.count - $($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).count)) / $Jobs.Count * 100) -Status "$(@($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False})).count) remaining - $remaining"

       ForEach ($Job in $($Jobs | Where-Object {$_.Handle.IsCompleted -eq $True})){
           $Job.Thread.EndInvoke($Job.Handle)     
           $Job.Thread.Dispose()
           $Job.Thread = $Null
           $Job.Handle = $Null
       }
   }

   $RunspacePool.Close() | Out-Null
   $RunspacePool.Dispose() | Out-Null
}


function Get-CloudUUID2
{
   [CmdletBinding()]
   param(
   [string[]]
   [ValidateNotNullOrEmpty()]
   $vCenters = @(),
   [int]$MaxThreads = 50,
   [System.Management.Automation.PSCredential]
   [System.Management.Automation.Credential()]
   $Credential)

   if(!$Credential)
   {
       $Credential = Get-Credential -Message "Please enter vCenter credentials."
   }

   # Вызов функции Get-VMCloudUUID, где мы распараллеливаем операцию
   $AllCloudVMs = Get-VMCloudUUID -vCenters $vCenters -MaxThreads $MaxThreads -Credential $Credential
   $Result = $AllCloudVMs | Sort-Object Value | Group-Object -Property CloudUUID | Where-Object -FilterScript {$_.Count -gt 1} | Select-Object -ExpandProperty Group
   $Result
}

D'Schéinheet vun dësem Skript ass datt et an anere ähnleche Fäll benotzt ka ginn andeems Dir de ScriptBlock an d'Parameteren einfach ersetzt, déi an de Stroum weidergeleet ginn. Ausnotzen et!

Mir moossen Zäit:

Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten

55 Sekonnen. Et ass besser, awer et kann ëmmer méi séier sinn. 

Loosst eis op déi zweet Geschwindegkeet goen: GetView

Loosst eis erausfannen wat falsch ass.
Éischtens a virun allem hëlt de Get-VM cmdlet eng laang Zäit fir auszeféieren.
Zweetens, de Get-AdvancedOptions cmdlet dauert nach méi laang fir ze kompletéieren.
Loosst d'éischt mat der zweeter beschäftegen. 

Get-AdvancedOptions ass praktesch fir eenzel VM Objekter, awer ganz onheemlech wann Dir mat villen Objeten schafft. Mir kënnen déi selwecht Informatioun vum virtuelle Maschinnobjekt selwer kréien (Get-VM). Et ass just gutt am ExtensionData Objet begruewen. Bewaffnet mat der Filterung beschleunegen mir de Prozess fir déi néideg Donnéeën ze kréien.

Mat enger liicht Beweegung vun der Hand ass dëst:


VM | Get-AdvancedSetting -Name Cloud.uuid -Server $ConnectionString | Select-Object @{N="VMName";E={$_.Entity.Name}},@{N="CloudUUID";E={$_.Value}},@{N="PowerState";E={$_.Entity.PowerState}}

Verwandelt dëst:


$VM | Where-Object {($_.ExtensionData.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value -ne $null} | Select-Object @{N="VMName";E={$_.Name}},@{N="CloudUUID";E={($_.ExtensionData.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value}},@{N="PowerState";E={$_.summary.runtime.powerstate}}

D'Ausgab ass d'selwecht wéi Get-AdvancedOptions, awer et funktionnéiert vill Mol méi séier. 

Elo fir Get-VM. Et ass net séier well et mat komplexen Objeten handelt. Eng logesch Fro stellt sech: Firwat brauche mir extra Informatioun an e monstréisen PSObject an dësem Fall, wa mir just den Numm vum VM brauchen, säin Zoustand an de Wäert vun engem komplizéierten Attribut?  

Zousätzlech ass den Hindernis a Form vu Get-AdvancedOptions aus dem Skript geläscht. D'Benotzung vun Runspace Pools schéngt elo wéi Iwwerkill well et net méi e Besoin ass fir eng lues Aufgab iwwer squat thread ze paralleliséieren wann Dir eng Sessioun iwwerginn. D'Tool ass gutt, awer net fir dëse Fall. 

Loosst eis d'Ausgab vun ExtensionData kucken: et ass näischt méi wéi e Get-View Objet. 

Loosst eis déi antik Technik vun de PowerShell Masters uruffen: eng Zeil mat Filteren, Sortéierung a Gruppéierung. All de fréiere Horror ass elegant an eng Zeil zesummegeklappt an an enger Sessioun ausgefouert:


$AllVMs = Get-View -viewtype VirtualMachine -Property Name,Config.ExtraConfig,summary.runtime.powerstate | Where-Object {($_.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value -ne $null} | Select-Object @{N="VMName";E={$_.Name}},@{N="CloudUUID";E={($_.Config.ExtraConfig | Where-Object {$_.key -eq "cloud.uuid"}).Value}},@{N="PowerState";E={$_.summary.runtime.powerstate}} | Sort-Object CloudUUID | Group-Object -Property CloudUUID | Where-Object -FilterScript {$_.Count -gt 1} | Select-Object -ExpandProperty Group

Mir moossen Zäit:

Wéi bauen ech e Rakéitebooster fir PowerCLI Scripten

9 Sekonnen fir bal 10k Objete mat Filter vun der gewënschter Konditioun. Super!

Amplaz vun enger Konklusioun

En akzeptabelt Resultat hänkt direkt vun der Wiel vum Tool of. Et ass dacks schwéier fir sécher ze soen wat genau soll gewielt ginn fir dat z'erreechen. Jiddereng vun den opgezielte Methoden fir Scripten ze beschleunegen ass gutt bannent de Grenze vu senger Applikatioun. Ech hoffen dësen Artikel hëlleft Iech an der schwiereger Aufgab fir d'Basis vun der Prozessautomatiséierung an der Optimiséierung an Ärer Infrastruktur ze verstoen.

PS: Den Auteur seet all Gemeinschaftsmemberen Merci fir hir Hëllef an Ënnerstëtzung beim Virbereedung vum Artikel. Och déi mat Patten. An och déi, déi keng Been hunn, wéi e Boa Constrictor.

Source: will.com

Setzt e Commentaire