Know Your Azure VM Created Date Using PowerShell & AZCli

Do you want know when was your Azure VM created? Then this script will retrieve date time created for the given Azure VM(s). Not sure whether there is direct way to retrieve the VM created date, but I couldn’t find any CmdLet to know the VM created date. However, I have written a PowerShell function to know the VM created date by considering the VM OS disk creation date as VM creation date. The function accepts the combination of Resource Group Name and VM Name as mandatory parameters or VM object(s), and you will see the output as below… And even I have tried the same using Azure Cli as well, and you get the output like this… And, here’s the script… PowerShell AZCli <# This script pulls the date and the time on which the Azure VM(s) created. This script accepts Resource Group & VM Name as mandatory parameters and accepts VM object(s) optionally. Since there is no direct Cmdlet to fetch the create date, it is considered the disk create date as VM create date. #> Function Get-AzVMCreateDate { [CmdletBinding()] param ( [parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string] $ResourceGroupName, # Resource Group Name [parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [string] $Name, # VM Name [parameter(Mandatory=$false, ValueFromPipeline=$true)] [System.Object[]] $VMObject # VM Object ) Begin { # Check if the VM Object is from the pipeline $IsItVMObject = $null -ne $VMObject # Checking login, if not asking for the login if (($IsItVMObject -eq $false) -and ($null -eq $(Get-AzContext -ErrorAction SilentlyContinue))) { Login-AzAccount } # Output array object $VMArray = @() } Process { # Fetching the VM details from Resource Group Name and VM Name if provided if ($IsItVMObject -eq $false) { $VMObject = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $Name } foreach ($VM in $VMObject) { # Get the OS Disk Name $VMDiskName = $VM.StorageProfile.OsDisk.Name # Get the Disk Info $VMDiskInfo = Get-AzDisk -ResourceGroupName $VM.ResourceGroupName -DiskName $VMDiskName # Get disk create date & time $VMCreatedDate = $VMDiskInfo.TimeCreated # Add result to the output array $VMArray += New-Object -TypeName psobject -Property @{ ResourceGroup = $VM.ResourceGroupName VMName = $VM.Name CreateDate = $VMCreatedDate } } } End { # Output return ($VMArray | Select-Object ResourceGroup, VMName, CreateDate) } } <# Load the function PS /> . ./Get-AzVMCreateDate.ps1 # on Linux PS \> . .\Get-AzVMCreateDate.ps1 # on Windows #> <# Calling the function PS > Get-AzVMCreateDate #> # Login to your Azure Subscription #az login # Declare variables resourceGroupName='LINUX-RG' vmName='ubuntu01' # Get VM OS disk name vmdiskname=$(az vm show --resource-group $resourceGroupName --name $vmName -d --query "storageProfile.osDisk.name" -o tsv) # Get VM OS disk create date createDate=$(az disk show --resource-group LINUX-RG --name $vmdiskname --query "timeCreated" -o tsv) # Convert the date to readable format createDatef=$(date -d $createDate '+%Y/%m/%d %T') # Output printf "%-20s | %-20s | %-20s\n" "$resourceGroupName" "$vmName" "$createDatef"

26 September 2019

Create New Azure VM Using PowerShell(Az)

