Query number of cores per vm using AZ GRAPH - azure

as of this moment in the organization, an automatic report is running on all resources. The report is running in POWERSHELL
and uses FORECH on FORECH to reach each machine to collect information
I was asked to optimize and refactor the script in order for it to be use the az graph search.
I manage to collect all the data, except for the number of cores per machine
Resources
| join kind=leftouter (ResourceContainers | where type=='microsoft.resources/subscriptions' | project subscriptionName=name, subscriptionId) on subscriptionId
| where type =~ 'Microsoft.Compute/virtualMachines'
| extend HUBEnabled = iff(isempty(tostring(properties.['licenseType'])), "No", "Yes")
| extend osType = tostring(properties.storageProfile.osDisk.osType)
| extend VMSize = tostring(properties.hardwareProfile.vmSize)
| extend VMStatus = tostring(properties.extended.instanceView.powerState.displayStatus)
| extend nics=array_length(properties.networkProfile.networkInterfaces)
| extend vCPUs = tostring(properties.hardwareProfile.vmSizeProperties.minVCPUCount)
| extend OSName = tostring(properties.osProfile.computerName)
| extend Location = tostring(location)
| extend vCPU = tostring(properties.hardwareProfile.vmSizeProperties)
| mv-expand nic=properties.networkProfile.networkInterfaces
| where nics == 1 or nic.properties.primary =~ 'true' or isempty(nic)
| extend nicId = tostring(nic.id)
| join kind=leftouter (
Resources
| where type =~ 'microsoft.network/networkinterfaces'
| extend ipConfigsCount=array_length(properties.ipConfigurations)
| mv-expand ipconfig=properties.ipConfigurations
| where ipConfigsCount == 1 or ipconfig.properties.primary =~ 'true'
| project nicId = id, privateIpAddress = tostring(ipconfig.properties.privateIPAddress))
| join kind=leftouter (
Resources
| where type == "microsoft.compute/virtualmachinescalesets"
)
on nicId
| project VMName = name, computer_name=OSName, VMSize, vCPU , Location, osType , VMStatus , Private_IP=privateIpAddress , HUBEnabled , subscriptionName , subscriptionId , resourceGroup
for some reason | extend vCPU = tostring(properties.hardwareProfile.vmSizeProperties) return empty value

I tried to reproduce the same in my environment.
when tried with query
vmCore=tostring(properties.hardwareProfile.vmSizeProperties.NumberOfCores)
But not able to get number of cores .
Tried with properties.hardwareProfile.vmSizeProperties
Graph query:
Resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| project name, properties.vmId, properties.storageProfile.osDisk.osType,properties.hardwareProfile.vmSize,properties.hardwareProfile.vmSizeProperties
| order by ['name'] asc
Everything like hardware profile is resulting in output except vm size properties are empty which includes number of cores property:
If i checked the VM in my environment. Its json doesn't have property separately for vmsize properties where it has to have number of cores.
So there is not a straight forward way for it through the graph query.
Try Initially check the properties and then call the number of cores for each VM.
Below command gives VM size particularly.
Command:
$Myvm= Get-AzureRmVM -ResourceGroupName myrg -Name myacctvm
Reference:
Command:
$MyVmZizeProperties = Get-AzureRmVMSize -ResourceGroupName myrg -VMName myacctVM
$NumberOfCores = $MyVmZizeProperties.NumberOfCores
Reference: get-number-of-cores-of-vm-in-azure | SO & https://learn.microsoft.com/en-us/azure/virtual-machines/resource-graph-samples?tabs=azure-cli

Related

Getting Distribution Groups / Owners w/ PowerShell, but removing entries that have a null or empty owner

