How delete VM Azure using tags using powershell? - azure

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

Related

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

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.

How to get the list of azure servers having Auto-Shutdown disabled using PowerShell?

I want to get the list of azure servers having auto-shutdown disabled on them, I have the below script but the issue with the script is that it gets the list of RG's under the Subscription GUID but repeats the output after every loop.
Import-AzureRmContext -Path "$PSScriptRoot\AzureProfile.json"
Select-AzureRmSubscription -SubscriptionId {subscriptionId}
[array]$ResourceGroupArray = Get-AzureRMVm | Select-Object -Property ResourceGroupName, Name, VmId
foreach ($resourceGroup in $ResourceGroupArray){
$targetResourceId = (Get-AzureRmVM -ResourceGroupName $resourcegroup.ResourceGroupName -Name $resourceGroup.Name).Id
$shutdownInformation = (Get-AzureRmResource -ResourceGroupName $resourcegroup.ResourceGroupName -ResourceType Microsoft.DevTestLab/schedules -Expandproperties).Properties
Write-Host "ID: " $targetResourceId
$shutdownInformation
The output for each VM is displayed in the following format,
What I want is simple, I want the VM name and its status of Auto-shutdown to be displayed on the screen so that its easy for me to find out which all VM have auto-shutdown currently disabled on them.
Any help related to this would be helpful.
You just need to get the microsoft.devtestlab/schedules resource ID using:
/subscriptions/{subscriptionId}/resourceGroups/{rgName}/providers/microsoft.devtestlab/schedules/shutdown-computevm-{vmName}
Then iterate over all your VMs using Get-AzVM, Get the microsoft.devtestlab/schedules resource using Get-AzResource, then output VM name and status into a table using Format-Table.
$subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Set-AzContext -SubscriptionId $subscriptionId
& {
foreach ($vm in Get-AzVM) {
try {
$shutdownResource = Get-AzResource `
-ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
-ErrorAction Stop
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $shutdownResource.Properties.status
}
}
catch {
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $_.Exception.Message
}
}
}
} | Format-Table -AutoSize
To set the context to the correct subscription, we can use Set-AzContext.
The above however is using the latest Az modules. You can do the same using the equivalent AzureRm modules.
$subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Set-AzureRmContext -SubscriptionId $subscriptionId
& {
foreach ($vm in Get-AzureRmVM) {
try {
$shutdownResource = Get-AzureRmResource `
-ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
-ErrorAction Stop
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $shutdownResource.Properties.status
}
}
catch {
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $_.Exception.Message
}
}
}
} | Format-Table -AutoSize
Although I do recommend moving to the Az module since support for AzureRm is ending December 2020. You can read the documentation for more information about this.
The above code should give you an output similar to the following
VMName ShutdownStatus
------ --------------
vm1 Enabled
vm2 Disabled
Update
The Call operator & is used here to run the for loop as a script block. You can read more about this in about_Script_Blocks.
Try something like this to get the auto-shutdown status of all VMs. Instead of trying to get the schedules inside the loop, get all the ones in the subscription and match them based on the VM's full resource Id.
[array]$VMArray = Get-AzureRMVm | Select-Object -Property ResourceGroupName, Name, VmId, Id
$ShutdownInformation = (Get-AzureRmResource -ResourceType Microsoft.DevTestLab/schedules -Expandproperties).Properties
foreach($vm in $VMArray) {
$ShutdownStatus = "Not Configured"
$Schedule = $ShutdownInformation | Where-Object { $_.targetResourceId -eq $vm.Id } | Select -First 1
if($Schedule -ne $null) {
$ShutdownStatus = $Schedule.status
}
Write-Host $vm.VmId $ShutdownStatus
}

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Easier way of retrieving an Azure VM's Public IP address

