Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI 

Sa madugay o sa madali, ang bisan unsang VMware system administrator moabut sa pag-automate sa naandan nga mga buluhaton. Nagsugod ang tanan sa command line, unya moabut ang PowerShell o VMware PowerCLI.

Ingnon ta nga nahanas na nimo ang PowerShell labi pa sa paglansad sa ISE ug paggamit sa mga standard nga cmdlet gikan sa mga module nga nagtrabaho tungod sa "usa ka matang sa salamangka". Kung magsugod ka sa pag-ihap sa mga virtual nga makina sa gatusan, imong makita nga ang mga script nga makatabang sa gamay nga sukod modagan nga labi ka hinay sa usa ka dako nga sukod. 

Niini nga sitwasyon, 2 ka himan ang makatabang:

  • PowerShell Runspaces - usa ka pamaagi nga nagtugot kanimo nga iparehas ang pagpatuman sa mga proseso sa lainlaing mga hilo; 
  • Pagtan-aw - usa ka sukaranan nga function sa PowerCLI, usa ka analogue sa Get-WMIObject sa Windows. Kini nga cmdlet wala magbira sa mga butang nga nag-uban sa mga entidad, apan nakadawat og impormasyon sa porma sa usa ka yano nga butang nga adunay yano nga mga tipo sa datos. Sa daghang mga kaso kini mogawas nga mas paspas.

Sunod, hisgotan nako ang matag himan ug ipakita ang mga pananglitan sa paggamit. Atong analisahon ang piho nga mga script ug tan-awon kung ang usa molihok nga mas maayo kaysa sa lain. Lakaw!

Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI

Unang yugto: Runspace

Busa, ang Runspace gidisenyo alang sa parallel nga pagproseso sa mga buluhaton sa gawas sa main module. Siyempre, mahimo nimong ilunsad ang laing proseso nga makakaon sa pipila ka panumduman, processor, ug uban pa. Kung ang imong script modagan sa pipila ka mga minuto ug mogamit usa ka gigabyte nga memorya, lagmit dili nimo kinahanglan ang Runspace. Apan alang sa mga script alang sa napulo ka libo nga mga butang gikinahanglan kini.

Mahimo ka magsugod sa pagkat-on dinhi: 
Pagsugod sa Paggamit sa PowerShell Runspaces: Bahin 1

Unsa ang gihatag sa paggamit sa Runspace:

  • paspas pinaagi sa paglimit sa lista sa mga gipatuman nga mga mando,
  • parallel nga pagpatuman sa mga buluhaton,
  • seguridad.

Ania ang usa ka pananglitan gikan sa Internet kung ang Runspace makatabang:

"Ang panagbingkil sa pagtipig mao ang usa sa pinakalisud nga sukatan nga masubay sa vSphere. Sa sulod sa vCenter, dili ka lang moadto ug tan-awon kung unsang VM ang nag-usik sa daghang mga kapanguhaan sa pagtipig. Suwerte, mahimo nimong kolektahon kini nga datos sa mga minuto salamat sa PowerShell.
Ipaambit nako ang usa ka script nga magtugot sa mga tagdumala sa sistema sa VMware nga dali nga makapangita sa tibuuk nga vCenter ug makadawat usa ka lista sa mga VM nga adunay datos sa ilang kasagaran nga konsumo.  
Ang script naggamit sa PowerShell runspaces aron tugotan ang matag ESXi host sa pagkolekta sa impormasyon sa konsumo gikan sa kaugalingon nga mga VM sa usa ka separado nga Runspace ug diha-diha dayon i-report ang pagkompleto. Gitugotan niini ang PowerShell nga isira dayon ang mga trabaho, imbes nga mag-uli sa mga host ug maghulat nga makompleto sa matag usa ang hangyo niini.

Source: Giunsa Ipakita ang Virtual Machine I/O sa usa ka ESXi Dashboard

Sa kaso sa ubos, ang Runspace dili na magamit:

"Gisulayan nako ang pagsulat sa usa ka script nga nagkolekta daghang datos gikan sa usa ka VM ug nagsulat bag-ong datos kung kinahanglan. Ang problema mao nga adunay daghang mga VM, ug 5-8 segundos ang gigugol sa usa ka makina. 

Source: Multithreading PowerCLI uban sa RunspacePool

Dinhi kinahanglan nimo ang Get-View, magpadayon kita niini. 

Ikaduha nga yugto: Pagtan-aw

