Cara nggawe booster roket kanggo skrip PowerCLI 

Cepet utawa mengko, administrator sistem VMware bakal ngotomatisasi tugas rutin. Iku kabeh diwiwiti karo baris printah, banjur teka PowerShell utawa VMware PowerCLI.

Contone, sampeyan wis nguwasani PowerShell luwih sithik tinimbang ngluncurake ISE lan nggunakake cmdlet standar saka modul sing bisa digunakake amarga "sawetara jenis sihir". Nalika sampeyan miwiti ngetang mesin virtual ing atusan, sampeyan bakal nemokake sing Tulisan sing bantuan metu ing ukuran cilik mlaku noticeably alon ing ukuran gedhe. 

Ing kahanan iki, 2 alat bakal mbantu:

  • PowerShell Runspaces - pendekatan sing ngidini sampeyan parallelize eksekusi proses ing benang sing kapisah; 
  • Get-View - fungsi PowerCLI dhasar, analog saka Get-WMIObject ing Windows. Cmdlet iki ora narik obyek sing ngiringi entitas, nanging nampa informasi ing wangun obyek prasaja karo jinis data prasaja. Ing akeh kasus metu luwih cepet.

Sabanjure, aku bakal ngomong babagan saben alat lan nuduhake conto panggunaan. Ayo analisa skrip tartamtu lan deleng yen siji bisa luwih apik tinimbang liyane. Tindak!

Cara nggawe booster roket kanggo skrip PowerCLI

Tahap pisanan: Runspace

Dadi, Runspace dirancang kanggo ngolah tugas paralel ing njaba modul utama. Mesthi, sampeyan bisa miwiti proses liyane sing bakal mangan sawetara memori, prosesor, etc. Yen script mbukak ing sawetara menit lan nganggo gigabyte memori, paling kamungkinan sampeyan ora perlu Runspace. Nanging kanggo skrip kanggo puluhan ewu obyek dibutuhake.

Sampeyan bisa miwiti sinau ing kene: 
Miwiti Panggunaan PowerShell Runspaces: Part 1

Apa sing nggunakake Runspace menehi:

  • kacepetan kanthi matesi dhaptar printah sing dieksekusi,
  • eksekusi paralel tugas,
  • keslametan

Iki conto saka Internet nalika Runspace mbantu:

"Pertentangan panyimpenan minangka salah sawijining metrik sing paling angel dilacak ing vSphere. Ing vCenter, sampeyan ora mung bisa ndeleng VM sing nggunakake sumber daya panyimpenan luwih akeh. Untunge, sampeyan bisa ngumpulake data iki sajrone sawetara menit amarga PowerShell.
Aku bakal nuduhake script sing bakal ngidini administrator sistem VMware cepet nelusuri saindhenging vCenter lan nampa dhaftar VM karo data ing konsumsi rata-rata sing.  
Skrip nggunakake PowerShell runspaces kanggo ngidini saben host ESXi ngumpulake informasi konsumsi saka VM dhewe ing Runspace kapisah lan langsung laporan rampung. Iki ngidini PowerShell kanggo nutup proyek langsung, tinimbang ngulang liwat host lan ngenteni saben wong ngrampungake panjaluke.

Source: Cara Nuduhake Mesin Virtual I / O ing Dashboard ESXi

Ing kasus ing ngisor iki, Runspace ora migunani maneh:

"Aku nyoba nulis skrip sing ngumpulake akeh data saka VM lan nulis data anyar yen perlu. Masalahe yaiku ana akeh VM, lan 5-8 detik digunakake ing siji mesin. 

Source: Multithreading PowerCLI karo RunspacePool

Ing kene sampeyan butuh Get-View, ayo pindhah menyang. 

Tahap kapindho: Get-View

Kanggo ngerti sebabe Get-View migunani, sampeyan kudu ngelingi cara kerja cmdlet ing umum. 

Cmdlet dibutuhake kanggo entuk informasi kanthi gampang tanpa perlu sinau buku referensi API lan reinvent sabanjure wheel . Apa ing jaman biyen njupuk satus utawa rong baris kode, PowerShell ngidini sampeyan nindakake karo siji printah. We mbayar penak iki karo kacepetan. Ora ana sihir ing jero cmdlet dhewe: naskah sing padha, nanging ing tingkat sing luwih murah, ditulis dening tangan trampil master saka India sing cerah.

Saiki, kanggo mbandhingake karo Get-View, ayo njupuk cmdlet Get-VM: ngakses mesin virtual lan ngasilake obyek komposit, yaiku, nempelake obyek sing gegandhengan karo: VMHost, Datastore, lsp.  

Get-View ing panggonane ora nambah apa-apa sing ora perlu kanggo obyek sing bali. Kajaba iku, ngidini kita nemtokake informasi sing dibutuhake, sing bakal nggawe obyek output luwih gampang. Ing Windows Server umume lan ing Hyper-V khususe, cmdlet Get-WMIObject minangka analog langsung - ide kasebut persis padha.

Njaluk-View ora trep kanggo operasi rutin ing obyek titik. Nanging nalika nerangake ewu lan puluhan ewu obyek, iku ora duwe rega.

Sampeyan bisa maca liyane ing blog VMware: Pambuka kanggo Get-View

Saiki aku bakal nuduhake sampeyan kabeh nggunakake kasus nyata. 

Nulis skrip kanggo mbongkar VM

Sawijining dina kancaku njaluk aku ngoptimalake naskah. Tugas kasebut minangka rutinitas umum: golek kabeh VM kanthi parameter cloud.uuid duplikat (ya, iki bisa ditindakake nalika kloning VM ing vCloud Director). 

