After many Amazon Web Services Elastic Compute Cloud (AWS EC2) projects involving Linux, I’m finally working on a Windows EC2 project. With that we need a variety of maintenance scripts, such as assigning a static IP at boot (Elastic IP or EIP). Much to my surprise, there are very few examples for using native Windows scripting to perform this work (other than tired, old, cmd.exe
, which is very limiting).
So, with a very basic understanding of PowerShell, I’ve setout to fill this gap… stay tuned for other AWS PS scripts soon, such as taking EBS Snapshots. Make sure you have the AWS .NET SDK installed before running this script.
Without further ado, here is the script (you may download it as well: AWS-EIP.ps1).
<# .SYNOPSIS Simple script to safely assign AWS Elastic IPs (EIPs) at Windows Boot. .DESCRIPTION Script first checks to see if the IP is already assigned, and if so aborts returning a non-zero code. If assginement is successful, zero (0) is returned. NOTE: Script must be updated to include instanceID, EIP, security credentials, and ServiceURL for your particular Region. .NOTES File Name : AWS-EIP.ps1 Author : Nick Webb - nickw at redwireservices dot com Version : 0.2 - 02/21/2012 .LINK http://www.redwireservices.com .EXAMPLE AWS-EIP.ps1 #> # User modifyable items: ################################################# # Update to the AWS SDK Path on your system, if not default Add-Type -Path "C:Program Files (x86)AWS SDK for .NETbinAWSSDK.dll" # Update the following lines, as needed: $accessKeyID="your access key ID" $secretAccessKey="your secret access key" $instanceID="i-your instance id" $instanceEIP="x.x.x.x" # Uncomment ONE of the following, which applies to your region # US-West N. California: $ServiceURL="https://ec2.us-west-1.amazonaws.com" # US-West Oregon #$ServiceURL="https://ec2.us-west-2.amazonaws.com" # US-East (Standard) #$ServiceURL="https://ec2.us-east-1.amazonaws.com" # END User configurable options ########################################## $config=New-Object Amazon.EC2.AmazonEC2Config $config.ServiceURL = $ServiceURL $client=[Amazon.AWSClientFactory]::CreateAmazonEC2Client($accessKeyID,$secretAccessKey,$config) # See if the IP is already assigned somewhere $request = New-Object -TypeName Amazon.EC2.Model.DescribeAddressesRequest [void]$request.WithPublicIp($instanceEIP) $result = New-Object -TypeName Amazon.EC2.Model.DescribeAddressesResponse try { $result = $client.DescribeAddresses($request) } catch { echo "Failed to validate EIP $instanceEIP, ensure that it is allocated and associated with your account. Aborting." exit 2 } # See if an instanceID is already assigned to this EIP $xml=$result.ToXML() $assignedInstanceID = [string]($xml.DescribeAddressesResponse.DescribeAddressesResult.Address.InstanceId) # Run this block if an Instance already has this EIP associated to it... just in case changes would # result in downtime (i.e. if we are launching a test system from a cloned production one). if ($assignedInstanceID) { echo "Address $instanceEIP already assigned to: $assignedInstanceID, aborting." exit 1 } # If we get here, the IP is free and clear, go ahead and associate it. $request = New-Object -TypeName Amazon.EC2.Model.AssociateAddressRequest [void]$request.WithInstanceId($instanceID) [void]$request.WithPublicIp($instanceEIP) $result = $client.AssociateAddress($request) if ($result) { echo "Address $instanceEIP assigned to $instanceID successfully." exit 0 } else { echo "Failed to assign $instanceEIP to $instanceID." exit 3 }
For me, the $instanceID changes every time the instance is re-started. How do you make it a fixed $instanceID or how do you retrieve it in the script?
Hey Emmanuel (et al.),
I too wanted to know this, because after an autoscaling event the instance ID changes. Here’s what worked for me:
PS C:\> $instanceID = Invoke-RestMethod http://169.254.169.254/latest/meta-data/instance-id -Body (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id)
PS C:\> echo $instanceID
i-e8529f01
Emmanuel,
Great question.
I’ve ran into that as well, and you can get the current instanceID from within the instance with a request to this URL:
http://169.254.169.254/latest/meta-data/instance-id
On Linux/bash I’ve put that in a variable like so:
MY_INSTANCE=$(/usr/bin/wget -q -O – http://169.254.169.254/latest/meta-data/instance-id)
Also note that this is pretty legacy stuff at this point. I wouldn’t update retiring applications that are using it, but I would (and have) slowly migrate over to VPC where this is not an issue (EIP assignments and local IPs are static across reboots and power-offs).
Given your question, however, you may have a great use case for the old way (“EC2 Classic”).
Hi,
I am new to Powershell programming and when i run this script i am getting following error.
Add-Type : Could not load file or assembly ‘file:///C:\Program Files (x86)\AWS SDK for .NET\bin\Net45\AWSSDK.dll’ or one of its dependencies. This assembly is buil
t by a runtime newer than the currently loaded runtime and cannot be loaded.
At C:\AWS-EIP.ps1:4 char:9
+ Add-Type <<<< -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\Net45\AWSSDK.dll" # Update the following lines, as
Any help.
Thanks,
Dev
Dev,
Sounds like you do not have the AWS .NET toolkit installed.
Nick
Hi Nick,
I have AWS.NET toolkit on that window instance. It seems that issue is realted to latest .net framework. But i figure out another way. I used bat file and after facing issue in order to run this bat file as a window service, i used task scheduler for that purpose. It work for me.
Thanks for posting nice article.
Thanks,
Dev