Quomodo aedificare cursus in eruca scripta PowerCLI 

Serius vel post, administrator systematis VMware ad automataria exercitationis officia venit. Omnia incipit cum linea recta, tunc comes PowerShell vel VMware PowerCLI.

Dicamus te dominasse PowerShell paulo longius quam ISE deducendo et vexillum cmdlets ex modulorum modulorum operantibus adhibitis ad "magicam quandam". Cum in machinis virtualibus in centenis computare incipias, scripta quae adiuvant in parva scala invenies tardiorem in magna magnitudine conspicue currere. 

In hoc situ, instrumenta 2 adiuvabunt:

  • PowerShell Runspaces – accessus qui permittit ut processuum executionem in filis separatis parallelis facias; 
  • Adepto-View - munus fundamentale PowerCLI, analogum GET-WMIObject in Windows. Hoc cmdlet non trahit obiecta entia comitante, sed informationes accipit in forma obiecti simplicis notitiarum specierum. In multis citius exeat.

Deinceps de singulis instrumentis breviter dicam et usus exempla praebebo. Scripta specifica excutiamus et videamus quando unum melius quam alterum operatur. Perge!

Quomodo aedificare cursus in eruca scripta PowerCLI

Primum scaena: Runspace

Ergo, Runspace, ordinatur ad processui parallelam officiorum extra moduli principalis. Utique, alium processum mittere potes qui memoriam aliquam, processus, etc. Si scriptum tuum in duobus minutis decurrit et memoriae gigabyte consumit, verisimile non opus erit Runspace. Sed ad scriptorum decem millia objectorum opus est.

Discere hic potes incipere: 
Initium Usus PowerShell Runspaces: Pars I

Quid per Runspace da:

  • celeritatem finiendo indicem iussa;
  • pari officiorum executione;
  • securitatem.

Hic exemplum est de Interrete cum Runspace adiuvat:

β€œRepono contentio est unum ex durissimis metricis in vSphere indagare. Intus vCenter, non potes tantum ire et videre quae VM plus repono opes consumit. Feliciter, hanc notitias in minutas gratias PowerShell colligere potes.
Scriptum communicabo quod administratores systematis VMware permittit ut celeriter per vCenter quaeras et elenchum VMs cum notitia in media consummatione recipiam.  
Scriptum est PowerShell spatiis missis utatur ut quisque ESXi exercitum ad notitias consumptionis colligendas ex proprio VMs in Runspace separatum ac statim complementum referret. Hoc permittit PowerShell claudere jobs immediate, potius quam iterare per turmas et unumquemque ad petitionem suam implere.

Source: Quam ostendere Virtualis Machina I/O in ESXi Dashboard

In casu infra, Runspace non iam utile est;

β€œLibrum scribere studeo quod multum notitiarum ex VM colligit et novas notitias scribit cum necesse est. Problema est multum VMs esse, et 5-8 secundae machinae in una consumpta sunt. 

Source: Multithreading PowerCLI cum RunspacePool

Hic opus erit Get-Visum, ad eam transeamus. 

Secundus gradus: Get-View

Scire cur Get-Visum utile est, memorabile est quomodo cmdlets in genere laborabit. 

Cmdlets opus est ut commode notitias habere sine necessitate studiorum API librorum referendi et reinventum rotae proximae. Quod olim centum vel duo in codice tulerunt, PowerShell uno imperio te permittit facere. Hoc commodum cum celeritate pensamus. Intus cmdlets magica non est: eadem scriptura, sed in inferiori gradu, ex apricis Indiae peritis magistri manus.

Nunc, ad comparationem cum Get-View, Get-VM cmdlet capiamus: machina virtuali accedit et objectum compositum reddit, hoc est, alia obiecta ei affingit: VMHost, Datastore, etc.  

Get-View in loco suo rem redditam nihil non superfluum addit. Praeterea nobis permittit stricte definire quae notitia nobis necessaria est, quae facilius rem output efficiet. In Fenestra Servo in genere et in Hyper-V in specie, GET-WMIObject cmdlet directa analogi est - idea prorsus eadem est.

Get-View inconveniens est exercitationi operationes in puncto objectorum. Sed quantum ad milia et decem milia, nullum pretium habet.

Plus legere potes in blog VMware: Introductio ad Get-View

Nunc omnia tibi demonstrabo casu reali utens. 

Scribens scriptum exonerare VM

Olim collega meus me rogat ut suam scripturam optimize. Negotium commune usitatum est: omnia VMs reperire cum duplicata nube.uuid parametri (sic, hoc fieri potest cum a VM in vCloud Directore perplexus). 

Patet solutio quae in mentem venit:

  1. Indicem omnium VMs habe.
  2. Parse indice quodam modo.

Versio originalis erat haec scriptura simplex;

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

Omnia simplicia et perspicua sunt. Potest scribi in duobus minutis cum capulus confractus. Screw in colamentum et factum est.

Sed tempus metior;

Quomodo aedificare cursus in eruca scripta PowerCLI

Quomodo aedificare cursus in eruca scripta PowerCLI

III minutis XXX secundis cum dispensando fere 10k VMs. Bonus est absentia eliquarum et necessitas manualis eventus sortitur. Patet, scriptum ipsum requirit.

Runspaces sunt primi ad succurrendum cum necesse est simul exercitum metrics e vCenter obtinere vel opus ad processum decem milia objectorum. Quid aditus afferat videamus.

Conversus ad primam celeritatem: PowerShell Runspaces

Primum, quod huic scripto occurrit, ansam non successiue, sed in filis parallelis exequi, omnia indicia in unum colligere et percolare. 

Sed quaestio est: PowerCLI non sinit nos multas sessiones independentes aperire ad vCenter et ridiculum errorem mittent;

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.

Ad hoc solvendum, informationes sessionum primum intra rivum transire debes. Meminerimus PowerShell opera cum obiectis quae transiri possunt ut modulus vel ad functionem vel ad ScriptBlock. Sessionem transeamus in forma rei talis, praetermittens $ global: DefaultVIServers (Connect-VIServer cum clavis -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 $_
           }
       }
   }

Nunc multiplicemus deducendi per Runspace piscinas.  

Algorithmus talis est;

  1. Indicem omnium VMs obtinemus.
  2. Parallelis fluminum nubes.uuid.
  3. Notitia ex rivis in unum colligimus.
  4. Obiectum eliquamus per copulationem agri CloudUUID valoris: ubi numerus valorum singularium maior est quam 1 sunt VMs quaerimus.

Quam ob rem scripturam obtinemus;


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
}

Pulchritudo huius scripti est quod in aliis similibus casibus adhiberi potest, simpliciter reponendo ScriptBlock et parametris quae ad flumen transibunt. Exsequere eam!

Metimur tempus;

Quomodo aedificare cursus in eruca scripta PowerCLI

55 seconds. Melius est, sed velocius esse potest. 

Lets move ad secundum velocitatem: GetView

Sit scriptor quid mali invenire.
Imprimis, Get-VM cmdlet longum tempus exequi.
Secundo, cmdlet Get-AdvancedOptions etiam diutius ad perficiendum accipit.
De secundo primo agamus. 

Adepto-AdvancedOptions VM rebus singulis convenit, sed valde incondite cum multis obiectis laborat. Eadem informationes accipere possumus ex ipso objecto virtualis machinae (Get-VM). It's just buried well in the ExtensionData object. Armati eliquandi processum ad res necessarias datas acceleramus.

Levi motu manus haec est;


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

Vertit in hoc;


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

Output idem est ac AdvancedOptions Get, sed multoties velocius operatur. 

IAM AD-VM. Ieiunium non est, quia de complexis agitur. Quaestio logica oritur: quid opus est extra informationem et monstruosum PSObjectum in hoc casu, cum tantum indigemus nomine VM, statu et valore fallaciae attributi?  

Praeterea impedimentum formae Get-AdvancedOptions remotum est a scripto. Lacus Runspace uti nunc videtur sicut overkill cum iam non opus est ad parallelize lentum negotium trans fila salaputium cum sessionem tradens. Instrumentum bonum est, sed non causa. 

Intueamur ad output of ExtensionData: nihil aliud est quam obiectum Visum Get. 

Invocemus antiquam artem magistrorum PowerShell: una linea utens filtra, genus et copulationem. Horror priorum omnes eleganter in unam lineam concidit et in una sessione profertur;


$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

Metimur tempus;

Quomodo aedificare cursus in eruca scripta PowerCLI

9 seconds nam fere 10k res percolatur a conditione optata. Magna!

Sed in finem

Effectum acceptabile directe dependet ex instrumenti electione. Saepe difficile dictu est pro certo quidnam eligendum sit ad id assequendum. Singulae methodi enumerantur ad scripta acceleranda, intra fines applicabilitatis suae bona est. Spero te hunc articulum adiuvabit in difficultate intellegendi basicas processus automationis et optimizationis in infrastructura tua.

PS: Auctor omnibus membris communitatis gratias agit pro eorum auxilio et auxilio in articulo praeparando. Etiam qui ungula. Et qui crura non habent, ut boa constrictor.

Source: www.habr.com