Solusi sing jelas sing ana ing pikiran yaiku:

  1. Entuk dhaptar kabeh VM.
  2. Parse dhaftar piye wae.

Versi asli yaiku skrip prasaja iki:

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
}
# Π”Π°Π»Π΅Π΅ РУКАМИ парсим ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚

Kabeh iku arang banget prasaja lan cetha. Bisa ditulis sajrone sawetara menit kanthi istirahat kopi. Screw ing filtrasi lan wis rampung.

Nanging ayo ngukur wektu:

Cara nggawe booster roket kanggo skrip PowerCLI

Cara nggawe booster roket kanggo skrip PowerCLI

2 menit 47 detik nalika ngolah meh 10k VM. Bonus yaiku ora ana saringan lan kudu ngurutake asil kanthi manual. Temenan, skrip kasebut mbutuhake optimasi.

Runspaces sing pisanan teka kanggo ngluwari nalika sampeyan kudu bebarengan njupuk metrik host saka vCenter utawa kudu proses puluhan ewu obyek. Ayo ndeleng apa pendekatan iki ndadekke.

Aktifake kacepetan pisanan: PowerShell Runspaces

Wangsulan: Bab ingkang pisanan teka ing pikiran kanggo script iki kanggo nglakokakΓ© daur ulang ora sequentially, nanging ing thread podo karo, ngumpulake kabeh data menyang siji obyek lan nyaring. 

Nanging ana masalah: PowerCLI ora ngidini kita mbukak akeh sesi independen menyang vCenter lan bakal mbuwang kesalahan sing lucu:

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.

Kanggo ngatasi iki, sampeyan kudu ngirim informasi sesi ing stream. Elinga yen PowerShell bisa digunakake karo obyek sing bisa dilewati minangka parameter menyang fungsi utawa menyang ScriptBlock. Ayo ngliwati sesi kasebut ing wangun obyek kasebut, ngliwati $global:DefaultVIServers (Sambung-VIServer karo tombol -NotDefault):

$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 $_
           }
       }
   }

Saiki ayo ngetrapake multithreading liwat Runspace Pools.  

Algoritme kaya ing ngisor iki:

  1. Kita entuk dhaptar kabeh VM.
  2. Ing aliran podo karo kita njaluk cloud.uuid.
  3. Kita ngumpulake data saka stream menyang siji obyek.
  4. Kita nyaring obyek kanthi nglumpukake kanthi nilai lapangan CloudUUID: sing jumlah nilai unik luwih saka 1 yaiku VM sing kita goleki.

AkibatΓ©, kita entuk skrip:


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
}

Kaendahan saka skrip iki yaiku bisa digunakake ing kasus liyane sing padha kanthi ngganti ScriptBlock lan paramèter sing bakal dikirim menyang stream. Eksploitasi!

Kita ngukur wektu:

Cara nggawe booster roket kanggo skrip PowerCLI

55 detik. Luwih apik, nanging isih bisa luwih cepet. 

Ayo pindhah menyang kacepetan kapindho: GetView

Ayo goleki apa sing salah.
Kaping pisanan, cmdlet Get-VM butuh wektu suwe kanggo dieksekusi.
Kapindho, cmdlet Get-AdvancedOptions butuh luwih suwe kanggo ngrampungake.
Ayo dadi urusan karo sing nomer loro dhisik. 

Get-AdvancedOptions trep kanggo obyek VM individu, nanging kikuk banget nalika nggarap akeh obyek. Kita bisa entuk informasi sing padha saka obyek mesin virtual dhewe (Get-VM). Iku mung disarèkaké uga ing obyek ExtensionData. Bersenjata karo nyaring, kita nyepetake proses entuk data sing dibutuhake.

Kanthi gerakan tangan sing sithik iki:


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

Dadi iki:


$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}}

Outpute padha karo Get-AdvancedOptions, nanging kerjane luwih cepet. 

Saiki menyang Get-VM. Iku ora cepet amarga urusan karo obyek Komplek. Pitakonan logis muncul: kenapa kita butuh informasi tambahan lan PSObject monstrous ing kasus iki, nalika kita mung butuh jeneng VM, negara lan nilai atribut sing angel?  

Kajaba iku, alangan ing wangun Get-AdvancedOptions wis dibusak saka script. Nggunakake Runspace Pools saiki katon kaya overkill amarga ora ana maneh perlu kanggo parallelize tugas alon ing benang jongkok nalika nyerahke sesi. Alat kasebut apik, nanging ora kanggo kasus iki. 

Ayo katon ing output ExtensionData: iku ora luwih saka obyek Get-View. 

Ayo nelpon teknik kuno saka master PowerShell: siji baris nggunakake saringan, ngurutake lan ngelompokake. Kabeh medeni sadurunge kanthi elegan ambruk dadi siji baris lan dieksekusi ing siji sesi:


$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

Kita ngukur wektu:

Cara nggawe booster roket kanggo skrip PowerCLI

9 detik kanggo meh 10k obyek karo nyaring dening kondisi sing dikarepake. apik tenan!

Tinimbang kesimpulan

Asil sing bisa ditampa langsung gumantung saka pilihan alat. Asring angel ngomong kanthi pasti apa sing kudu dipilih kanggo entuk. Saben cara sing kadhaptar kanggo nyepetake skrip apik ing watesan sing bisa ditrapake. Muga-muga artikel iki bakal mbantu sampeyan ing tugas angel kanggo mangerteni dhasar otomatisasi proses lan optimasi ing infrastruktur sampeyan.

PS: Penulis matur nuwun marang kabeh anggota komunitas kanggo bantuan lan dhukungan kanggo nyiapake artikel kasebut. Malah sing duwe paws. Lan malah sing ora duwe sikil, kaya boa constrictor.

Source: www.habr.com

Add a comment