Deallocate Azure VMSS based on tag and current powerstate - azure

I am attempting to get a list of VMSS that have a specific tag and are still powered/allocated and then deallocate those VMSS.
I have not seen a property in Get-AzVmss that shows the allocation or power state of the VMSS.
I did however find if I dig in to the instances themselves I can get the powerstate of them using Get-AzVmssVM
I am able to successfully get this to occur at the instance level and power the instances off, but I would like to deallocate the VMSS itself.
This will be part of a DevOps deployment pipeline so I need to ensure it's reliable and consistent. It will be run as an Azure Powershell Task.
Anyone able to assist in what I am missing here? I would love to do this a layer up and not even get in to the instances, but I could not see how to do that (assuming it is possible).
Here is the code I have so far:
$RedTagValue = "Red"
$RGName = "test-rg"
$Resources = Get-AzVmss -ResourceGroupName $RGName | Where-Object { $_.Tags.Values -eq $RedTagValue }
foreach ($Resource in $Resources) {
$vmss = Get-AzVmssVM -ResourceGroupName $RGName -VMScaleSetName $Resource.Name
foreach ($vm in $vmss) {
$instances = Get-AzVmssVM -ResourceGroupName $RGName -VMScaleSetName $Resource.Name -InstanceId $vm.InstanceId -InstanceView
if ($instances.Statuses[1].Code -notcontains "PowerState/deallocated") {
Write-Output "Turning off" #Need some code here to output the VMSS that are being turned off and also some logic to turn them off
}
else {
Write-Output "No Machines to turn Off"
}
}
}

Stop-AzVmss -ResourceGroupName $RGName -VMScaleSetName $Resource.Name -InstanceId $vm.InstanceId -Force
You need add the above stop-azvmss cmdlet in the If block in your script to stop a particular vmss instance.
Instead of Hardcoding the ResourcegroupName in your script, we have made some changes to it.
This new Script will validate the instance status whether are running or not. if instance are in running state then the script will trigger stop-azvmss cmdlets to deallocate those instance.
Here is the Modified PowerShell Script :
$RedTagValue = "Red"
$Resources = Get-AzVmss| Where-Object { $_.Tags.Values -eq $RedTagValue }
foreach ($Resource in $Resources) {
$vmss = Get-AzVmssVM -ResourceGroupName $Resources.ResourceGroupName -VMScaleSetName $Resource.Name
foreach($vm in $vmss){
$instanceId=Get-AzVmssVM -ResourceGroupName $Resources.ResourceGroupName -VMScaleSetName $Resource.Name -InstanceId $vm.InstanceId -InstanceView
if($instanceId.Statuses[1].Code -eq 'PowerState/running'){
Write-Host "Turnning OFF","$($vm.Name)"
Stop-AzVmss -ResourceGroupName $Resources.ResourceGroupName -VMScaleSetName $Resource.Name -InstanceId $vm.InstanceId -Force
}
else {
Write-Host "$($Resource.Name)","Virtual Machines are already turned off"
}
}
}
Here is the sample Output for reference:

Related

How delete VM Azure using tags using powershell?

How do I delete a VM using tags? Let's say there is a VM with the tags "Name:Surname". How can I delete this VM without using the VM name or ID. Namely deletion using tags.
I try to use:
get-azvm -ResourceGroupName "ResourceGroup" | Where-Object {$_.Tags -like "[Name, blabla], [Surname, blabla]"}
but it didn't find that VM
I have reproduced in my environment. Firstly, you need to find the Virtual Machine using the below command:
xx- Name of the resource group
hello- tag name
get-azvm -ResourceGroupName "xx" | Where-Object {$_.Tags['hello']}
After getting the VM name you can use the below command to delete the VM:
xx- Name of the resource group
yy- Name of the vm.
Remove-AzVM -ResourceGroupName "xx" -Name "yy"
Then type Y(yes) to delete the VM as below:
References taken from:
https://learn.microsoft.com/en-us/powershell/module/az.compute/remove-azvm?view=azps-8.2.0#example-1-remove-a-virtual-machine
https://learn.microsoft.com/en-us/powershell/module/az.compute/get-azvm?view=azps-8.2.0
Based on this,
You could do something like this:
$Surname= 'Test'
$VMs = Get-AzVM -ResourceGroupName 'myRG'
foreach ($VM in $VMs)
{
[Hashtable]$VMTag = (Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name).Tags
foreach ($h in $VMTag.GetEnumerator()) {
if (($h.Name -eq "Name") -and ($h.value -eq $Surname))
{
Write-host "Removing VM" $VM.Name
Remove-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Force -Confirm:$false
}
}
}

Get Azure VM details by filtering using tags in powershell

I will like to use the Get-AzVm command to get list of VMs having a specific tag.
I have tried Get-AzVM | Where-Object {$_.Tags['Resource'] -eq "test"}
Still does not return VMS with the tag "Resource:test"
The output of get-azvm doesn't produce Tags for VM. But, Get-AzVM -ResourceGroupName ResourceGroupName -Name VMName does that.
So you need to loop through VMs, store the VM tag in a hashtable and then enumerate through the hastable to check your desired tag with value is there. Here goes the code-
$VMs = get-azvm
foreach ($VM in $VMs)
{
[Hashtable]$VMTag = (Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name).Tags
foreach ($h in $VMTag.GetEnumerator()) {
if (($h.Name -eq "Resource") -and ($h.value -eq "test"))
{
Write-host "VM with tags Resource:test are" $VM.Name
}
}
}

Powershell script to get list of Running VM's and stop them

Am using this script, but its gathering all the vms and stopping it one by one even when the VM is already in stopped state
$vm = Get-Azvm
foreach($vms in $vm)
{
$resource = Get-Azvm | where {$_.Statuses -eq "Running"}
if($resource -ne $null)
{
Write-Output "Stopping virtual machine..." + $vms
Stop-AzVM -ResourceGroupName $resource.ResourceGroupName -Name $vms -Force
}
else
{
Write-output "Virtual machine not found:" + $vms
}
}
Based on the above shared requirement , we have modified the PowerShell script to check the virtual machines status ( whether it is running or not ), if virtual Machine is running you need to stop it using stop-Azvm cmdlet.
Checked the below script(while testing we passed resource group flag to the Get-Azvm ) in our local environment which is working fine.
$vm = Get-Azvm -Status
foreach($vms in $vm)
{
$statuscheck = Get-AzVM -ResourceGroupName $vms.ResourceGroupName -Name $vms.Name -Status
if($statuscheck.Statuses.DisplayStatus[1] -eq "VM running")
{
Write-Output "Stopping virtual machine...$($vms.Name)"
Stop-AzVM -ResourceGroupName $vms.ResourceGroupName -Name $vms.Name -Force
}
else
{
Write-output "Virtual machine $($vms.Name) is already in stopped state"
}
}
Here is the sample output for reference:

Lock azure resource with PowerShell

I've been trying to run a script to create a lock on azure resource to prevent resources being deleted inadvertently.
I get an error message and I can't figure out why it's showing me this error message.
Script:
#Sign in to Azure account
Login-AzAccount
#Select the subscription you want to work on
Select-AzSubscription -Subscription "test.subscription"
#Get All Resources in a resource group
$Resources = Get-AzResource -ResourceGroupName dummy_rg | Format-Table
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($null -eq $lck)
{
Write-Host "$ResourceName has no lock"
New-AzResourceLock -resourceGroupName $rg -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
Error message:
Gaurav request result:
#Start logging
Start-Transcript -Path "C:\Windows\Logs\Lock - $(((get-date).ToUniversalTime()).ToString("yyyy-MM-dd_hh-mm-ss")).log" -Force
#Connect to Azure account
Login-AzAccount
#Select Azure subscription
Set-AzContext -Subscription "subscription_id_numbers"
#Deny rule on Azure Data Factory and Azure Machine Learning
$Resources = Get-AzResource | Where-Object {$_.Name -NotLike '*adf*' -and $_.Name -NotLike '*aml*'}
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($lck -eq $null)
{
Write-Host "$ResourceName has no lock"
Set-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
#Stop Logging
Stop-Transcript
This will loop on every ressources except azure data factory in the tenant and create a "delete" type lock to make sure resources aren't deleted inadvertently.
Read comments in each section to understand the code.

How to connect multiple Azure VMs to log analytics workspace using ARM template?

I can able to connect the Azure VM to the log analytics workspace using the ARM template(https://learn.microsoft.com/en-us/azure/azure-monitor/agents/resource-manager-agent) but I want to connect the multiple VMs at a time in one subscription and different resource groups to the log analytics workspace.
Is there any way to work around this?
If you want to add a bunch of VMs in a subscription to a log analytics workspace in Azure, we can use PowerShell command Set-AzVMExtension to implement it.
For example
# all windows VMs in the subscription (which you set via Set-AzContext)
$PublicSettings = #{ "workspaceId" = "" }
$ProtectedSettings = #{ "workspaceKey" = "" }
# Using -Status switch to get the status too
Get-AzVM -Status | Where-Object{ $_.Powerstate -eq "VM running" -and $_.StorageProfile.OsDisk.OsType -eq "Windows" } | ForEach-Object {
$VMName = $_.Name
$ResourceGroupName = $_.ResourceGroupName
$Location = $_.Location
Write-Host "Processing $VMName"
Set-AzVMExtension -ExtensionName "MicrosoftMonitoringAgent" `
-ResourceGroupName "$ResourceGroupName" `
-VMName "$VMName" `
-Publisher "Microsoft.EnterpriseCloud.Monitoring" `
-ExtensionType "MicrosoftMonitoringAgent" `
-TypeHandlerVersion 1.0 `
-Settings $PublicSettings `
-ProtectedSettings $ProtectedSettings `
-Location "$Location"
}
For more details, please refer to here and here.

Resources