Skip to content

Instantly share code, notes, and snippets.

@charlesmims
Created September 1, 2016 15:23
Show Gist options
  • Save charlesmims/e92a12d1d53ac54485ccd74620e7a6a3 to your computer and use it in GitHub Desktop.
Save charlesmims/e92a12d1d53ac54485ccd74620e7a6a3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# @charlesmims 2015
# Maintains a number of coreOS hosts running in ec2. Can be used to scale up by increasing NUM_NODES,
# but in present state will not scale down cleanly.
import boto.ec2
import time
from os import environ
from collections import defaultdict
from jinja2 import Template
import sys
ACCESS = environ['AWS_KEY']
SECRET = environ['AWS_SECRET']
if len(sys.argv) > 1:
TOKEN = sys.argv[1]
print "using token %s" % TOKEN
else:
TOKEN = environ['ELK_TOKEN']
print "using ELK_TOKEN %s" % TOKEN
REGION = environ['ELK_REGION']
AMI = environ['ELK_AMI']
KEY = environ['ELK_KEY']
TYPE = environ['ELK_TYPE']
GROUPS = [environ['ELK_GROUP']]
SUBNET_ID = environ['ELK_SUBNET']
NUM_NODES = int(environ['ELK_NUM_NODES'])
DISK = environ['ELK_DISK']
# block device mapping stuff for creating instance with larger EBS drive than default
dev_xvda = boto.ec2.blockdevicemapping.BlockDeviceType()
dev_xvda.size = DISK # size in Gigabytes
bdm = boto.ec2.blockdevicemapping.BlockDeviceMapping()
bdm['/dev/xvda'] = dev_xvda
# template stuff for rendering cloud init user data
cloud_config = """#cloud-config
hostname: coreos{{ instance_num }}
coreos:
etcd2:
name: coreos{{ instance_num }}
discovery: https://discovery.etcd.io/{{ token }}
# multi-region and multi-cloud deployments need to use $public_ipv4
advertise-client-urls: "http://$private_ipv4:2379"
initial-advertise-peer-urls: "http://$private_ipv4:2380"
listen-client-urls: "http://0.0.0.0:2379,http://0.0.0.0:4001"
listen-peer-urls: "http://$private_ipv4:2380,http://$private_ipv4:7001"
units:
- name: etcd2.service
command: start
- name: fleet.service
command: start
"""
template = Template(cloud_config)
# establish connection to ec2
print "connecting to aws..."
conn = boto.ec2.connect_to_region(REGION, aws_access_key_id=ACCESS, aws_secret_access_key=SECRET)
# get the currently running instances tagged with Name: coreos*
print "getting coreos instances... ",
instance_tags = []
reservations = conn.get_all_instances(filters={'tag:Name':'coreos*','instance_state_name':'running'})
for reservation in reservations:
instance = reservation.instances[0]
instance_tag = instance.tags['Name']
instance_tags.append(instance_tag)
print len(instance_tags), "of", NUM_NODES, "found"
if len(instance_tags) < NUM_NODES:
print "launching %i ec2 instances..." % (NUM_NODES - len(instance_tags))
# take list of instance tags down to just numbers so we can compare it against a range
instance_tags.sort()
instance_numbers = [int(x.split('coreos')[1]) for x in instance_tags]
# compare it against a range
missing_instance_numbers = []
for n in range(NUM_NODES):
if n not in instance_numbers:
missing_instance_numbers.append(n)
# print "missing nodes:", missing_instance_numbers
# launch new instances
for num in missing_instance_numbers:
reservation = conn.run_instances(image_id=AMI, key_name=KEY, instance_type=TYPE, security_group_ids=GROUPS, subnet_id=SUBNET_ID,
block_device_map=bdm, user_data=template.render(token=TOKEN, instance_num=num))
instance = reservation.instances[0]
status = instance.update()
if status == 'terminated':
print instance.state_reason['message']
while status == 'pending':
time.sleep(10)
status = instance.update()
if status == 'running':
print "coreos%s running" % num
tagged = 0
while tagged == 0:
try:
instance.add_tag('Name', 'coreos%s' % num)
print "tagged instance coreos%s" % num
tagged = 1
except:
time.sleep(5)
print 'coreos%s started at %s' % (num, instance.private_ip_address)
else:
print('Instance status: ' + status)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment