Best way to retrieve CPU utilization for all VMs in a Azure subscription - azure

Trying to get the CPU utilization (and preferably network as well. I would love to get RAM too, but as i understand that requires having the guest module installed to get those metrics. so at this point i just need the metrics at the 'host' level).
Idea is to run this against all VMs in a subscription, to get VM name, VM resource group, CPU utilization over the last x days, network in over the last x days, and network out over the last x days.
The first thing I tried though, using the "Get-AzureRMMetric", starts giving errors.
I type "get-azurermmetric", and am prompted for a resource ID. I enter the resource ID of the VM, and the response i get is a long string of warnings, and exception types, that an invalid status code 'notfound' was returned.
Any ideas?

First, you need to determine which metrics are supported for vm, use the following code:
(Get-AzureRmMetricDefinition -ResourceId "vm resource id").name
Then you can see the supported metrics(Just ignore the warning message):
As per your question, I think you need "Percentage CPU" / "Network In" / "Network Out".
Then you can use the sample code below for your purpose(you can make some changes if it does not meet your need):
#get all vms in a resource group, but you can remove -ResourceGroupName "xxx" to get all the vms in a subscription
$vms = Get-AzureRmVM -ResourceGroupName "xxx"
#get the last 3 days data
#end date
$et=Get-Date
#start date
$st=$et.AddDays(-3)
#define an array to store the infomation like vm name / resource group / cpu usage / network in / networkout
$arr =#()
foreach($vm in $vms)
{
#define a string to store related infomation like vm name etc. then add the string to an array
$s = ""
#percentage cpu usage
$cpu = Get-AzureRmMetric -ResourceId $vm.Id -MetricName "Percentage CPU" -DetailedOutput -StartTime $st `
-EndTime $et -TimeGrain 12:00:00 -WarningAction SilentlyContinue
#network in
$in = Get-AzureRmMetric -ResourceId $vm.Id -MetricName "Network In" -DetailedOutput -StartTime $st `
-EndTime $et -TimeGrain 12:00:00 -WarningAction SilentlyContinue
#network out
$out = Get-AzureRmMetric -ResourceId $vm.Id -MetricName "Network Out" -DetailedOutput -StartTime $st `
-EndTime $et -TimeGrain 12:00:00 -WarningAction SilentlyContinue
# 3 days == 72hours == 12*6hours
$cpu_total=0.0
$networkIn_total = 0.0
$networkOut_total = 0.0
foreach($c in $cpu.Data.Average)
{
#this is a average value for 12 hours, so total = $c*12 (or should be $c*12*60*60)
$cpu_total += $c*12
}
foreach($i in $in.Data.total)
{
$networkIn_total += $i
}
foreach($t in $out.Data.total)
{
$networkOut_total += $t
}
# add all the related info to the string
$s = "VM Name: " + $vm.name + "; Resource Group: " + $vm.ResourceGroupName + "; CPU: " +$cpu_total +"; Network In: " + $networkIn_total + "; Network Out: " + $networkOut_total
# add the above string to an array
$arr += $s
}
#check the values in the array
$arr
The test result:

Space
Is that we can able to fetch maximum usage on CPU with date using same script,
i have used to did below changes like call Maximum ...no luck..i hope some condition need to do you have solution for that
foreach($c in $cpu.Data.Maximum)
{
#this is a average value for 12 hours, so total = $c*12 (or should be $c*12*60*60)
$cpu_total += $c*12
#($c|measure -maximum).maximum
}

Related

Azure Powershell Question for Virtual Machine

I am reviewing a script that is supposed to delete a vm along with all of the resources attributed to the vm
Write-Host -NoNewline -ForegroundColor Green "Please enter the VM name you would like to remove:"
$VMName = Read-Host
$vm = Get-AzVm -Name $VMName
if ($vm) {
$RGName=$vm.ResourceGroupName
Write-Host -ForegroundColor Cyan 'Resource Group Name is identified as-' $RGName
#boot diagnostics container auto generated in storage account. Auto delete this storageURI property
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
Write-Host -ForegroundColor Cyan 'Marking Disks for deletion...'
$tags = #{"VMName"=$VMName; "Delete Ready"="Yes"}
$osDiskName = $vm.StorageProfile.OSDisk.Name
$datadisks = $vm.StorageProfile.DataDisks
$ResourceID = (Get-Azdisk -Name $osDiskName).id
New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
if ($vm.StorageProfile.DataDisks.Count -gt 0) {
foreach ($datadisks in $vm.StorageProfile.DataDisks){
$datadiskname=$datadisks.name
$ResourceID = (Get-Azdisk -Name $datadiskname).id
New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
}
}
if ($vm.Name.Length -gt 9){
$i = 9
}
else
{
$i = $vm.Name.Length - 1
}
$azResourceParams = #{
'ResourceName' = $VMName
'ResourceType' = 'Microsoft.Compute/virtualMachines'
'ResourceGroupName' = $RGName
}
$vmResource = Get-AzResource #azResourceParams
$vmId = $vmResource.Properties.VmId
$diagContainerName = ('bootdiagnostics-{0}-{1}' -f $vm.Name.ToLower().Substring(0, $i), $vmId)
$diagSaRg = (Get-AzStorageAccount | where { $_.StorageAccountName -eq $diagSa }).ResourceGroupName
$saParams = #{
'ResourceGroupName' = $diagSaRg
'Name' = $diagSa
}
Write-Host -ForegroundColor Cyan 'Removing Boot Diagnostic disk..'
if ($diagSa){
Get-AzStorageAccount #saParams | Get-AzStorageContainer | where {$_.Name-eq $diagContainerName} | Remove-AzStorageContainer -Force
}
else {
Write-Host -ForegroundColor Green "No Boot Diagnostics Disk found attached to the VM!"
}
Write-Host -ForegroundColor Cyan 'Removing Virtual Machine-' $VMName 'in Resource Group-'$RGName '...'
$null = $vm | Remove-AzVM -Force
Write-Host -ForegroundColor Cyan 'Removing Network Interface Cards, Public IP Address(s) used by the VM...'
foreach($nicUri in $vm.NetworkProfile.NetworkInterfaces.Id) {
$nic = Get-AzNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $nicUri.Split('/')[-1]
Remove-AzNetworkInterface -Name $nic.Name -ResourceGroupName $vm.ResourceGroupName -Force
foreach($ipConfig in $nic.IpConfigurations) {
if($ipConfig.PublicIpAddress -ne $null){
Remove-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name $ipConfig.PublicIpAddress.Id.Split('/')[-1] -Force
}
}
}
Write-Host -ForegroundColor Cyan 'Removing OS disk and Data Disk(s) used by the VM..'
Get-AzResource -tag $tags | where{$_.resourcegroupname -eq $RGName}| Remove-AzResource -force | Out-Null
Write-Host -ForegroundColor Green 'Azure Virtual Machine-' $VMName 'and all the resources associated with the VM were removed sucessfully...'
}
else{
Write-Host -ForegroundColor Red "The VM name entered doesn't exist in your connected Azure Tenant! Kindly check the name entered and restart the script with correct VM name..."
}
I had a question: what does this block of code exactly do:
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
I know it matches the storage uri, but how? And why is this needed? I am not sure what the .groups[1].value is referring to either
$diagSa =
[regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri,
'^http[s]?://(.+?).').groups[1].value
I know it matches the storage uri, but how?
You are using the [regex] type accelerator & match method () in the above expression.
The Match() method is a way to instruct PowerShell to attempt to match a string inside of another string. The Match() method has two parameters; the string you'd like to match on and the regular expression you'd like to test against.
Whenever a match is found and a regex group is used; (), the [regex] type accelerator has a Captures property. This Captures property then has a property called Groups. This is a collection that contains lots of attributes of what was matched. The second element in that collection contains the actual value that was matched.
what the .groups[1].value is referring to either
groups[1].values returns the storage account name where the boot diagnostics container resides.
And why is this needed?
When creating an Azure VM, you always have the option of creating a boot diagnostics container. This is useful to troubleshooting VM boot issues but doesn’t get removed when a VM is deleted. Let’s remedy that.
To remove the boot diagnostics container, you first need to figure out the name of the storage account the container resides on. To find that storage account, you’ll have to do some parsing of the storageUri property that’s exists in the DiagnosticsProfile object on the VM.
for more information about [regex]::match().group[1].value expression refer the below blog :
https://mcpmag.com/articles/2015/09/30/regex-groups-with-powershell.aspx

PowerShell - Azure Delete Reserved disks over 90 days

i am facing a mission in my work and she goes like this:
We have disks in our Azure account that they are attached to stopped and stopped(deallocated) vms. if am saying right they called Reserved disks.
The problem that we are still charged for this disks, i need your help with a PowerShell Script to look for this disks over xx days and than delete them.
my script for now looks like this.. please anyone that expert in PowerShell can help me here?
*** UPDATE - The mission i got have changed to list all the vms that are in status deallocated over xx days and than remove the disks that related to them.
# Get orphan managed disks
$managedDisks = Get-AzDisk
foreach ($md in $managedDisks) {
if (($md.ManagedBy -eq $null) -and ($md -notlike '*-ASRReplica')) {
$md | Remove-AzDisk -Force -verbose
}
}
Thank you all !!!
Per my understanding, you already get the way to filter all managed disks that have not been appended to a VM. And now, you want to know how to filter all managed disks that have not been used for 30 days.
For this requirement, we can query disk metrics: if a disk has been used in 30 days, there should be some metrics data(i,e read bytes and write bytes):
and if it has not been used, its metrics data in this period of time should be empty. So we can use PowerShell below to check:
#check disk read and write metrics log for each hour in past 30 days
$now = Get-Date -AsUtc
$m = Get-AzMetric `
-ResourceId '<managed disk resource ID>' `
-StartTime $now.AddDays(-30) `
-EndTime $now `
-TimeGrain 01:00:00 `
-MetricName 'Composite Disk Read Bytes/sec','Composite Disk Write Bytes/sec'
$readMetricsRecord = $m[0].Data
$writeMetricsRecord = $m[1].Data
if($readMetricsRecord.length -eq 0 -and $writeMetricsRecord.length -eq 0){
echo 'this disk has no usage record'
}else{
echo 'this disk has been used'
}
sharing with you the script guys , Get the vms in deallocated state over X days than , if they have a disk that is over X GB tag the vm and the disk .
$ids = New-Object System.Collections.ArrayList
$mergedTags = #{"Candidate"="Delete Me"}
$vms = (Get-AzVM -Status)
foreach ($vm in $vms ) {
$getStatuses = Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status
$getTodaysDate = Get-Date
$ts = New-TimeSpan -Start (($getStatuses.Statuses).Time).DateTime -End $getTodaysDate
[bool]$flag = 0
if (($vm.PowerState -eq "VM deallocated") -AND ($ts.Days -gt 30)) {
$ids.Add($vm.Id)
foreach ($disk in $getStatuses.Disks.Name) {
$diskSize = Get-AzDisk -ResourceGroupName $vm.ResourceGroupName -Name $disk
if ($diskSize.DiskSizeGB -gt 50) {
$flag = 1
$ids.Add($diskSize.Id)
if ($flag = 1) {
Update-AzTag -ResourceId $vm.Id -Tag $mergedTags -Operation Merge
Update-AzTag -ResourceId $diskSize.Id -Tag $mergedTags -Operation Merge
}
}
}
}
}
}

