Skip to content

Commit

Permalink
Merge pull request #58 from hudl/STRUCT-AddIISNodeType
Browse files Browse the repository at this point in the history
Add IISNode IICluster and Autoscaler classes
  • Loading branch information
Chris Gilbert committed Jul 27, 2015
2 parents 8418705 + 489b601 commit d9b6aa2
Show file tree
Hide file tree
Showing 8 changed files with 708 additions and 120 deletions.
2 changes: 2 additions & 0 deletions tyr/clusters/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from mongo import MongoCluster
from iis import IISCluster
from autoscaling import AutoScaler
112 changes: 112 additions & 0 deletions tyr/clusters/autoscaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from boto.ec2.autoscale import LaunchConfiguration
from boto.ec2.autoscale import AutoScalingGroup
import boto.ec2
import logging


class AutoScaler(object):
'''
Autoscaler setup class
'''
def __init__(self, launch_configuration,
autoscaling_group,
node_obj,
desired_capacity=1,
max_size=1,
min_size=1,
default_cooldown=300,
availability_zones=None,
subnet_ids=None,
health_check_grace_period=300):
self.log = logging.getLogger('tyr.clusters.AutoScaler')
self.log.setLevel(logging.DEBUG)

self.launch_configuration = launch_configuration
self.autoscaling_group = autoscaling_group
self.desired_capacity = desired_capacity

# You can set a list of availability zones explicitly, else it will
# just use the one from the node object
if availability_zones:
self.autoscale_availability_zones = availability_zones
else:
self.autoscale_availability_zones = None

# If you set these they must match the availability zones
if subnet_ids:
self.autoscale_subnets = subnet_ids
else:
self.autoscale_subnets = None # TODO: (get the subnet IDs)

if not subnet_ids and not availability_zones:
self.log.critical(
"Must specify either availability_zones or subnets.")
raise ValueError(
"Must specify either availability_zones or subnets.")

if subnet_ids and availability_zones:
self.log.warning("Specified both availability_zones and subnets.")

self.node_obj = node_obj
self.max_size = max_size
self.min_size = min_size
self.default_cooldown = default_cooldown
self.health_check_grace_period = health_check_grace_period

def establish_autoscale_connection(self):
try:
self.conn = boto.ec2.autoscale.connect_to_region(
self.node_obj.region)
self.log.info('Established connection to autoscale')
except:
raise

def create_launch_configuration(self):
self.log.info("Getting launch_configuration: {l}"
.format(l=self.launch_configuration))

lc = self.conn.get_all_launch_configurations(
names=[self.launch_configuration])
if not lc:
self.log.info("Creating new launch_configuration: {l}"
.format(l=self.launch_configuration))
lc = LaunchConfiguration(name=self.launch_configuration,
image_id=self.node_obj.ami,
key_name=self.node_obj.keypair,
security_groups=self.node_obj.
get_security_group_ids(
self.node_obj.security_groups),
user_data=self.node_obj.user_data,
instance_profile_name=self.node_obj.role)
self.conn.create_launch_configuration(lc)
self.launch_configuration = lc

def create_autoscaling_group(self):
existing_asg = self.conn.get_all_groups(
names=[self.autoscaling_group])

if not existing_asg:
self.log.info("Creating new autoscaling group: {g}"
.format(g=self.autoscaling_group))

ag = AutoScalingGroup(name=self.autoscaling_group,
availability_zones=self.
autoscale_availability_zones,
desired_capacity=self.desired_capacity,
health_check_period=self.
health_check_grace_period,
launch_config=self.launch_configuration,
min_size=self.min_size,
max_size=self.max_size,
default_cooldown=self.default_cooldown,
vpc_zone_identifier=self.autoscale_subnets,
connection=self.conn)
self.conn.create_auto_scaling_group(ag)
else:
self.log.info('Autoscaling group {g} already exists.'
.format(g=self.autoscaling_group))

def autorun(self):
self.establish_autoscale_connection()
self.create_launch_configuration()
self.create_autoscaling_group()
104 changes: 104 additions & 0 deletions tyr/clusters/iis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import logging
from tyr.servers.iis import IISNode
from tyr.clusters.autoscaling import AutoScaler


class IISCluster():

def __init__(self, group=None,
server_type=None,
instance_type=None,
environment=None,
ami=None,
region=None,
subnet_ids=[],
role=None,
keypair=None,
security_groups=None,
autoscaling_group=None,
desired_capacity=1,
max_size=1,
min_size=1,
default_cooldown=300,
availability_zones=None,
health_check_grace_period=300,
launch_configuration=None):

self.log = logging.getLogger('tyr.clusters.IISCluster')
self.group = group
self.server_type = server_type
self.instance_type = instance_type
self.environment = environment
self.ami = ami
self.region = region
self.role = role
self.subnet_ids = subnet_ids

self.keypair = keypair
self.security_groups = security_groups
self.autoscaling_group = autoscaling_group
self.desired_capacity = desired_capacity
self.max_size = max_size
self.min_size = min_size
self.default_cooldown = default_cooldown
self.availability_zones = availability_zones
self.health_check_grace_period = health_check_grace_period
self.launch_configuration = launch_configuration

if subnet_ids:
self.node_subnet = self.subnet_ids[0]
else:
self.node_subnet = None

if self.availability_zones:
self.node_zone = availability_zones[0]
else:
self.node_zone = None

def provision(self):

self.log.info('Provisioning IISCluster')
if not self.launch_configuration:
self.launch_configuration = "{0}-{1}-web".format(
self.environment[0], self.group)
if not self.autoscaling_group:
if self.subnet_ids:
templ = "{0}-{1}-web-asg-vpc"
else:
templ = "{0}-{1}-web-asg"
self.autoscaling_group = templ.format(
self.environment[0], self.group)

# Template to use with an autoscaling group
node = IISNode(group=self.group,
server_type=self.server_type,
instance_type=self.instance_type,
environment=self.environment,
ami=self.ami,
region=self.region,
role=self.role,
keypair=self.keypair,
availability_zone=self.node_zone,
security_groups=self.security_groups,
subnet_id=self.node_subnet)
node.configure()

self.log.info('Creating autoscaler')
auto = AutoScaler(launch_configuration=self.launch_configuration,
autoscaling_group=self.autoscaling_group,
desired_capacity=self.desired_capacity,
max_size=self.max_size,
min_size=self.min_size,
default_cooldown=self.default_cooldown,
availability_zones=self.availability_zones,
subnet_ids=self.subnet_ids,
health_check_grace_period=self.
health_check_grace_period,
node_obj=node)
auto.autorun()

def baked(self):
return all([node.baked() for node in self.nodes])

def autorun(self):
self.provision()
7 changes: 7 additions & 0 deletions tyr/policies/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
'allow-describe-elbs': elb.allow_describe_elbs,
'allow-modify-nginx-elbs-stage': elb.allow_modify_nginx_elbs_stage,
'allow-modify-nginx-elbs-prod': elb.allow_modify_nginx_elbs_prod,
'allow-outpost-sns-stage': ec2.allow_outpost_sns_stage,
'allow-outpost-sns-prod': ec2.allow_outpost_sns_prod,
'allow-web-initialization-prod': ec2.allow_web_initialization_prod,
'allow-web-initialization-stage': ec2.allow_web_initialization_stage,
'allow-set-cloudwatch-alarms': ec2.allow_set_cloudwatch_alarms,
'allow-remove-cloudwatch-alarms': ec2.allow_remove_cloudwatch_alarms,
'allow-deploy-web-updates': ec2.allow_deploy_web_updates,
'allow-describe-snapshots': ec2.allow_describe_snapshots,
'allow-get-hudl-config': s3.allow_get_hudl_config
}
Loading

0 comments on commit d9b6aa2

Please sign in to comment.