May 11 2022 09:22 PM
I just want to shared my modified code in azure vm information extraction.
Data will be the list of VMName, IPAddress, ResourceGroup, VmSize & Tag.
# User Authentication
$ua = Get-StoredCredential -Target AzureAccount
$credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $ua.UserName,$ua.Password
# Login to your Azure Account
Connect-AzAccount -Tenant '<Tenant ID>' -Credential $credential
# Get All Virtual Machines & VMSize
$resultVMs = Get-AzVM | Where-Object { $_.Name -and $_.ResourceGroupName -and $_.HardwareProfile.VmSize } `
| Select-Object -Property @{n="Resource"; e={ $_.ResourceGroupName }}, @{n="VMName"; e={ $_.Name }}, @{n="VmSize"; e={ $_.HardwareProfile.VmSize }} `
# Get All Virtual Machines & WorkNo Tag
$resultTags = Get-AzResource -ResourceType "Microsoft.Compute/virtualMachines" `
| Where-Object { $_.Name -and $_.ResourceGroupName -and $_.Tags.WorkNo } `
| Select-Object -Property @{n="Resource"; e={ $_.ResourceGroupName }}, @{n="VMName"; e={ $_.Name }}, @{n="Tags"; e={ $_.Tags.WorkNo }} `
# Get All Virtual Machines & Ip Address
$resultIPAdds = Get-AzNetworkInterface | Where-Object { $_.ResourceGroupName -and $_.VirtualMachine -and $_.IPConfigurations -and $_.IPConfigurations.PrivateIPAddress } `
| Select-Object -Property @{n="Resource"; e={ $_.ResourceGroupName }}, @{n="VMName"; e={ $_.VirtualMachine.Id.Split("/")[-1] }}, @{n="PrivateIPAddress"; e= { $_.IpConfigurations.PrivateIPAddress }} `
# Create Report Array
$report = @()
# Loop All VM's
foreach($resultVM in $resultVMs){
# Creating Report Header
$reportdetails = "" | Select VMName, IPAddress, ResourceGroup, VmSize, Tag
# Save the VM Name
$reportdetails.VMName = $resultVM.VMName
# Save the Resource Group Name
$reportdetails.ResourceGroup = $resultVM.Resource
# Save the VmSize
$reportdetails.VmSize = $resultVM.VmSize
# Save the IP Address
$temp = @(($resultIPAdds | Where-Object { $_."VMName" -match $resultVM.VMName }).PrivateIPAddress)
$reportdetails.IPAddress = $temp[0]
# Save the Tag
$temp = @(($resultTags | Where-Object { $_."VMName" -match $resultVM.VMName }).Tags)
$reportdetails.Tag = $temp[0]
# Save Report
$report+=$reportdetails
}
# Generate Report
$report | Export-Excel ".\Desktop\VMList_ $(get-date -f yyyy.MM.dd.HH.mm.ss).xlsx"
Write-Host "Finished..."
Hope it can help others too. :beaming_face_with_smiling_eyes::beaming_face_with_smiling_eyes::beaming_face_with_smiling_eyes:.
May 12 2022 01:27 AM
Hey, Alan.
It's good to see the final version of what you were working towards with the previous questions - well done!
Here's a variation of your finished product that will work for others courtesy of some minor changes.
I'm not currently working in an Azure-facing role meaning I can't see how well this alternative scales performance-wise - I only have visibility of a small number of Azure virtual machines.
That said, it will consume less memory as it is working from the pipeline rather than from data stored in variables - with the unavoidable exception of the private IP address, since they're not exposed via Get-AzResource.
This reduces the overhead from three variables storing the full set of Azure VM data down to one, while the rest can be released as soon as they've been processed meaning memory utilisation won't scale as steeply in larger environments.
Anyhow, give it a try and let me know how it compares from a run time perspective. I'm hoping it's favourable or better but since using "-ExpandProperties" results in more data being returned, it'll be interesting to see if that outweighs the benefit of removing the separate call to Get-AzVM.
# User Authentication
$ua = Get-StoredCredential -Target AzureAccount
$credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $ua.UserName,$ua.Password
# Login to your Azure Account
Connect-AzAccount -Tenant '<Tenant ID>' -Credential $credential
# Build a dictionary of private IP addresses, given they can't be obtained via Get-AzResource -ExpandProperties.
[System.Collections.Generic.Dictionary[int, string]] $PrivateAddressesById = [System.Collections.Generic.Dictionary[int, string]]::new();
Get-AzNetworkInterface |
Where-Object { $_.ResourceGroupName -and $_.VirtualMachine -and $_.IPConfigurations -and $_.IPConfigurations.PrivateIPAddress } |
ForEach-Object {
$PrivateAddressesById.Add($_.Id.GetHashCode(), ($_.IpConfigurations.PrivateIPAddress -join ", "));
}
# Now, fetch the virtual machine information, making use of the speedy dictionary lookups to flesh out the IPAddress data.
Get-AzResource -ResourceType "Microsoft.Compute/virtualMachines" -ExpandProperties |
ForEach-Object {
[PSCustomObject]@{
VMName = $_.Name;
IPAddress = $PrivateAddressesById[($_.Properties.networkProfile.networkInterfaces.id.GetHashCode())];
ResourceGroup = $_.ResourceGroupName;
VmSize = $_.Properties.hardwareProfile.vmSize;
Tag = $_.Tags["WorkNo"];
}
} | Export-Csv -NoTypeInformation -Path ".\VMList_$([datetime]::Now.ToString("yyyy.MM.dd.HH.mm.ss")).csv";
# Clean up and bail.
$PrivateAddressesById.Clear();
[gc]::Collect();
Write-Host "Finished..."
Cheers,
Lain
May 12 2022 04:31 PM - edited May 12 2022 04:39 PM
@LainRobertson
Hi Lain
Yeah now I'm already started how to script using PowerShell its very difficult from the start but once you already familiarized the syntax its not that difficult anymore. So far my code speed from 20mins to 17sec. But your code is beyond my level. Yeah i will try your code hope it can beat my current 17 sec. :D
Thanks again. I will try decoding this.
May 12 2022 05:08 PM - edited May 12 2022 05:10 PM
All good. You're doing well so far.
With the re-write above, here's a brief explainer on some of the thought processes behind it - but the general motivators were seeing if we could improve performance:
In reality, it's always a case-by-case balancing act as to which combination is better, but here's how those thoughts translated:
That's a pretty basic explanation but it may serve as some useful information in your own learning journey!
Cheers,
Lain
Edited for spelling and punctuation.
May 12 2022 05:18 PM