Azure Powershell Script

I have written a PowerShell script to print VM names with unmanaged disks however it's giving me an error. Appreciate any help on this -
$location=Read-Host -Prompt 'Input location for VMs'
$azuresubscription=Read-Host -Prompt 'Input Subscription Id'
$rmvms=Get-AzurermVM
# Add info about VM's from the Resource Manager to the array
foreach ($vm in $rmvms)
{
# Get status (does not seem to be a property of $vm, so need to call Get-AzurevmVM for each rmVM)
$vmstatus = Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status | where Location -like $location
# Add values to the array:
$vmarray += New-Object PSObject -Property #{`
# Subscription=$Subscription.SubscriptionName; `
Subscription=$azuresubscription.SubscriptionName; `
AzureMode="Resource_Manager"; `
Name=$vm.Name; PowerState=(get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")[1]); `
Size=$vm.HardwareProfile.VirtualMachineSize}
}
foreach ($vm in $vmarray)
{
$vmdiskstatus = (Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName).StorageProfile.OsDisk.ManagedDisk
if (!$vmdiskstatus) {Write-Host $vm.Name}
}
Error Message:
($vmarray is resulting in Null array) -
Cannot index into a null array.
Expected Output - $vmarray should have one VM as there is a running
instance in eastus (that's what I am using as value for $location)
As requested by Victor Silva to add my comment as answer, here goes:
You need to define the $vmarray as array before entering the loop to add objects to it.
Then, after that loop, the foreach ($vm in $vmarray) does have an array to index into, even if empty:
$location=Read-Host -Prompt 'Input location for VMs'
$azuresubscription=Read-Host -Prompt 'Input Subscription Id'
$rmvms=Get-AzurermVM
###################################################
# create an array variable to collect the result(s)
###################################################
$vmarray = #()
# Add info about VM's from the Resource Manager to the array
foreach ($vm in $rmvms)
{
# rest of your code
}

Azure Application Insights, how to change daily cap by Azure CLI

I'm trying to change daily cap for data transfer for all my Application Insights on Azure. Is there any way to change it for all of them?
I can't find how to do it by using Azure CLI.
Thank you.
You can change the daily cap with the Azure PowerShell cmdlet Set-AzureRmApplicationInsightsDailyCap.
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionName "Your Sub Name"
function Set-DailyCap {
$AI = Get-AzureRmApplicationInsights | Select ResourceGroupName, Name
$AI | foreach {
write-output ("Attempting to set daily cap for App Insights in resource group {0} instance {1}" -f $_.ResourceGroupName, $_.Name)
Set-AzureRmApplicationInsightsDailyCap -ResourceGroupName $_.ResourceGroupName -Name $_.Name -DailyCapGB 0.2
}
}
Set-DailyCap
Here is a modified version of #RonDBA's solution, which includes some logic to parse the names and set limits based on their name. Using this script, I was able to update hundreds of daily caps in a matter of seconds.
import-module azurerm.applicationinsights
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionName "yoursubscription here"
$ai = Get-AzureRmApplicationInsights | select ResourceGroupName, Name
$AI | foreach {
$cap = 1
$color = 'red'
if($_.Name -match 'dev'){
$cap = .12
$color = 'green'
}
if($_.Name -match 'stg'){
$cap = .24
$color = 'blue'
}
if($cap -eq 1)
{
if($_.Name -match 'api'){
$cap = 1.4
$color = 'yellow'
}
else{$cap = 2.9}
}
write-host ("Attempting to set daily cap at $cap for {0} instance " -f $_.ResourceGroupName) -NoNewline
write-host $_.Name -ForegroundColor $color
Set-AzureRmApplicationInsightsDailyCap -ResourceGroupName $_.ResourceGroupName -Name $_.Name -DailyCapGB $cap
}
There is no way you can change the daily cap of your application insights component using Azure CLI or even Azure REST APIs as of today.
To change it, use the Daily volume cap blade, linked from the Data
Volume Management blade (see below). Note that some subscription types
have credit which cannot be used for Application Insights. If the
subscription has a spending limit, the daily cap blade will have
instructions how to remove it and enable the daily cap to be raised
beyond 32.3 MB/day.
Data source/Reference:
https://learn.microsoft.com/en-us/azure/application-insights/app-insights-pricing#data-rate

Is there an Azure powershell cmdlet to get cores, cpu of an ARM VM in a subscription

I am trying to get the list of ARM VM's in a subscription using Get-AzureRmVM and their instance sizes using the HardwareProfile.VmSize object. Is there a way to get the #of Cpu, #of Cores etc. for each vm using a cmdlet ( like in classic using the Get-AzureRoleSize cmdlet) ?
Do you mean use command to get information like this?
PS C:\User> $size = (Get-AzureRmVM -ResourceGroupName ubuntu -Name vm1).HardwareProfile.VmSize
PS C:\Users> get-azurermvmsize -location eastus | ?{ $_.name -eq $size }
Name NumberOfCores MemoryInMB MaxDataDiskCount OSDiskSizeInMB ResourceDiskSizeInMB
---- ------------- ---------- ---------------- -------------- --------------------
Standard_DS1_v2 1 3584 2 1047552 7168
Here the complete solution if you want to get the Total Cores of multiple VMs:
# Calculating total Amount of Cores
Write-Output "Calculating the total Cores of VMs ..."
try {
$TotalCores = $null
$Location = "westeurope"
$Cores = $null
$TotalVMs = (Get-AzVM -Status | Where-Object { $_.ProvisioningState -eq "Succeeded" }) | Sort-Object -Property Name
foreach ($VM in $TotalVMs) {
Write-Output "Checking $($Vm.Name) ..."
$VMSize = (Get-AzVM -Name $VM.Name).HardwareProfile.VmSize
$Cores = (Get-AzVMSize -location $Location | Where-Object { $_.name -eq $VMSize }).NumberOfCores
$TotalCores += $Cores
}
Write-Output "Wow! Found '$TotalCores' Cores ..."
}
catch {
$ErrorMsg = "[ERROR] while calculating the total CPU Cores: $($_.Exception.Message)!"
Write-Error -Message $ErrorMsg
}

Resources