Read from txt file and convert to managed disks - azure

I've got a list of virtua machines in Azure which I'm trying to convert to managed disks.
I have a list of vm's, I read from the list and export to csv capturing resourcegroupname and vm name, however I seem to get vms from the whole subscription.
Also when I attempt to import the csv, when I run $comps it returns the correct information in the csv, however I can't seem to pass them through to the next lines.
CSV format is
ResouceGroupName Name
RG-01 vm-01
RG-01 vm-02
RG-01 vm-03
RG-01 vm-04
The code I'm trying is
Login-AzureRmAccount
$sub = Get-AzureRmSubscription | ogv -PassThru
Select-AzureSubscription -SubscriptionId $sub
$virtualmachines = Get-Content C:\temp\vm.txt | % {
Get-Azurermvm | select ResourceGroupName,Name | export-csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Append
}
$comps = Import-Csv c:\temp\Vm.csv |
foreach ($Comp in $comps)
{
Stop-AzureRmVM -ResourceGroupName $_.ResourceGroupName -Name $_.Name -Force
ConvertTo-AzureRmVMManagedDisk -ResourceGroupName $_.ResourceGroupName -VMName $_.Name
}
Thanks in advance..

For your issue, you export the virtual machines in a csv file and use it in the foreach code. So, it's unneccesary to use command:
$virtualmachines = Get-Content C:\temp\vm.txt | % {
Get-Azurermvm | select ResourceGroupName,Name | export-csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Append
}
And your VMs all in a resourcegroup, you can get them with ResourceGroupName directly.
For the pipeline in foreach, it's unneccesary. You can use the following code that I make a little change with your code and it works well.
Login-AzureRmAccount
$sub = Get-AzureRmSubscription | ogv -PassThru
Select-AzureRmSubscription -Subscription $sub
Get-Azurermvm –ResourceGroupName RG-01 | select ResourceGroupName,Name | export-csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Append
$comps = Import-Csv c:\temp\Vm.csv
foreach ($Comp in $comps)
{
Stop-AzureRmVM -ResourceGroupName $Comp.ResourceGroupName -Name $Comp.Name -Force
ConvertTo-AzureRmVMManagedDisk -ResourceGroupName $Comp.ResourceGroupName -VMName $Comp.Name
}
This is the screenshot of my result.

Related

How to split different values in powershell by a line

With this script i am able to fetch all the Tags that a VM has but i want that in output the each key and its value should be separated by a line in the way that each key and its value appears on different lines like this
reference image
# Sign into Azure Portal
connect-azaccount
# Fetch the Virtual Machines from the subscription
$azureVMDetails = get-azvm
# Fetch the NIC details from the subscription
$azureNICDetails = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
#Fetching Virtual Machine Details
$virtual_machine_object = $null
$virtual_machine_object = #()
#Iterating over the NIC Interfaces under the subscription
foreach($azureNICDetail in $azureNICDetails){
#Fetching the VM Name
$azureVMDetail = $azureVMDetails | ? -Property Id -eq $azureNICDetail.VirtualMachine.id
#Fetching the VM Tags
foreach($azureDetail in $azureVMDetails) {
$vm_tags = $azureVMDetail| Select-Object -Property (
#{name='Tags'; expression = {($_.tags.GetEnumerator().ForEach({ '{0} : {1}' -f $_.key, $_.value }) -join ';')}}
)
}
#VM Details export
$virtual_machine_object_temp = new-object PSObject
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "name" -Value $azureVMDetail.Name
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "comments" -Value ($vm_tags.Tags -join ';')
$virtual_machine_object += $virtual_machine_object_temp
}
#Report format and path
$virtual_machine_object | Export-Csv "C:\Users\JOHN\Desktop\Inventory\Final Scripts\VM_details_$(get-date -f dd.MM.yyyy).csv" -NoTypeInformation -Force
I tried to reproduce the same in my environment and got the results successfully by using the below PowerShell script:
$vmdeatil = Get-AzVm -Name testvm | Select -ExpandProperty Tags
$value = $vmdeatil
foreach($i in 0..($value.Count -1))
{
$ErrorActionPreference = ‘SilentlyContinue’
[array]$report += [pscustomobject] #{
key = $key[$i]
name = $value[$i]
}
}
$report | Export-Csv -Path "C:\Users\ruk1.csv" -NoTypeInformation
Response:
The output is successfully exported in the csv file like below:

How to loop through mulitple azure subscriptions parallelly

I am trying with nested ForEach-Object -Parallel to loop through multiple azure subscriptions parallelly and get data from all VMs in one go. I am using below code:
$SubsJob = Get-AzSubscription -WarningAction SilentlyContinue | Where-Object {$_.Name -match 'abc'} | ForEach-Object -Parallel {
$Context = Set-AzContext -Tenant $_.TenantId -SubscriptionId $_.SubscriptionId
[System.String]$ScriptBlock = {Get-Process}
$VMsJob = Get-AzVM | ForEach-Object -Parallel {
$FileName = $using:Context.Subscription.Name + "_$($_.Name)_" + (Get-Random) + ".ps1"
Out-File -FilePath $FileName -InputObject $using:ScriptBlock -NoNewline
$Output = Invoke-AzVMRunCommand -Name $_.Name -ResourceGroupName $_.ResourceGroupName -CommandId 'RunPowerShellScript' -ScriptPath $FileName
$PSCustomObject = [PSCustomObject]#{Subscription = $using:Context.Subscription.Name; ServerName = $_.Name; Output = $Output}
#Remove-Item -Path $FileName -Force -ErrorAction SilentlyContinue
Write-Output $PSCustomObject
} -ThrottleLimit 200 -AsJob
Write-Output $VMsJob
} -ThrottleLimit 200 -AsJob
I am not able to get it work, not sure what is wrong. One thing I observed while debugging is that, Get-AzVM command is getting VMs list from all the subscriptions rather than specific subscription. I came to know that by looking at the Out-File -FilePath $FileName which are generated.
sub1_server1_980337551.ps1
sub2_server1_42701325.ps1
server1 is only present in sub1 but it is being picked in sub2 as well.

Get Azure resource using filters

i'm trying to use Powershell to query my Storage Accounts by using name filter
I have tried these commands (and their variants) but have not still managed to get this working.
Get-AzStorageAccount | where -FilterScript {($_.ResourceType -eq "storageAccounts") -and ($_.StorageAccountName -contains "Prod") }
Get-AzResource -ResourceType Microsoft.Storage/storageAccounts | Get-AzResource -Name Prod* | ft
Any tips because I'm a bit lost. My goal would be that command / script would print out e.g all Storage Accounts which contains Prod in their name.
You can use Where-Object and -match to filter here:
Get-AzStorageAccount | Where-Object {$_.StorageAccountName -match 'prod'}
Or using -like:
Get-AzStorageAccount | Where-Object {$_.StorageAccountName -like '*prod*'}
If you really want to use Get-AzResource, then you need to filter by the Microsoft.Storage/storageAccounts resource type:
Get-AzResource -ResourceType "Microsoft.Storage/storageAccounts" | Where-Object {$_.Name -match 'prod'}
You can have a look at Matching Operators from about_comparison_operators for more information.

Azure PowerShell - get VM usage from across all subscriptions

