Controlling EC2 instances with a button

The Minecraft button

I have a Minecraft server on AWS, but use it quite seldom. It doesn’t make sense to have it turned on constantly as you pay by the hour. On the other hand I don’t want to have to login to the AWS Console and sometimes the kids wants to play Minecraft when I’m not home. That’s where the idea with the Minecraft button came in – basically having a physical button to turn on and off the server.

The bits and pieces

Quite simple actually:

  • A Raspberry Pi
  • Green, yellow, red LED to indicate instance status
  • On/off switch
  • A Python script that checks the status of the server and lights the corresponding led
  • Another Python script that checks the button and sends API calls to AWS when pressed
  • AWS CLI and Boto3 for communication with AWS
20161106_132712
I made holes in the Raspberry Pi case and stuck everything there

Raspberry Pi

The Raspberry Pi runs Raspbian and is generation 1 model B, simply because that was what I had laying around. My gen 1 also has a roomier case than the gen 2 and 3 I have, which came handy to fit the cables, etc.

Electronic components

This is my shopping list. It links to a Swedish site but should give you and idea anyway.

Apart from that I use a 100 ohm resistor not to overload the LEDs.

The circuit looks like this.

curcuit

The stuff is fitted in the Raspberry Pi. Then just plugging in the cables to their corresponding pins. Check out the documentation on PIN numbering.

20161106_131712

AWS access

First of all, we need to create a user and assign it permissions.

Go to the  AWS console and navigate to IAM. Create a user, assign it the AmazonEC2FullAccess policy and create an access key that the Raspberry Pi will use to talk to AWS.

Install the AWS CLI which will allow us to configure credentials for accessing AWS.

sudo apt-get install awscli

Then run the following command and type in the access key you created and region where your EC2 instance is running.

aws configure

You also need to install Boto3 which is AWS’ SDK for Python. Just run a:

pip install boto3

The control script

The control script handles the button and begins with defining two functions

  • start_server – call AWS using Boto3 to start the server
  • stop_server – call AWS using Boto3 to stop the server

Then it just runs an endless loop and checks if the button is pressed every half a second. If it is pressed, it checks if the server is running and then calls the stop_server function, and the other way around. If the server is nog running or stopped, example in the middle of starting or stopping, then it does nothing.

#!/usr/bin/python
import boto3
import RPi.GPIO as GPIO
from datetime import datetime
from time import sleep


def start_server(server_id):
    print('Starting server {}'.format(server_id))
    instance = ec2.Instance(server_id)
    instance.start()

def stop_server(server_id):
    print('Stopping server {}'.format(server_id))
    instance = ec2.Instance(server_id)
    instance.stop()


pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

ec2 = boto3.resource('ec2')

while True:
    if GPIO.input(17):
        instance = ec2.Instance('i-dae58150')
        if instance.state['Name'] == 'stopped':
            print('{} - Starting server'.format(datetime.now()))
            instance.start()
        elif instance.state['Name'] == 'running':
            print('{} - Stopping server'.format(datetime.now()))
            instance.stop()
        else:
            print('{} - server is in unknown state, skipping'.format(datetime.now())) 
            sleep(1)
    sleep(0.5)

GPIO.cleanup()

The status script

This script handles the leds and makes a call to AWS, using Boto3, to check the status of the instance and updates the LEDs accordingly. This is done in an endless loop with a 1 second sleep for each iteration.

#!/usr/bin/python
import boto3
import RPi.GPIO as GPIO
from time import sleep

instance_id = 'i-dae58150'
red_pin = 27
green_pin = 22
yellow_pin = 10

GPIO.setmode(GPIO.BCM)
GPIO.setup(red_pin, GPIO.OUT)
GPIO.setup(green_pin, GPIO.OUT)
GPIO.setup(yellow_pin, GPIO.OUT)

ec2 = boto3.resource('ec2')

while True:
    instance = ec2.Instance(instance_id)
    state = instance.state['Name']
    if state == 'running':
        GPIO.output(red_pin, GPIO.LOW)
        GPIO.output(yellow_pin, GPIO.LOW)
        GPIO.output(green_pin, GPIO.HIGH)
    elif state == 'stopped':
        GPIO.output(red_pin, GPIO.HIGH)
        GPIO.output(yellow_pin, GPIO.LOW)
        GPIO.output(green_pin, GPIO.LOW)
    else:
        GPIO.output(red_pin, GPIO.LOW)
        GPIO.output(yellow_pin, GPIO.HIGH)
        GPIO.output(green_pin, GPIO.LOW)
    sleep(1)

Staring the scripts at boot

To make the scripts run automatically when you start the Pi, add the following lines to your crontab (run crontab -e)

@reboot nohup /home/pi/MinecraftButton/server_control.py &
@reboot nohup /home/pi/MinecraftButton/server_status.py &

 

 

Leave a comment