Aron masabtan kung ngano nga ang Get-View mapuslanon, angay nga hinumdoman kung giunsa ang paglihok sa mga cmdlet sa kinatibuk-an. 

Ang mga Cmdlet gikinahanglan aron daling makakuha og impormasyon nga dili kinahanglan nga magtuon sa mga libro sa pakisayran sa API ug mag-imbento pag-usab sa sunod nga ligid. Unsa sa karaan nga mga adlaw ang gikuha usa ka gatos o duha ka linya sa code, gitugotan ka sa PowerShell nga buhaton sa usa ka mando. Gibayran namon kini nga kasayon ​​​​sa tulin. Wala’y salamangka sa sulod sa mga cmdlet sa ilang kaugalingon: parehas nga script, apan sa usa ka ubos nga lebel, gisulat sa hanas nga mga kamot sa usa ka agalon gikan sa sunny India.

Karon, alang sa pagtandi sa Get-View, atong kuhaon ang Get-VM cmdlet: kini nag-access sa virtual machine ug nagbalik sa usa ka composite nga butang, nga mao, kini nag-attach sa ubang mga butang nga may kalabutan niini: VMHost, Datastore, ug uban pa.  

Ang Get-View sa lugar niini wala magdugang bisan unsa nga wala kinahanglana sa gibalik nga butang. Dugang pa, kini nagtugot kanato sa hugot nga pagtino kon unsa nga impormasyon ang atong gikinahanglan, nga sa paghimo sa output butang nga mas sayon. Sa Windows Server sa kinatibuk-an ug sa Hyper-V sa partikular, ang Get-WMIObject cmdlet usa ka direkta nga analogue - ang ideya parehas ra.

Ang Get-View dili kombenyente alang sa naandan nga mga operasyon sa punto nga mga butang. Apan kon mahitungod sa liboan ug napulo ka libo nga mga butang, kini walay bili.

Makabasa ka og dugang sa VMware blog: Pasiuna sa Get-View

Karon ipakita ko kanimo ang tanan gamit ang tinuod nga kaso. 

Pagsulat og script aron madiskarga ang usa ka VM

Usa ka adlaw gihangyo ko sa akong kauban nga i-optimize ang iyang script. Ang buluhaton usa ka kasagaran nga rutina: pangitaa ang tanan nga mga VM nga adunay usa ka duplicate nga cloud.uuid parameter (oo, posible kini kung mag-clone sa usa ka VM sa vCloud Director). 

Ang klaro nga solusyon nga moabut sa hunahuna mao ang:

  1. Pagkuha usa ka lista sa tanan nga mga VM.
  2. I-parse ang lista sa usa ka paagi.

Ang orihinal nga bersyon mao kining yano nga script:

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
}
# Далее РУКАМИ парсим полученный результат

Ang tanan yano kaayo ug klaro. Mahimo kini isulat sa pipila ka minuto nga adunay usa ka pahulay sa kape. I-screw ang filtration ug nahuman na.

Apan atong sukdon ang oras:

Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI

Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI

2 minutos 47 segundos kung giproseso ang hapit 10k VMs. Ang usa ka bonus mao ang pagkawala sa mga pagsala ug ang panginahanglan sa mano-mano nga paghan-ay sa mga resulta. Dayag, ang script nanginahanglan pag-optimize.

Ang mga runspace mao ang una nga motabang kung kinahanglan nimo nga dungan nga makakuha mga sukatan sa host gikan sa vCenter o kinahanglan nga iproseso ang libu-libo nga mga butang. Atong tan-awon kung unsa ang gidala niini nga pamaagi.

I-on ang unang tulin: PowerShell Runspaces

Ang una nga butang nga mosantop sa hunahuna alang niini nga script mao ang pagpatuman sa loop dili sunud-sunod, apan sa parallel nga mga hilo, kolektaha ang tanan nga datos sa usa ka butang ug isala kini. 

Apan adunay problema: Dili kami tugutan sa PowerCLI nga magbukas sa daghang mga independente nga sesyon sa vCenter ug magbutang usa ka kataw-anan nga sayup:

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.

Aron masulbad kini, kinahanglan una nimong ipasa ang impormasyon sa sesyon sa sulod sa sapa. Atong hinumdoman nga ang PowerShell nagtrabaho sa mga butang nga mahimong ipasa isip parameter sa usa ka function o sa usa ka ScriptBlock. Ipasa nato ang sesyon sa porma sa maong butang, nga molabay sa $global:DefaultVIServers (Connect-VIServer uban sa -NotDefault key):

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

