In this post I will show you how I created a PowerShell script that makes use of the Microsoft Azure PowerShell module to manage resources on Azure.

What will the script do?

The script will enable us to:

  • Create / Remove
    • Subscriptions
    • Resource Groups
    • Resources
      • Web Applications
      • Virtual Machines
      • Virtual Networks
      • Availability Sets
      • Network Adapters
      • Public IPs
      • Storage Accounts
      • Etc.

I gathered most knowledge from the following resources:

  • https://docs.microsoft.com/en-us/powershell/azureps-cmdlets-docs/
  • https://docs.microsoft.com/en-us/powershell/resourcemanager/
  • http://www.jonathanmedd.net/2015/01/how-to-make-use-of-functions-in-powershell.html

First off, I am not a developer and most certainly not a scripting expert. I have just recently “discovered” the phenomena of a function in PowerShell and the usage of Try{} Catch{} and am just trying to put this knowledge to work.

Why would I want to make a script if i can use the GUI?

Sure, the GUI is easy to use, performs quite well most of the time and..you can see:-)

Scripting comes to mind when you have enough of the slugish performance of the online Azure GUI, like me, or to create a bulk of machines, let’s say 10. Some with different characteristics than the other, maybe all the same. I do know technicians who will actually make a list with servers and specs and just do everything manual. Hey, whatever works for you. If you want to be able to have more control over the process, make it sharable, versioned, repeatable. Then at minimum you should go for a scripted solution. In following posts i will inform on how to do the same as this script and more, with the Azure SDK for Visual Studio.

To get started we need the Azure PowerShell module installed on our local machine. And of course an account on Azure. You can start a free trial here.

Install Azure PowerShell

Azure PowerShell recommends installing from the PowerShell Gallery. You need the PowerShellGet module to use the PowerShell Gallery. Alternatively, use the Web Platform Installer (WebPI), or the MSI file available from GitHub.3

Install the latest Azure PowerShell from the PowerShell Gallery using an elevated Windows PowerShell or PowerShell Integrated Scripting Environment (ISE) prompt:

# Install the Azure Resource Manager modules from the PowerShell Gallery
Install-Module AzureRM

Connect to an Azure account

You can run the cmdlets from the standard Windows PowerShell console, or from PowerShell Integrated Scripting Environment (ISE). The cmdlets need your subscription information so they can manage your services.

Type “Login-AzureRMAccount” in your console window and press Enter.

Enter the email account you used to subscribe to Azure.

Azure CMDlets

Now that we have confirmed that the Azure PowerShell Module is properly installed, I will run you through some basics.

To retrieve information from an object or objects we use “Get” followed by a dash(-) and then the method keyword.

We will use the following methods to retrieve info:

  • Get-AzureRmSubscription
  • Get-AzureRmResourceGroup
  • Get-AzureRmResources
  • Get-AzureRmWebApp
  • Get-AzureVM
  • Get-AzurRMVirtualNetwork
  • Get-AzureRmAvailabilitySet
  • Get-AzureRmNetworkInterface
  • Get-AzureRmPublicIpAddress
  • Get-AzureRmStorageAccount

Replacing the Get statement with “Remove” or “New” or “Select” is all it takes to meet our other wishes with regards to the script. You gotta love PowerShell.

I decided to create a separate PowerShell file for all the different functions. I call it common.ps1.

For logging purposes I also created a separate PowerShell file called logging.ps1

The main file will be AzureAdmin.ps1. This is basically a file from where I call a menu which can call all the functions from common.ps1.

For starters I would like to login to Azure. Off course i could have just typed

Login-AzureRMAccount

but that would be just too easy:-)

so

#Login to Azure
function login-ToAzure()
{
try
{
$Global:credentials = Login-AzureRmAccount -ErrorAction Stop
}
catch
{
$_.Exception.Message
$_.Exception.ItemName
}
}

To select the subscription I would like to work with, I created the following function:

#select subscription
function select-Subscription()
{
Try
{
$Global:subscription = Get-AzureRmSubscription -ErrorAction Stop
$subscriptionmenu = @{}
for ($i=1;$i -le $Global:subscription.count; $i++)
{ Write-Host "$i. $($Global:subscription[$i-1].SubscriptionName),$($Global:subscription[$i-1].State)"
$subscriptionmenu.Add($i,($Global:subscription[$i-1].SubscriptionName))}
[int]$Global:subscriptionans = Read-Host 'Enter selection'
$Global:subScrSelection = $subscriptionmenu.Item($Global:subscriptionans) ; Select-AzureRmSubscription -SubscriptionName $Global:subScrSelection
}
Catch
{
$_.Exception.Message
$_.Exception.ItemName
}
}

As you can see i’m making use of Global Variables

$Global:

here and there. This is because I would like to use the values maybe in a later stage of the script.

Now this same trick of building menu’s where I can make a selection, I will do a lot. It is because you would want to be able to make a choiche for an existing resource or creating a new one for instance. This goes almost definitely for the Resource Group, but I also need it for Location.

Moving on…

Let’s do “Select a New or Existing Resource Group”