I have the lovely job of getting a list of Distribution Groups and their owners from Exchange Online. So far this is working great, but I need to fine tune my output to exclude groups that don't have any owners; and groups that have multiple owners (by returning only the first).
So far this has been fairly difficult as this is sort of my first foray into PShell.
Here's my code:
$job = Get-DistributionGroup | select Name,PrimarySmtpAddress, #{n= "ManagedBy"; e={$_.ManagedBy | Select-Object -First 1 | Where-Object {$_.ManagedBy.Count -eq 0} |foreach {(Get-Mailbox $_).PrimarySMTPAddress}}}
Write-Output $job | ConvertTo-Json
Here's an example of my output:
I basically only want a single string address to be returned. So a single owner of a distro group, no nulls, and only the first address in the collections. (Right now they are blank, I'm probably nuking them with my code- but usually they return 4 or so email addresses but I just want the first person)
Thanks!
By collection you mean the ManagedBy property right? If so, try with { ($_.ManagedBy | Select-Object -First 1 | Get-Mailbox).PrimarySMTPAddress } –
Santiago Squarzon
1 hour ago

Get unlocked resources azure

I need a powershell script to get a list of all unlocked resource groups.
If you run Get-AzureRmResourceLock it will show the resources that are currently locked not the ones that are unlocked
One way you can go about doing this is as follows:
Get all Resource Groups in your Subscription
$AllRGs = $(Get-AzResourceGroup | Select-Object ResourceGroupName).ResourceGroupName
Get the Resource Groups that have locks
$lockedRGs = $(Get-AzResourceLock | Where-Object {$_.ResourceType -eq "Microsoft.Authorization/locks"} | Select-Object ResourceGroupName).ResourceGroupName
Take a diff of the two
$noLockRGs = $AllRGs | Where-Object {$lockedRGs -notcontains $_}

Adding values by duplicated name

I want to generate Azure log analytics query using powershell.
But I'm stuck on a strange problem. Not sure why, but it shows duplicated entries for few VMs.
My goal is to generate report of up time values for each VM. Here's my code:
$startime = '2019-08-01';
$endtime = '2019-08-31';
$queryResults = Invoke-AzOperationalInsightsQuery -WorkspaceId "..." -Query "let start_time=startofday(datetime('$startime'));
let end_time=endofday(datetime('$endtime'));
Heartbeat
| where TimeGenerated > start_time and TimeGenerated < end_time
| summarize heartbeat_per_hour=count() by bin_at(TimeGenerated, 1h, start_time), Computer
| extend available_per_hour=iff(heartbeat_per_hour>0, true, false)
| summarize total_available_hours=countif(available_per_hour==true) by Computer
"
$output = $QueryResults.Results | foreach-object {
[PSCustomObject]
#{
"VM Name" = ($_.Computer.split('.')[0]).ToUpper()
"VM Uptime (in Hours)" = $_.total_available_hours
}
}
In $output variable I see multiple entries for few VMs. It would be easy to just remove the duplicates, but I want to sum the values of up time for each VM occurence in order to avoid duplicate entries, but having them added at the same time.
Duplicates happen because in query result, some VMs are shown both w/out and with FQDN with different up time values, hence the split command in foreach-object command. Not sure why that happens too.
Please correct me if I'm misunderstanding the issue.
According to your code, seems that if the computer_1 name is pc_1, and computer_2 name is pc_1.azure.com, then you think them as the same computer? so you want to sum the uptime of the 2 computers together? Like pc_1 uptime is 10, pc_1.azure.com uptime is 20, the result should be vmName:pc_1 => uptime:30? right?
If that's the case, you have 2 ways to achieve that. The first way is re-write the query in kusto, the 2nd way is re-write powershell code.
Here, I just re-write your kusto query by split the computer name, like below:
let start_time=startofday(datetime('$startime'));
let end_time=endofday(datetime('$endtime'));
Heartbeat
| where TimeGenerated > start_time and TimeGenerated < end_time
| extend aa=split(Computer, ".")
| extend bb=array_slice(aa, 0, 0)
| extend my_Computer=strcat_array(bb,"")
| summarize heartbeat_per_hour=count() by bin_at(TimeGenerated, 1h, start_time), my_Computer
| extend available_per_hour=iff(heartbeat_per_hour>0, true, false)
| summarize total_available_hours=countif(available_per_hour==true) by my_Computer
The screenshot below shows the effect of split computer name:
The 2nd way to use powershell, like op mentioned in the comment:
$output = $output | Group-Object -Property "VM Name" | Select-Object -unique Name, #{L="VM Uptime (in Hours)";E={($_.group | Measure-Object -Property "VM Uptime (in Hours)" -Sum).sum}}

Azure Powershell - Script to obtain VM info across subscriptions

