Pages

Thursday, March 06, 2014

Wake on LAN in AWS

Someone asked the question. Is Wake-on-LAN supported in Amazon Web Services.

The answer is no. But it also shows not thinking of infrastructure as code.

How would you approach this in AWS? You can fire of an API call to start any instance, but what if you wanted to make this easier? Simply tag your instances with an identifiable tag, such as "WakeOnLAN" and then run the following script (I prefer Ruby).

#!/usr/bin/ruby
require 'aws-sdk'

AWS.regions.sort_by(&:name).each do |region|
  next if region.name.match('cn-')
  puts region.name
  region.ec2.instances.each do |instance|
    if instance.status == :stopped and
       instance.tags.to_h.has_key?('WakeOnLAN')
      puts "\t#{instance.id} started"
      instance.start
    end
  end
end

That results in

[ec2-user@ ~]$ ./wake.rb 
ap-northeast-1
ap-southeast-1
ap-southeast-2
i-7c444f41 started
eu-west-1
sa-east-1
us-east-1
us-west-1
us-west-2
[ec2-user@ ~]$

The script simply goes through all of your instances in each region, finding those that have the WakeOnLAN tag and that are stopped, then starts them. If you run it make sure it has privilege to perform the actions, a role on an EC2 instance makes this easy.

I am a big fan of the AWS CLI too. Here is how to do the same on one line, all be it only within a single region. Its one command line but I have wrapped for formatting.

:~ rodos$ aws ec2 describe-instances 
--query 'Reservations[*].Instances[*].[InstanceId]'
--filters "Name=instance-state-name,Values=stopped"
"Name=tag-key,Values=WakeOnLAN" --output text 
| xargs aws ec2 start-instances --instance-ids
{
    "StartingInstances": [
        {
            "InstanceId": "i-7c444f41", 
            "CurrentState": {
                "Code": 0, 
                "Name": "pending"
            }, 
            "PreviousState": {
                "Code": 80, 
                "Name": "stopped"
            }
        }
    ]
}
:~ rodos$ 

This uses two very powerful features of the CLI. One is the --query option which lets you pull data out of the returned JSON data. The second is the --filters option which, as the name implies, lets you filter the results based on a lot of criteria. You can see all of the filters for the describe-instances command in the documentation. There are 78 different filters you can use (based on my quick count)!

Enjoy the world of infrastructure as code!

Rodos