Using the name/resource group of a specific VM, I'm trying to get the VM's public IP address.
This code works but it seems unwieldy in comparison to other AzureRM cmdlets.
$VM = Get-AzureRmVM -ResourceGroupName MyResourceGroup -Name MyVMName
$NIC = $VM.NetworkProfile.NetworkInterfaces[0].Id -replace '.*\/'
$NI = Get-AzureRmNetworkInterface -Name $NIC -ResourceGroupName MyResourceGroup
$NIIC = Get-AzureRmNetworkInterfaceIpConfig -NetworkInterface $NI
$PIP = $NIIC.PublicIpAddress.Id -replace '.*\/'
$PIP = Get-AzureRmPublicIpAddress -Name $PIP -ResourceGroupName MyResourceGroup
$PIP.IpAddress
Is there a quicker/easier/shorter way of accessing this information?
As far as i know, Not Yet for PowerShell. But you can use Azure CLI
az vm list-ip-addresses -n <VMName> -g <ResourceGroup> | grep publicIpAddresses
Try the Azure CLI command:
az vm list-ip-addresses -g groupName -n vmName --query "[].virtualMachine.network.publicIpAddresses[*].ipAddress" -o tsv
Or the PowerShell command just filter with your vm name:
$ipAddress= (Get-AzureRmPublicIpAddress -ResourceGroupName groupName | Where-Object { $_.IpConfiguration.Id -like "*vmName*" }
)
$ipAddress.IpAddress
It's possible. This script will list all VMs PIP in your Azure cloud.
OLD
$VM_int = Get-AzureRmResource -ODataQuery "`$filter=resourcetype 'Microsoft.Compute/virtualMachines'"
foreach($int in $VM_int){
$vmName = $int.Name
$ipAddress= (Get-AzureRmPublicIpAddress -ResourceGroupName $int.ResourceGroupName | Where-Object { $_.IpConfiguration.Id -like "*$vmName*" })
$vmName + ' --- ' + $ipAddress.IpAddress
}
UPDATE
Unfortunately, Get-AzVM doesn't provide the Public IP address of VM, but we can scrape its Network Interface Name and make a wildcard search of it through all assigned Public IPs which NIC name are matched.
It's not fast but will provide with correct results.
$array = #()
foreach ($vm in Get-AzVM) {
$vmNicName = $vm.NetworkProfile.NetworkInterfaces.Id.Split("/")[8]
$ipAddress = Get-AzPublicIpAddress | Where-Object {$_.IpConfiguration.Id -like "*$vmNicName*"}
if ($null -ne $ipAddress) {
$pipInput = New-Object psobject -Property #{
VM = $vm.Name
PublicIP = $ipAddress.IpAddress
}
$array += $pipInput
}
}
The way i got the value for my Linux VM's was using below code.
Get-AzureRmPublicIpAddress -ResourceGroupName <yourRG> -Name <yourVMName> | Select-Object {$_.IpAddress}
This will return something of this sort:
$_.IpAddress
------------
52.170.56.60
This outputs a bit of information however the public IP address is in there.
Get-AzPublicIpAddress -ResourceGroupName MyResourceGroup | Where-Object {$_.name -like "*MyVMName*" }
Or you can do this to just get the IP address:
Get-AzPublicIpAddress -ResourceGroupName MyResourceGroup | Where-Object {$_.name -like "*MyVMName*" } | Select-Object { $_.IpAddress }
Output is like:
$_.IpAddress
--------------
13.255.162.33
You can also match the AzPublicIpAddress IpConfiguration.Id with the VM's NetworkInterfaces.Id:
Get-AzPublicIpAddress | ?{$_.IpConfiguration.Id -match "$((Get-AzVM -Name $computername).NetworkProfile.NetworkInterfaces.Id).*" }
#Get the VM object
$vm = Get-AzVM -Name $vmName -Status
#Get name of network adapter object attached to VM
$NetworkInterfaceName = $vm.NetworkProfile.NetworkInterfaces.Id.Split("/") | Select -Last 1
#Get network adaptor object attached to VM
$NetworkInterfaceObject = Get-AzNetworkInterface -Name $NetworkInterfaceName
#Get public IP Address object name attached to network adaptor object
$ipObjectName = $NetworkInterfaceObject.IpConfigurations.PublicIpAddress.Id.Split("/") | Select -Last 1
#get publivc IP Address attached to public IP Address object
$ipObject = Get-AzPublicIpAddress -ResourceGroupName $resourceGroupName -Name $ipObjectName
Write-Output $ipObject.IpAddress
Yet another method from within a Linux VM.
First, install the Azure command-line tools in the VM, see Azure docs
Second, execute the following in a shell on the VM:
az network public-ip list --query "[?dnsSettings.domainNameLabel=='MY_VM']"
where MY_VM is (hopefully) the host name of your VM. The command returns a multiline JSON string which is a list. Example is shown below:
[
{
"dnsSettings": {
"domainNameLabel": "MY_VM",
"fqdn": "my_vm.westeurope.cloudapp.azure.com"
},
"etag": "W/\"some_uuid...\"",
...
"ipAddress": "AAA.BBB.CCC.DDD",
},
...
]
How to parse the FQDN and the public IP out of this is left as an exercise to the reader :-)

Resources