Trying to run a script that will connect to each subscription, and pull the
$azureSubs = Get-AzureRMSubscription
$azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | select resourcegroupname, name, licensetype -WarningAction SilentlyContinue}
This works, BUT I'd like to add two more pieces of information: the "OSType" and "VMSize"
If I do a GET-AZURERMVM, in the table for that subscription that the command is run in, the two pieces of information I need are there: VmSize and OsType
However, when I try to add them to the query, the columns are blank.
I believe the VmSize is in the HardwareProfile, and OsType is in the OsProfile, as if I run a "Get-AzureRMVM -name (name) -resourcegroupname (RGname)", then it shows "Hardware Profile: VMSize" and "OSProfile: ComputerName, AdminUsername windowsConfiguration, Secrets"
Ultimate goal is to get the script that will, for each subscription, print results like:
ResourceGroupName | Name | License Type | VMSize | OS Type
TEST_RG | Test_VM | Windows_Server | DS3_v2 | Windows
Test_RG | Test_VM2 | | DS3_v2 | Linux
etc.
Thankful for any help; sorry for such a noob question. Have spent so much time trying to figure this out...
Something like the following would work.
What you were missing mainly was calculated properties.
This is what allow you to perform a select of custom property.
Some notes:
In your code, you used -WarningAction SilentlyContinue on the Select statement. You need to put it on the Get-AzureRMVM CmdLet instead.
This is my opinion but unless you are writing one-liners on purposes, try aerating your code more. It will make it way easier to read, debug and maintain.
This is the code you wrote, modified to include the calculated properties and with the WarningAction parameter set to Get-AzureRMVM instead of the Select statement.
$azureSubs = Get-AzureRMSubscription
$Vms = $azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM -WarningAction SilentlyContinue | select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}}
$Vms | ft
The same thing, with some progress indication without forcing everything on one line.
$azureSubs = Get-AzureRMSubscription
$Vms = New-Object 'System.Collections.Generic.List[PSObject]'
ForEach ($sub in $azureSubs) {
Select-AzureRMSubscription $sub | Out-Null
Write-Host "Processing Subscription $($sub.Name)".PadRight(50,' ') -ForegroundColor Cyan -NoNewline
[PsObject[]]$items = Get-AzureRMVM -WarningAction SilentlyContinue |
select resourcegroupname,
name,
licensetype,
#{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},
#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}
Write-Host "($($items.count) retrieved)"
if ($items -ne $null) {
$vms.AddRange($items)
}
}
$vms | Format-Table
You are looking for something like this on the select side
select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}}, #{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}

Get-AzureRmConsumptionUsageDetail limited response to 1000 items

I've discovered this azure PS command Get-AzureRmConsumptionUsageDetail that as per docs is able to "get usage details of the subscription".
I performed some tests on my MSDN account with success. When tried with the Enterprise account (with many more resources) I've seen that it is always returning a max of 1000 items in all cases.
I tried to set -MaxCount to a higher than 1000 value without success.
The only workaround I see is try to identify all the resources in my subscription and query each one with the hope that no one individually has more than a thousand entries. Bad news is that I cannot do that for deleted items.
This behavior is not mentioned on the MS docs page so, any idea how this command should be properly used?
To partially solve my problem I developed a quick and dirty script that is able to ask for all the current subscription resources and then iterate through all them to get the billing details. It should be strange for a single resource to overpass the 1000 rows limit as resources are usually billed per day.
The drawbacks are the amount of api calls it has to perform and thus the time as well as that deleted resources are not included.
$resources = Get-AzureRmResource
Write-Output "Found $($resources.Count) in the subscription"
$consumption = #()
$i = $resources.Count
foreach($resource in $resources) {
$consumption += Get-AzureRmConsumptionUsageDetail -InstanceId $resource.ResourceId
$i--
Write-Output "$i - $($resource.ResourceId)"
}
$consumption | Group-Object InstanceId | %{
New-Object psobject -Property #{
ResourceGroup = ([regex]::Match($_.Name, ".*\/resource[gG]roups\/(.*?)\/.*$")).Groups[1].Value.ToUpper();
Cost = ($_.Group | Measure-Object PretaxCost -Sum).Sum
}
} | Group-Object ResourceGroup | %{
New-Object psobject -Property #{
ResourceGroup = $_.Name;
Total = ($_.Group | Measure-Object Cost -Sum).Sum
}
} | Export-Csv cost_report.csv

Resources