I want to list all the VMs that generate costs in a specific timeframe or billing period.
I managed to create this script to get me the desired output:
$file="C:\temp\GeneratedCost-short.csv"
(az consumption usage list `
--start-date "2020-07-01" --end-date "2020-07-31" | ConvertFrom-Json)`
| Where-Object {$_.product -Match "Virtual Machines"}`
| Sort-Object -Property instanceName -Descending | Select-Object instanceName, subscriptionName`
| Get-Unique -AsString | ConvertTo-Csv -NoTypeInformation | Set-Content $file
But this will give me the output only for the current subscription.
How can I run on all the subscriptions that I have on the azure tenant?
I tried using the below version but it doesn't seem to work:
$file="C:\temp\GeneratedCost-short.csv"
$VMs = #()
$Subscriptions = Get-AzSubscription
foreach ($sub in $Subscriptions) {
Get-AzSubscription -SubscriptionName $sub.Name | az account set -s $sub.Name
$VMs += (az consumption usage list --start-date "2020-07-01" --end-date "2020-07-03" | ConvertFrom-Json)
}
#
$VMs | Where-Object {$_.product -Match "Virtual Machines"}`
| Sort-Object -Property instanceName -Descending | Select-Object instanceName, subscriptionName`
| Get-Unique -AsString | ConvertTo-Csv -NoTypeInformation | Set-Content $file
Any suggestions?
Mixing the Azure PowerShell module and Azure CLI could be causing issues with your code if the accounts haven't been retrieved between the two. Verify that az cli has the proper subscriptions
az account list -o table
If you don't see the accounts be sure to re-run az login.
Here's your code with the azure cli only
$file="C:\temp\GeneratedCost-short.csv"
$VMs = #()
az account list -o json | ConvertFrom-Json |
ForEach-Object {
Write-Host "Getting usage for account: " $_.Name
az account set -s $_.Name
$VMs += (az consumption usage list --start-date "2020-07-01" --end-date "2020-07-03" | ConvertFrom-Json)
}
$VMs | Where-Object {$_.product -Match "Virtual Machines"} |
Sort-Object -Property instanceName -Descending |
Select-Object instanceName, subscriptionName |
Get-Unique -AsString | ConvertTo-Csv -NoTypeInformation |
Set-Content $file
never do += on an array, worst pattern ever.
[System.Collections.Generic.List[PSObject]]$VMs = #()
$subs = Get-AzSubscription # | Where-Object {$_.State -eq 'Enabled'}
foreach ($s in $subs) {
Set-AzContext -SubscriptionObject $s | Out-Null
$vm = # your search here ...
$VMs.Add($vm)
}

Output Value from select-object calculated value

I've used a hash table to calculate some values for my VMWare inventory script, but now when I output the data, it records it as a key/value pair. I'd like to dump just the value. When I simply take what I'm handed that works fine, but when I get picky PS starts to stonewall me. :-)
Here is the relevant part of the script.
foreach ($machine in $vmList) {
$vmname = $machine.Name
$properties = #{
'Name'=Get-VM $vmname | Select -ExpandProperty Name
'RAM'=Get-VM $vmname | Select -ExpandProperty MemoryGB
'CpuCount'=Get-VM $vmname | Select -ExpandProperty NumCpu
'UsedDiskGB'=Get-VM $vmname | Select-Object #{n="UsedDiskGB"; e={[math]::Round( $_.UsedSpaceGB, 3 )}}
'TotalDiskGB'=Get-VM $vmname | Select-Object #{n="TotalDiskGB"; e={[math]::Round((Get-HardDisk -vm $_ | Measure-Object -Sum CapacityGB).Sum)}}
'Networks'=Get-VM $vmname | Select-Object #{n="Networks"; e={(Get-NetworkAdapter -VM $_ |Sort-Object NetworkName |Select -Unique -Expand NetworkName) -join '; '}}
'OS'=(Get-VM -Name $vmname | Get-View).summary.config.guestFullName
}
$object=New-Object -TypeName PSObject -Prop $properties
Export-Csv -Path $WorkDir\vms.csv -Append -Encoding UTF8 -InputObject $Object
Write-Output $Object
}
How do I get UsedDiskGB, Networks and TotalDiskGB to display just the value instead of something like '#{TotalDiskGB=80}'? Ram, OS, CpuCount and Name work exactly as desired already.
Also, suggestions on doing this in a faster way are welcome. I'm sure all these calls can be done better. I had it done in a single line, but then they asked for OS to be added and that changed everything.
Easy, but bad way:
In the expression pipe to |Select -ExpandProperty <property name> to get just the value. Such as:
'TotalDiskGB'=Get-VM $vmname | Select-Object #{n="TotalDiskGB"; e={[math]::Round((Get-HardDisk -vm $_ | Measure-Object -Sum CapacityGB).Sum)}}|select -expand totaldiskgb
The better way:
Structure your properties better to start with. Try this:
'TotalDiskGB'= [math]::Round((Get-HardDisk -vm (Get-VM $vmname) | Measure-Object -Sum CapacityGB).Sum)
The reason you're having issues is because you are creating a PSCustomObject with your Select, and Totaldiskgb is a property of that object. You don't want to make an object, you just want the value of that property.
Edit: Thank you to #briantist for pointing out that Get-VM $vmname should be called once, and stored as an object to be used later, rather than called for each time it is needed for a member of $Properties. For example:
foreach ($machine in $vmList) {
$vmname = $machine.Name
$vmobject = Get-VM $vmname
$properties = #{
'Name'=$vmobject | Select -ExpandProperty Name
'RAM'=$vmobject | Select -ExpandProperty MemoryGB
'CpuCount'=$vmobject | Select -ExpandProperty NumCpu
'UsedDiskGB'=[math]::Round( $vmobject.UsedSpaceGB, 3 )
'TotalDiskGB'=[math]::Round((Get-HardDisk -vm $vmobject | Measure-Object -Sum CapacityGB).Sum)
'Networks'=(Get-NetworkAdapter -VM $vmobject |Sort-Object NetworkName |Select -Unique -Expand NetworkName) -join '; '
'OS'=($vmobject | Get-View).summary.config.guestFullName
}
$object=New-Object -TypeName PSObject -Prop $properties
Export-Csv -Path $WorkDir\vms.csv -Append -Encoding UTF8 -InputObject $Object
Write-Output $Object
}

Resources