Deploying the Virtual Machines in the Azure cloud using the templates is the best way to create the VM to satisfy the attributes like quick, consistent, reusable and handles the dependency among the resources. However PowerShell has the flexibility to deploy the VMs with ease and allows the user to choose the required parameters necessary for the particular deployment alone without even touching the code. Ofcourse this approach is also quick and reusable, but the user has to ensure the consistency and dependency among the resources if required while creating the resources in the Azure cloud. Since the new Azure PowerShell Module Az 1.0.1 is released, I have written the scripts using the Az module CmdLets. So please install Az module on Windows PowerShell or PowerShell Core, import the module and connect to Azure account using Connect-AzAccount. Add required parameters to the script… #requires -Modules Az param ( [Parameter(Mandatory=$true)] [string] $ResourceGroupName, # Resource Group [Parameter(Mandatory=$true)] [string] $VMName, # VM Name [Parameter(Mandatory=$true)] [string] $Location, # Location [Parameter(Mandatory=$true)] [ValidateSet('Windows','Linux')] [string] $OSType, # OS Type (Windows/Linux) [Parameter(Mandatory=$true)] [string] $VirtualNetworkName, # VNet [Parameter(Mandatory=$true)] [string] $SubnetName, # Subnet [Parameter(Mandatory=$true)] [string] $SecurityGroupName, # NSG [Parameter(Mandatory=$false)] [string] $VMSize, # VM Size [Parameter(Mandatory=$false)] [switch] $AssignPublicIP, # Assign PIP [Parameter(Mandatory=$false)] [pscredential]$VMCredential, # VM login credential [Parameter(Mandatory=$false)] [Int[]] $AllowedPorts # NSG rules ) Ensure you are connected to Azure subscription, if the script exits then connect to Azure subscription using Connect-AzAccount CmdLet, and this is a browser-based authentication. # Verify Login if( -not $(Get-AzContext) ) { return } Ensure that there is no existing vm with the same name in the resource group. If there is a VM already exists then exit the script. # Verify VM doesn't exist $VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -ErrorAction SilentlyContinue if($null -ne $VM) { return } Create VM login credentials, if not provided along with the script… # Create user object if (-not $PSBoundParameters.ContainsKey('VMCredential')) { [pscredential] $VMCredential = Get-Credential -Message 'Please enter the vm credentials' } # Verify credential if ($VMCredential.GetType().Name -ne "PSCredential") { return } The script identifies the existing resources with the names provided, if exist then they will be used and if they don’t exist then will be created with different names. Two things that you need to choose based on your requirements, one is the VM Size and the other is OS Image (Sku)… # Lists all the VM Sizes available in South India region PS C:\> Get-AzVMSize -Location southindia To retrieve the OS Skus, I have written an another post List of available Azure VM Image skus using new Azure PowerShell module Az , please refer to it… Now the main block starts from here… # Verify/Create a resource group $ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue if ($null -eq $ResourceGroup) { $ResourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location } # Verify the virtual network $VNet = Get-AzVirtualNetwork -Name $VirtualNetworkName -ResourceGroupName $ResourceGroup.ResourceGroupName -ErrorAction SilentlyContinue if ($null -eq $VNet) { [Microsoft.Azure.Commands.Network.Models.PSSubnet] $SubnetConfig = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix $VNet = New-AzVirtualNetwork -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -Name $VirtualNetworkName -AddressPrefix -Subnet $SubnetConfig } else { $Subnets = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $VNet $SubnetConfig = $Subnets | Where-Object -FilterScript {$_.Name -eq $SubnetName} if ($null -eq $SubnetConfig) { $VNetAddressPrefixes = $VNet.AddressSpace.AddressPrefixes $AddressPrefix = @($VNetAddressPrefixes.Split('.')) $AddressPrefix[2] = [int]($Subnets.AddressPrefix|Measure-Object -Maximum).Maximum.ToString().Split('.')[2] + 1 $AddressPrefix = $AddressPrefix -join '.' $VNet | Add-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix $AddressPrefix | Set-AzVirtualNetwork } } $Subnet = Get-AzVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $VNet # Create a public IP address and specify a DNS name if ($PSBoundParameters.ContainsKey('AssignPublicIP')) { [string] $PipName = $VMName + '-pip' $VerifyPip = Get-AzPublicIpAddress -Name $PipName -ResourceGroupName $ResourceGroup.ResourceGroupName -ErrorAction SilentlyContinue if ($null -ne $VerifyPip) { $PipName = $VMName + '-pip-' + $(Get-Random).ToString() } $PublicIP = New-AzPublicIpAddress -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -Name $PipName -AllocationMethod Static -IdleTimeoutInMinutes 4 } # Create/Select a network security group $NSG = Get-AzNetworkSecurityGroup -Name $SecurityGroupName -ResourceGroupName $ResourceGroup.ResourceGroupName -ErrorAction SilentlyContinue if ($null -eq $NSG) { # Create an inbound network security group rules if ($PSBoundParameters.ContainsKey('AllowedPorts')) { [System.Array] $NsgRules = @() [int] $Priority = 1000 foreach ($Port in $AllowedPorts) { $Rule = New-AzNetworkSecurityRuleConfig -Name "Allow_$Port" -Protocol Tcp -Direction Inbound -Priority $Priority -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $Port -Access Allow $Priority++ $NsgRules += $Rule } $NSG = New-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -Name $SecurityGroupName -SecurityRules $NsgRules } else { $NSG = New-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -Name $SecurityGroupName } } else { # Add an inbound network security group rules, if missing any if ($PSBoundParameters.ContainsKey('AllowedPorts')) { $NSGAllowedPorts = $NSG.SecurityRules | Where-Object -FilterScript {$_.Access -eq "Allow"} | Select-Object -ExpandProperty DestinationPortRange $PortsToAllow = $AllowedPorts | Where-Object -FilterScript {$_ -notin $NSGAllowedPorts} $Priority = ($NSG.SecurityRules.Priority|Measure-Object -Maximum).Maximum + 100 if ($PortsToAllow.Count -gt 0) { foreach($Port in $PortsToAllow) { $NSG | Add-AzNetworkSecurityRuleConfig -Name "Allow_$Port" -Protocol Tcp -Direction Inbound -Priority $Priority -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $Port -Access Allow | Set-AzNetworkSecurityGroup } } } } # Create a virtual network card and associate with public IP address and NSG $NICName = "$VMName-nic" $NIC = Get-AzNetworkInterface -Name $NICName -ResourceGroupName $ResourceGroup.ResourceGroupName -ErrorAction SilentlyContinue if ($null -ne $NIC) { $NICName = $VMName + "-nic-" + $(Get-Random).ToString() } $NIC = New-AzNetworkInterface -Name $NICName -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -SubnetId $Subnet.Id -NetworkSecurityGroupId $NSG.Id if ($PSBoundParameters.ContainsKey('AssignPublicIP')) { $NIC | Set-AzNetworkInterfaceIpConfig -Name $NIC.IpConfigurations[0].Name -PublicIpAddressId $PublicIP.Id -SubnetId $Subnet.Id | Set-AzNetworkInterface | Out-Null } # VM Size if($PSBoundParameters.ContainsKey('VMSize') -eq $false ) { $VMSize = 'Standard_A1' } # OS Type $VMSourceImage = @{PublisherName='';Offer='';Sku=''} switch ($OSType) { 'Windows' { $VMSourceImage.PublisherName = 'MicrosoftWindowsServer' $VMSourceImage.Offer = 'WindowsServer' $VMSourceImage.Sku = '2016-Datacenter' } 'Linux'{ $VMSourceImage.PublisherName = 'Canonical' $VMSourceImage.Offer = 'UbuntuServer' $VMSourceImage.Sku = '18.10-DAILY' } } # Create a virtual machine configuration $VMConfig = New-AzVMConfig -VMName $VMName -VMSize $VMSize if ($OSType -eq 'Windows') { $VMConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential | Out-Null } else { $VMConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMName -Credential $VMCredential | Out-Null } $VMConfig | Set-AzVMSourceImage -PublisherName $VMSourceImage.PublisherName -Offer $VMSourceImage.Offer -Skus $VMSourceImage.Sku -Version latest | Out-Null $VMConfig | Add-AzVMNetworkInterface -Id $NIC.Id | Out-Null $VMConfig | Set-AzVMBootDiagnostic -Disable | Out-Null # Create a virtual machine New-AzVM -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $Location -VM $VMConfig To create a Windows VM… .\Create-AzVM.ps1 -ResourceGroupName test-rg ` -VMName testvm -Location southindia ` -OSType Windows ` -VirtualNetworkName test-vnet ` -SubnetName testnet ` -SecurityGroupName test-nsg ` -AssignPublicIP ` -AllowedPorts 3389 ` -VMCredential $cred ` -Verbose To create a Linux VM… .\Create-AzVM.ps1 -ResourceGroupName test-rg ` -VMName testvm -Location southindia ` -OSType Linux ` -VirtualNetworkName test-vnet ` -SubnetName testnet ` -SecurityGroupName test-nsg ` -AssignPublicIP ` -AllowedPorts 22 ` -VMCredential $cred ` -Verbose You can find the complete source code on my git repository. 

3 January 2019