#New or Existing ResourceGroup
function select-NewOrExistingResourceGroup()
{
Write-Host "Use an existing Resource Group or create New?" -ForegroundColor Yellow
[int]$NewOrExistingRsrcGrpMenuChoiceA = 0
while ( $NewOrExistingRsrcGrpMenuChoiceA -lt 1 -or $NewOrExistingRsrcGrpMenuChoiceA -gt 2 ){
Write-host "1. New"
Write-host "2. Use Existing"

[Int]$NewOrExistingRsrcGrpMenuChoiceA = read-host "Please enter an option 1 to 2..." }
Switch( $NewOrExistingRsrcGrpMenuChoiceA ){
1{$Global:NewOrExistingRsrcGrpMenuChoice = "New"}
2{$Global:NewOrExistingRsrcGrpMenuChoice = "Use Existing"}
}
if($Global:NewOrExistingRsrcGrpMenuChoice -eq "New")
{
new-ResourceGroup
$Global:ResourceGroup = $Global:nwRscGroupName
}
if($Global:NewOrExistingRsrcGrpMenuChoice -eq "Use Existing")
{
select-ResourceGroup
$Global:ResourceGroup = $Global:resourcegroupselection
}
}

You can see that when I make the choice for a new or existing, I’m calling either function

new-ResourceGroup

or

select-ResourceGroup

.And I have not shown you these!

Here is what happens when you choose “New”

#New Resource Group
function new-ResourceGroup()
{
#select-Subscription

$global:nwRscGroupName = Read-Host "Enter new Resource Group Name"
$ifRscGrpExists = Get-AzureRmResourceGroup -Name $global:nwRscGroupName -ErrorAction SilentlyContinue

try
{
if($ifRscGrpExists -eq $null)
{
Write-Host "Choose the location for the new Resource Group" -ForegroundColor Yellow
select-location
LogInformation "Creating New Resource Group ""$global:nwRscGroupName""@ Geo Location ""$Global:locationSelection"""
New-AzureRmResourceGroup -Name $global:nwRscGroupName -Location $Global:locationSelection -ErrorAction Stop
LogInformation "Succesfully created New Resource Group ""$global:nwRscGroupName""@ Geo Location ""$Global:locationSelection"""
}
else
{
LogInformation "The Resource group already ""$global:nwRscGroupName"" exists"
}
}
catch
{
LogInformation $_.Exception.Message
LogInformation $_.Exception.ItemName
}
}

Cool aye?

So without further delay we will create a Virtual Machine with everything it needs.

#new VM
function new-VirtualMachine()
{
try
{
$cred = Get-Credential -Message "Type the name and password of the local administrator account."

$Global:NwVMName = Read-Host "Enter a unique name for your New Virtual Machine"

Write-Host "Select the size of your New Virtual Machine" -ForegroundColor Yellow
select-AzureVMSize

#Select existing or create a new Resource Group for the New Virtual Machine
select-NewOrExistingResourceGroup

#Select existing or create a new Storage Account for the New Virtual Machine
select-NewOrExistingStorageAccount

#Select existing or create a new Network Interface for the New Virtual Machine
select-NewOrExistingNIC

LogInformation "Creating a new VM Configuration for ""$Global:NwVMName"" Size ""$Global:VMSizeSelection"""
$myVM = New-AzureRmVMConfig -VMName $Global:NwVMName -VMSize $Global:VMSizeSelection
LogInformation "Successfully created a new VM Configuration for ""$Global:NwVMName"""

LogInformation "Settting the Operating System to Windows for VM ""$Global:NwVMName"""
$myVM = Set-AzureRmVMOperatingSystem -VM $myVM -Windows -ComputerName $Global:NwVMName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate
LogInformation "Successfully set the Operating System to Windows for VM ""$Global:NwVMName"""

LogInformation "Settting the Source Image to Microsoft Windows Server 2012-R2-Datacenter for ""$Global:NwVMName"""
$myVM = Set-AzureRmVMSourceImage -VM $myVM -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2012-R2-Datacenter" -Version "latest"
LogInformation "Successfully set the Source Image to Microsoft Windows Server 2012-R2-Datacenter for ""$Global:NwVMName"""

LogInformation "Adding Network Interface"
$myVM = Add-AzureRmVMNetworkInterface -VM $myVM -Id $Global:MyNIC.Id
LogInformation "Successfully added Network Interface"

$VMDiskName = Read-Host "Enter a name for a New Disk for VM" $Global:NwVMName
$VMDiskSizeInGB = "128"
$blobPath = "vhds/"+$VMDiskName+".vhd"
$osDiskUri = $Global:MyStorageAccount.PrimaryEndpoints.Blob.ToString() + $blobPath

LogInformation "Configure a disk size of ""$VMDiskSizeInGB"""
$myVM = Set-AzureRmVMOSDisk -VM $myVM -Name $VMDiskName -DiskSizeInGB $VMDiskSizeInGB -CreateOption FromImage -Caching ReadWrite
LogInformation "Successfully configured a disk size of ""$VMDiskSizeInGB"""

LogInformation "Attach disk ""$VMDiskName"" to ""$Global:NwVMName"""
$myVM = Set-AzureRmVMOSDisk -VM $myVM -Name $VMDiskName -VhdUri $osDiskUri -CreateOption fromImage
LogInformation "Succesfully attached disk ""$VMDiskName"" to ""$Global:NwVMName"""

Write-Host "Select a location for your New Virtual Machine" -ForegroundColor Yellow
select-Location

LogInformation "Creating VM ""$Global:NwVMName"""
New-AzureRmVM -ResourceGroupName $Global:resourcegroup -Location $Global:locationSelection -VM $myVM
LogInformation "Successfully created VM ""$Global:NwVMName"""
}
catch
{
LogInformation $_.Exception.Message
LogInformation $_.Exception.ItemName
}
}

I did some other nifty things like a bulk function in my “finished” script. Have a look at it.
I hope this will save you a lot of time.

Download here

Neem contact op

Coltbaan 4E
3439 NG Nieuwegein

+31 (0)85 - 489 1008

Meer informatie?

%d bloggers like this: