I had some free time (very rare these days) and was handed an assignment which led to this.  Basically, it reads a CSV for some VERY BASIC info and merges it with my Azure subscription to build out a set of VM’s with networking and so on.  Extremely 100-level stuff, but I will be improving upon this as a pet project.  1.0 right now.  1.1 will move more of the hard-coded stuff into the CSV to parameterize things more.  2.0 will move from CSV to JSON.

wpid-chinese-take-out.jpg

Note: The parameters are just for the time-being and will evolve (fewer, I hope).  The three shown in bold text can be obtained by running the Login-AzureRmAccount cmdlet without any parameters.  After you complete a login, the results are dumped to the console.  Then you can copy/paste them for repeat use.

The PowerShell script

param (
  [parameter(Mandatory=$False)] [string] $azEnv = "AzureCloud",
  [parameter(Mandatory=$False)] [string] $azAcct = "<yourliveID>",
  [parameter(Mandatory=$False)] [string] $azTenId = "<yourTenantID>",
  [parameter(Mandatory=$False)] [string] $azSubId = "<yourSubscriptionID>",
  [parameter(Mandatory=$False)] [string] $InputFile = "azurelab.csv",
  [parameter(Mandatory=$False)] [string] $rgName = "xxResGroup1",
  [parameter(Mandatory=$False)] [string] $saName = "xxstacct1",
  [parameter(Mandatory=$False)] [string] $subnetPfx = "10.0.0.0/24",
  [parameter(Mandatory=$False)] [string] $addressPfx = "10.0.0.0/16",
  [parameter(Mandatory=$False)] [string] $Location = "eastus",
  [parameter(Mandatory=$False)] [switch] $TestMode = $False,
  [parameter(Mandatory=$False)] [string] $subnetName = "xxsubnet1",
  [parameter(Mandatory=$False)] [string] $vnetName = "xxvnet1"
)

Write-Output "checking if session is authenticated..."
if ($azCred -eq $null) {
  Write-Output "authentication is required."
  $azCred = Login-AzureRmAccount -EnvironmentName $azEnv -AccountId $azAcct -SubscriptionId $azSubId -TenantId $azTenId
}
else {
  Write-Output "authentication already confirmed."
}

Write-Output "reading input file: $InputFile..."
$csvData = Import-Csv $InputFile

if ($csvData -ne $null) {
  $rg = Get-AzureRmResourceGroup -Name $rgName -Location $Location -ErrorAction SilentlyContinue
  if ($rg -eq $null) {
    Write-Output "creating resource group: $rgName..."
    $rg = New-AzureRmResourceGroup -Name $rgName -Location $Location
  }
  else {
    Write-Output "resource group already exists: $rgName"
  }
  $stAcct = Get-AzureRmStorageAccount -ResourceGroupName $rgName -Name $saName -ErrorAction SilentlyContinue
  if ($stAcct -eq $null) {
    Write-Output "creating storage account: $saName..."
    $stAcct = New-AzureRmStorageAccount -ResourceGroupName $rgName -Name $saName -SkuName Standard_LRS -Kind Storage -Location $Location -ErrorAction SilentlyContinue
  }
  else {
    Write-Output "storage account already exists: $saName"
  }
  if ($stAcct -ne $null) {
    $stURI = $stAcct.PrimaryEndpoints.Blob.ToString()
    Write-Output "storage account URI: $stURI"
  }
  if ($laCred -eq $null) {
    Write-Output "setting credentials for local administrator account..."
    $laCred = Get-Credential -Message "Type the name and password of the local administrator account."
  }
  Write-Output "creating virtual network: $subnetName / $subnetPfx..."
  $singleSubnet = New-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix $subnetPfx
  $vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $Location -AddressPrefix $addressPfx -Subnet $singleSubnet
  foreach ($row in $csvData) {
    $vmName  = $row.Name
    $vmOS    = $row.OS
    $vmSize  = $row.Size
    $nicName = "$vmName"+"nic1"

    if ($TestMode -ne $True) {
      $ipName = "$vmName"+"pip1"
      Write-Output "creating public IP: $ipName..."
      $pip = New-AzureRmPublicIpAddress -Name $ipName -ResourceGroupName $rgName -Location $Location -AllocationMethod Dynamic
      Write-Output "creating NIC: $nicName..."
      $nic = New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName -Location $Location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id
   
      Write-Output "preparing components for virtual machine..."
 
      $vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
      $vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $compName -Credential $laCred -ProvisionVMAgent -EnableAutoUpdate
      $vm = Set-AzureRmVMSourceImage -VM $vm -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus $vmOS -Version "latest"
      $vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
 
      $blobPath  = "$vmName"+"os.vhd"
      $osDiskUri = "$stURI"+"vhds/$blobPath"
      $diskName  = "$vmName"+"osdisk"
      $vm = Set-AzureRmVMOSDisk -VM $vm -Name $diskName -VhdUri $osDiskUri -CreateOption FromImage
 
      Write-Output "creating virtual machine: $vmName..."
      New-AzureRmVM -ResourceGroupName $rgName -Location $Location -VM $vm
 
      $vmnic = Get-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName
      $pvtIP = $($vmnic.IpConfigurations).PrivateIpAddress
      $pubIP = $(Get-AzureRmPublicIpAddress -Name vm02pip1 -ResourceGroupName rg3).IpAddress
      Write-Output "`tPrivate IP: $pvtIP"
      Write-Output "`tPublic IP: $pubIP"
    }
    else {
      Write-Output "testmode enabled."
      Write-Output "vm: $vmName / size: $vmSize / os: $vmOS / Location: $Location"
      $blobPath  = "$vmName"+"os.vhd"
      $osDiskUri = "$stURI"+"vhds/$blobPath"
      $diskName  = "$vmName"+"osdisk"
      Write-Output "`tstorage blob: $osDiskUri"
      Write-Output "`tstorage disk: $diskName"
    }
  }
}

Write-Output "Finished!!!" 
# bonus: blow it all away when finished!...
# Remove-AzureRmResourceGroup -Name $rgName -Force

The CSV file

(azurelab.csv)

Name,Size,OS
vm01,Standard_A1,2012-R2-Datacenter
vm02,Standard_A1,2012-R2-Datacenter
vm03,Standard_D2,2012-R2-Datacenter
vm04,Standard_D2,2012-R2-Datacenter

I’ll be on business travel for a few days, so I may not be able to respond to emails/comments immediately.  Thank you for reading!  Cheers!

Advertisements

3 thoughts on “Playing with Azure and PowerShell Again

    1. I wish I’d run across your script earlier! As to the parallel processing challenge, I’m not quite there yet. I still sit and wait for serial processing. However, I’m told that if you prepare the configuration as a JSON template and load it into Azure, it processes in parallel. I haven’t verified that yet however.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s