Karon atong ipatuman ang multithreading pinaagi sa Runspace Pools.  

Ang algorithm mao ang mosunud:

  1. Nakakuha kami usa ka lista sa tanan nga mga VM.
  2. Sa parallel streams atong makuha ang cloud.uuid.
  3. Gikolekta namo ang datos gikan sa mga sapa ngadto sa usa ka butang.
  4. Gisala namon ang butang pinaagi sa pag-grupo niini pinaagi sa kantidad sa natad sa CloudUUID: kadtong diin ang gidaghanon sa mga talagsaon nga kantidad labi ka daghan sa 1 mao ang mga VM nga among gipangita.

Ingon usa ka sangputanan, makuha namon ang script:


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
}

Ang katahum sa kini nga script mao nga kini magamit sa ubang parehas nga mga kaso pinaagi lamang sa pag-ilis sa ScriptBlock ug ang mga parameter nga ipasa sa sapa. Pagpahimulos niini!

Gisukod namon ang oras:

Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI

55 segundo. Kini mas maayo, apan kini mahimo gihapon nga mas paspas. 

Mobalhin ta sa ikaduhang tulin: GetView

Atong susihon kung unsa ang sayup.
Una ug labaw sa tanan, ang Get-VM cmdlet nagkinahanglan og taas nga panahon aron ma-execute.
Ikaduha, ang Get-AdvancedOptions cmdlet mas dugay pa aron makompleto.
Unahon nato ang ikaduha. 

Ang Get-AdvancedOptions sayon ​​​​alang sa indibidwal nga mga butang sa VM, apan clumsy kaayo kung nagtrabaho sa daghang mga butang. Makuha nato ang samang impormasyon gikan sa virtual machine object mismo (Get-VM). Gilubong lang kini og maayo sa ExtensionData nga butang. Armado sa pagsala, gipadali namo ang proseso sa pagkuha sa gikinahanglang datos.

Uban sa gamay nga paglihok sa kamot mao kini:


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

Nahimo kini:


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

Ang output parehas sa Get-AdvancedOptions, apan kini molihok sa daghang mga higayon nga mas paspas. 

Karon sa Get-VM. Dili kini paspas tungod kay naghisgot kini sa mga komplikadong butang. Ang usa ka lohikal nga pangutana mitungha: nganong nagkinahanglan kita og dugang nga impormasyon ug usa ka makalilisang nga PSObject niini nga kaso, kung gikinahanglan lang nato ang ngalan sa VM, ang estado niini ug ang bili sa usa ka malisud nga kinaiya?  

Dugang pa, ang babag sa porma sa Get-AdvancedOptions gikuha gikan sa script. Ang paggamit sa Runspace Pools karon daw sobra ra kaayo tungod kay wala na kinahanglana nga iparehas ang usa ka hinay nga buluhaton sa mga squat thread kung maghatag usa ka sesyon. Ang himan maayo, apan dili alang niini nga kaso. 

Atong tan-awon ang output sa ExtensionData: kini usa ka butang nga Get-View. 

Atong tawagan ang karaang teknik sa PowerShell masters: usa ka linya gamit ang mga filter, paghan-ay ug paggrupo. Ang tanan nga nangaging kalisang maayo nga nahugno sa usa ka linya ug gipatuman sa usa ka sesyon:


$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

Gisukod namon ang oras:

Giunsa paghimo ang usa ka rocket booster alang sa mga script sa PowerCLI

9 segundo alang sa hapit 10k nga mga butang nga adunay pagsala sa gusto nga kahimtang. Nindot!

Kay sa usa ka konklusyon

Ang madawat nga resulta direkta nga nagdepende sa pagpili sa himan. Kasagaran lisud isulti nga sigurado kung unsa gyud ang kinahanglan pilion aron makab-ot kini. Ang matag usa sa nalista nga mga pamaagi alang sa pagpadali sa mga script maayo sulod sa mga limitasyon sa paggamit niini. Nanghinaut ko nga kini nga artikulo makatabang kanimo sa lisud nga tahas sa pagsabut sa mga sukaranan sa automation sa proseso ug pag-optimize sa imong imprastraktura.

PS: Ang tagsulat nagpasalamat sa tanang miyembro sa komunidad sa ilang tabang ug suporta sa pag-andam sa artikulo. Bisan kadtong adunay mga tiil. Ug bisan kadtong walay mga bitiis, sama sa boa constrictor.

Source: www.habr.com

Idugang sa usa ka comment