Creating Multiple Azure Virtual Machines Part Tre

In my previous posts, I’ve described how to stand up multiple machines in the Microsoft Azure cloud. I then talked about installing a remote certificate in part deux.  This allowed us to connect to the remote machine and start executing commands on the remote box as if we were logged into it locally.  If you are not familiar with these concepts I would read the other posts first before diving into this one.In this installment (part tre) I will give you an examples of commands that you can execute on the remote machine.  I will demonstrate the following:

  • Create Folders
  • Passing Parameters
  • Making It Mandatory
  • Making It Optional
  • Declaring A Script Block

Create Folders

If you are deploying your software on a computer eventually, you will need to create a folder structure in order to place your software in it. This leads us into our first example. We saw a hint of this in the last post but I will endeavor to be more specific here. We will assume that your company name is XYZ Widgets

Write-Host 'Creating all folders required for deployment...'
Invoke-Command -Session $remoteSession -ScriptBlock { 
            New-Item -ItemType directory -Path 'C:\XYZ_Widgets'            
            New-Item -ItemType directory -Path 'C:\XYZ_Widgets\Application'
            New-Item -ItemType directory -Path 'C:\XYZ_Widgets\Data'
        }

This example shows you how to create several directories on the target machine.
Note: You must start with creating the root folder first before adding the sub directories!

Passing Parameters

Please remember that you are creating a new instance of PowerShell on the remote computer so any of your script wide or global variables will not have any effect unless you pass them into the remote script. Let’s take a look at the above sample assuming that the company name is set in a variable outside the scope of the remote machine.

Write-Host 'Creating all folders required for deployment...'
[string] $companyName = 'XYZ_Widgets'
Invoke-Command -Session $remoteSession -ScriptBlock { 
            Param([string] $company)
            New-Item -ItemType directory -Path ('C:\' + $company)
            New-Item -ItemType directory -Path ('C:\' + $company + '\Application')
            New-Item -ItemType directory -Path ('C:\' + $company + '\Data')
        } -ArgumentList $companyName

In this bit of code, we are passing the company name to the script that we are invoking on the remote server. While this might be a simple example, you’re getting the idea of the power that can be garnished from the use of parameters.

Making It Mandatory

Now the above snippet will fail if you fail to pass in the company name to the remote script. We can ensure that the user puts in something, even if it’s the wrong thing, for the company name.

Invoke-Command -Session $remoteSession -ScriptBlock { 
            Param([Parameter(Mandatory=$true, HelpMessage="(Required) The name of the root folder'n")]
                  [string] $folder)
            New-Item -ItemType directory -Path ('C:\' + $folder)
            New-Item -ItemType directory -Path ('C:\' + $folder + '\Application')
            New-Item -ItemType directory -Path ('C:\' + $folder + '\Data')
        } -ArgumentList 'TheWrongThing'

Even though I passed in ‘TheWrongThing‘ into the script, I was able to pass the validation of passing SOMETHING into the script.

Making It Optional

Now that we’ve made a parameter mandatory, we can no consider making a parameter optional. Here we may not care so much about the company name because that doesn’t change very often. The version number however we need to make mandatory because it changes often. Now if you pass the company name “ABC_Corp” for the company name and “3.4.0” into the script it will create the folder “C:\ABC_Corp_3.4.0“. If we don’t pass the company name in as one of the parameters, then it will create the folder “C:\XYZ_Widgets_3.4.0“.

Invoke-Command -Session $remoteSession -ScriptBlock { 
            Param([Parameter(Mandatory=$true, HelpMessage="(Optional) The version of the product'n")]
                  [string] $version, 
                  [Parameter(Mandatory=$false, HelpMessage="(Required) The name of the root folder'n")]
                  [string] $folder = 'XYZ_Widgets')

            [string] $componsiteFolder = ($folder + '_' + $version)
            New-Item -ItemType directory -Path ('C:\' + $componsiteFolder )
            New-Item -ItemType directory -Path ('C:\' + $componsiteFolder + '\Application')
            New-Item -ItemType directory -Path ('C:\' + $componsiteFolder + '\Data')
        } -ArgumentList '3.4.0'

Note: It is helpful but not required to have all of your optional parameters at the end of your parameter declaration.

Declaring A Script Block

There are times, often times, where you need to more complex code than will fit in just a few lines of code. Declaring a script block is helpful when you need to pass large amounts of code to the remote PowerShell instance. In this example, I’ve create a script block that will set the file system security rights on the newly created folders. Since I’ve setup ‘ContainerInherit‘, and ‘ObjectInherit‘ on the File System Access Rule, all of the folders and files below the root folder will inherent the rights defined by the rule.

$setFileAccessRightsOnFolder = {
        Param([string] $folderName, [string] $identity, [string] $fileSystemRights, [ValidateSet('Allow', 'Deny')] [string] $type = 'Allow')

        $folderInfo = Get-item -Path $folderName
        if ($folderInfo.Exists -eq $false) {
            throw ('The folder "' + $folderName + '" does not exist!  Unable to set the security rights on non-existant folder')
        }

        $folder = Get-Item -Path $folderName
        $securityDescriptor = Get-Acl $folder

        $fileAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $identity, $fileSystemRights, 'ContainerInherit, ObjectInherit', 'None', $type

        $securityDescriptor.SetAccessRule($fileAccessRule)
        $folder.SetAccessControl($securityDescriptor)

        Write-Host (' -> Security rights set on folder "' + $folderName + '"')
    }

Write-Host ' -> Giving "Everyone" full control on the newly created folder structure'
Invoke-Command -Session $remoteSession -ScriptBlock $setFileAccessRightsOnFolder -ArgumentList ('C:\' + $companyName), 'Everyone', 'FullControl'

Write-Host ' -> Folders created.'

Could I have set the file access rights using the { } syntax to dynamically declare the script block? Yes, but then I wouldn’t have the cool sample to show you next right? Did you notice anything else? How about the “ValidateSet attribute on the last parameter. Since I can’t really define enumerations in PowerShell, I’ve set the validation set on the $type property allowing me to restrict the input to one of the strings defined in the set.”

It is very important to understand these underlying concepts before you proceed. Everything else that we do going forward will build on the concepts in this lesson. If you’ve been keeping score, we have spun up the remote virtual machines, installed Microsoft Internet Information Service (IIS) and created deployment folders with access rights. I hope that you are getting as excited and I was. Please play with this example, and extend it. If you have questions, I’ll be here. Until next time, Addio!

Advertisements

One thought on “Creating Multiple Azure Virtual Machines Part Tre

  1. Pingback: Creating Multiple Azure Virtual Machines – Part Vier | OutOfMemoryException

Leave a Reply

Fill in your details below or click an icon to log in:

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