Tuesday, March 29, 2011

Random Wait PowerShell Script

During my work with Azure I have run into cases where the provisioning of service instances causes flooding of some other component – such as the backend Azure SQL database as my instances register themselves into a configuration database.

To get around this very traditional “black hole” type of problem I have a very simple PowerShell script that I run in the proper sequence as a First Logon Command as my instances complete mini-setup.  (The OS is prepared with sysprep so everything has to go through mini-setup).

The command line in my unattend.xml looks like this:

<FirstLogonCommands>
  <SynchronousCommand wcm:action="add">
    <Order>1</Order>
    <CommandLine>%WINDIR%\System32\WindowsPowerShell\v1.0\PowerShell.exe -command set-executionpolicy remotesigned -force >> C:\Users\Public\Documents\setExecution.log</CommandLine>
    <Description>Set the ExecutionPolicy to RemoteSigned for the script to run</Description>
  </SynchronousCommand>
  <SynchronousCommand wcm:action="add">
    <Order>2</Order>
    <CommandLine>%WINDIR%\System32\WindowsPowerShell\v1.0\PowerShell.exe C:\Tanzanite\RandomWait.ps1 >> C:\Users\Public\Documents\RandomWait.log</CommandLine>
    <Description>A random wait time to prevent storming and corrupting the database</Description>
  </SynchronousCommand>
  </FirstLogonCommands>

You will notice that the first thing I have to do is to issue a command to set the ExecutionPolicy.  After mini-setup the ExecutionPolicy is reset to Restricted and my script will not run.

BTW – FirstLogonCommands are executed when an Administrator logs on to the machine for the first time.  So, prior to this I am using AutoAdminLogon to set the administrator to logon and then these scripts execute.

Now, the PowerShell script.  (RandomWait.ps1)

<#
.SYNOPSIS
    This is a frivolous script, strictly to be called to introduce a random wait period
    within a five minute window, based on a random number of seconds.
.DESCRIPTION
    This script is designed to facilitate VM instance application setup in the Azure Environment.
    To prevent database corruption during deployment this random wait
    is introduced after provisioning and called as an UNATTEND.xml FirstLogonCommand
    during mini-setup.
.LEGAL
    SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF ANY KIND, INCLUDING BUT NOT LIMITED TO
    MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.  ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF THE AUTHOR,
    SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF ANY SUCH DAMAGE.  IF YOUR STATE DOES NOT PERMIT THE COMPLETE
    LIMITATION OF LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.  TEST ON NON-PRODUCTION SERVERS.
.AUTHOR
    Brian Ehlert, Citrix Labs, Redmond, WA, USA
.REFERENCES
    Thank you TechNet. For examples.
#>#

# Add the Service Runtime snap-in to the standard Windows PowerShell command shell.
add-pssnapin microsoft.windowsazure.serviceruntime

# Take the VM Instance offline with Azure
Set-RoleInstanceStatus -Busy

# Get the random number generator object so as not to require PoSh v2.0
# PoSh v2 introduces Get-Random
$randomNo = new-object system.random

# Generate a random number between 1 and 300
# using seconds instead of minutes as chance for it to be not equal to other instances is higher.
$number = $randomNo.Next(1, 300)

Start-Sleep -Seconds $number

No comments: