summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrlotun <rlotun@gmail.com>2011-03-31 14:38:28 +0100
committerrlotun <rlotun@gmail.com>2011-03-31 14:38:28 +0100
commitded10012872348af0e87b8010e61619f37bd8054 (patch)
tree1449b7eb620a9323585382cb5bd8fcb7d20fe24a
parenta4e8e065473b5ff9af554ceb91391f286ac5cac7 (diff)
parentc20653804a474658e396f9fb42f52c139fe9b7ba (diff)
downloadboto-ded10012872348af0e87b8010e61619f37bd8054.tar.gz
Merge branch 'autoscale-20100801'
Conflicts: boto/ec2/autoscale/__init__.py boto/ec2/autoscale/group.py
-rw-r--r--boto/ec2/autoscale/__init__.py283
-rw-r--r--boto/ec2/autoscale/activity.py17
-rw-r--r--boto/ec2/autoscale/group.py151
-rw-r--r--boto/ec2/autoscale/instance.py22
-rw-r--r--boto/ec2/autoscale/launchconfig.py78
-rw-r--r--boto/ec2/autoscale/policy.py146
-rw-r--r--boto/ec2/autoscale/scheduled.py55
-rw-r--r--boto/ec2/autoscale/trigger.py134
8 files changed, 626 insertions, 260 deletions
diff --git a/boto/ec2/autoscale/__init__.py b/boto/ec2/autoscale/__init__.py
index 2389b003..f4e820c8 100644
--- a/boto/ec2/autoscale/__init__.py
+++ b/boto/ec2/autoscale/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2009 Reza Lotun http://reza.lotun.name/
+# Copyright (c) 2009-2010 Reza Lotun http://reza.lotun.name/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
@@ -29,10 +29,11 @@ import boto
from boto.connection import AWSQueryConnection
from boto.ec2.regioninfo import RegionInfo
from boto.ec2.autoscale.request import Request
-from boto.ec2.autoscale.trigger import Trigger
from boto.ec2.autoscale.launchconfig import LaunchConfiguration
from boto.ec2.autoscale.group import AutoScalingGroup
from boto.ec2.autoscale.activity import Activity
+from boto.ec2.autoscale.policy import AdjustmentTypes, MetricCollectionTypes, ScalingPolicy
+from boto.ec2.autoscale.instance import Instance
RegionData = {
'us-east-1' : 'autoscaling.us-east-1.amazonaws.com',
@@ -122,20 +123,31 @@ class AutoScaleConnection(AWSQueryConnection):
def _update_group(self, op, as_group):
params = {
'AutoScalingGroupName' : as_group.name,
- 'Cooldown' : as_group.cooldown,
'LaunchConfigurationName' : as_group.launch_config_name,
'MinSize' : as_group.min_size,
'MaxSize' : as_group.max_size,
}
+ # get availability zone information (required param)
+ zones = as_group.availability_zones
+ self.build_list_params(params, zones,
+ 'AvailabilityZones')
+ if as_group.desired_capacity:
+ params['DesiredCapacity'] = as_group.desired_capacity
+ if as_group.vpc_zone_identifier:
+ params['VPCZoneIdentifier'] = as_group.vpc_zone_identifier
+ if as_group.healthcheck_grace_period:
+ params['HealthCheckGracePeriod'] = as_group.healthcheck_grace_period
+ if as_group.healthcheck_type:
+ params['HealthCheckType'] = as_group.healthcheck_type
+ if as_group.default_cooldown:
+ params['DefaultCooldown'] = as_group.default_cooldown
+ if as_group.placement_group:
+ params['PlacementGroup'] = as_group.placement_group
if op.startswith('Create'):
- if as_group.availability_zones:
- zones = as_group.availability_zones
- else:
- zones = [as_group.availability_zone]
- self.build_list_params(params, as_group.load_balancers,
- 'LoadBalancerNames')
- self.build_list_params(params, zones,
- 'AvailabilityZones')
+ # you can only associate load balancers with an autoscale group at creation time
+ if as_group.load_balancers:
+ self.build_list_params(params, as_group.load_balancers,
+ 'LoadBalancerNames')
return self.get_object(op, params, Request)
def create_auto_scaling_group(self, as_group):
@@ -144,6 +156,15 @@ class AutoScaleConnection(AWSQueryConnection):
"""
return self._update_group('CreateAutoScalingGroup', as_group)
+ def delete_auto_scaling_group(self, name):
+ """
+ Deletes the specified auto scaling group if the group has no instances
+ and no scaling activities in progress.
+ """
+ params = {'AutoScalingGroupName' : name}
+ return self.connection.get_object('DeleteAutoScalingGroup', params,
+ Request)
+
def create_launch_configuration(self, launch_config):
"""
Creates a new Launch Configuration.
@@ -154,10 +175,11 @@ class AutoScaleConnection(AWSQueryConnection):
"""
params = {
'ImageId' : launch_config.image_id,
- 'KeyName' : launch_config.key_name,
'LaunchConfigurationName' : launch_config.name,
'InstanceType' : launch_config.instance_type,
}
+ if launch_config.key_name:
+ params['KeyName'] = launch_config.key_name
if launch_config.user_data:
params['UserData'] = base64.b64encode(launch_config.user_data)
if launch_config.kernel_id:
@@ -167,58 +189,67 @@ class AutoScaleConnection(AWSQueryConnection):
if launch_config.block_device_mappings:
self.build_list_params(params, launch_config.block_device_mappings,
'BlockDeviceMappings')
- self.build_list_params(params, launch_config.security_groups,
- 'SecurityGroups')
+ if launch_config.security_groups:
+ self.build_list_params(params, launch_config.security_groups,
+ 'SecurityGroups')
+ if launch_config.instance_monitoring:
+ # XXX:
+ pass
return self.get_object('CreateLaunchConfiguration', params,
Request, verb='POST')
- def create_trigger(self, trigger):
+ def delete_launch_configuration(self, launch_config_name):
"""
+ Deletes the specified LaunchConfiguration.
+ The specified launch configuration must not be attached to an Auto
+ Scaling group. Once this call completes, the launch configuration is no
+ longer available for use.
"""
- params = {'TriggerName' : trigger.name,
- 'AutoScalingGroupName' : trigger.autoscale_group.name,
- 'MeasureName' : trigger.measure_name,
- 'Statistic' : trigger.statistic,
- 'Period' : trigger.period,
- 'Unit' : trigger.unit,
- 'LowerThreshold' : trigger.lower_threshold,
- 'LowerBreachScaleIncrement' : trigger.lower_breach_scale_increment,
- 'UpperThreshold' : trigger.upper_threshold,
- 'UpperBreachScaleIncrement' : trigger.upper_breach_scale_increment,
- 'BreachDuration' : trigger.breach_duration}
- # dimensions should be a list of tuples
- dimensions = []
- for dim in trigger.dimensions:
- name, value = dim
- dimensions.append(dict(Name=name, Value=value))
- self.build_list_params(params, dimensions, 'Dimensions')
-
- req = self.get_object('CreateOrUpdateScalingTrigger', params,
- Request)
- return req
-
- def get_all_groups(self, names=None):
+ params = {'LaunchConfigurationName' : launch_config_name}
+ return self.connection.get_object('DeleteLaunchConfiguration', params,
+ Request)
+
+ def get_all_groups(self, names=None, max_records=None, next_token=None):
"""
+ Returns a full description of each Auto Scaling group in the given
+ list. This includes all Amazon EC2 instances that are members of the
+ group. If a list of names is not provided, the service returns the full
+ details of all Auto Scaling groups.
+
+ This action supports pagination by returning a token if there are more
+ pages to retrieve. To get the next page, call this action again with
+ the returned token as the NextToken parameter.
"""
params = {}
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
if names:
self.build_list_params(params, names, 'AutoScalingGroupNames')
return self.get_list('DescribeAutoScalingGroups', params,
[('member', AutoScalingGroup)])
- def get_all_launch_configurations(self, names=None):
+ def get_all_launch_configurations(self, names=None, max_records=None, next_token=None):
"""
+ Returns a full description of the launch configurations given the
+ specified names.
+
+ If no names are specified, then the full details of all launch
+ configurations are returned.
"""
params = {}
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
if names:
self.build_list_params(params, names, 'LaunchConfigurationNames')
return self.get_list('DescribeLaunchConfigurations', params,
[('member', LaunchConfiguration)])
- def get_all_activities(self, autoscale_group,
- activity_ids=None,
- max_records=100):
+ def get_all_activities(self, autoscale_group, activity_ids=None, max_records=None, next_token=None):
"""
Get all activities for the given autoscaling group.
@@ -232,15 +263,35 @@ class AutoScaleConnection(AWSQueryConnection):
if isinstance(autoscale_group, AutoScalingGroup):
name = autoscale_group.name
params = {'AutoScalingGroupName' : name}
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
if activity_ids:
self.build_list_params(params, activity_ids, 'ActivityIds')
- return self.get_list('DescribeScalingActivities', params,
- [('member', Activity)])
+ return self.get_list('DescribeScalingActivities', params, [('member', Activity)])
- def get_all_triggers(self, autoscale_group):
- params = {'AutoScalingGroupName' : autoscale_group}
- return self.get_list('DescribeTriggers', params,
- [('member', Trigger)])
+ def get_all_scheduled_actions(self, autoscale_group=None, scheduled_actions=None,
+ start_time=None, end_time=None, max_records=None, next_token=None):
+ """
+ Lists all the actions scheduled for your Auto Scaling group that haven't been executed.
+ """
+ params = {}
+ # XXX
+ if autoscale_group:
+ params['AutoScalingGroupName'] = autoscale_group
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
+
+ def delete_scheduled_action(self, scheduled_action_name, autoscale_group=None):
+ params = {
+ 'ScheduledActionName' : scheduled_action_name,
+ }
+ if autoscale_group:
+ params['AutoScalingGroupName'] = autoscale_group
+ return self.get_status('DeleteScheduledAction', params)
def terminate_instance(self, instance_id, decrement_capacity=True):
params = {
@@ -250,6 +301,142 @@ class AutoScaleConnection(AWSQueryConnection):
return self.get_object('TerminateInstanceInAutoScalingGroup', params,
Activity)
+ def delete_policy(self, policy_name, autoscale_group=None):
+ params = {
+ 'PolicyName' : policy_name,
+ }
+ if autoscale_group:
+ params['AutoScalingGroupName'] = autoscale_group
+ return self.get_status('DeletePolicy', params)
+
+ def get_all_adjustment_types(self):
+ return self.get_list('DescribeAdjustmentTypes', {}, [('member', AdjustmentTypes)])
+
+ def get_all_autoscaling_instances(self, instance_ids=None, max_records=None, next_token=None):
+ """
+ Returns a description of each Auto Scaling instance in the InstanceIds
+ list. If a list is not provided, the service returns the full details
+ of all instances up to a maximum of fifty.
+
+ This action supports pagination by returning a token if there are more
+ pages to retrieve. To get the next page, call this action again with
+ the returned token as the NextToken parameter.
+ """
+ params = {}
+ if instance_ids:
+ self.build_list_params(params, instance_ids, 'InstanceIds')
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
+ return self.get_object('DescribeAutoscalingInstances', params, Instance)
+
+ def get_all_metric_collection_types(self):
+ """ Returns a list of metrics and a corresponding list of granularities
+ for each metric.
+ """
+ return self.get_object('DescribeMetricCollectionTypes', {}, MetricCollectionTypes)
+
+ def get_all_policies(self, as_group=None, policy_names=None, max_records=None, next_token=None):
+ """
+ Returns descriptions of what each policy does. This action supports
+ pagination. If the response includes a token, there are more records
+ available. To get the additional records, repeat the request with the
+ response token as the NextToken parameter.
+ """
+ params = {}
+ if as_group:
+ params['AutoScalingGroupName'] = as_group
+ if policy_names:
+ self.build_list_params(params, policy_names, 'PolicyNames')
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
+ return self.get_list('DescribePolicies', params, [('member', ScalingPolicy)])
+
+ def get_all_scaling_process_types(self):
+ # XXX
+ return self.get_object('DescribeScalingProcessTypes', {}, {})
+
+ def get_all_scheduled_actions(self, as_group=None, start_time=None, end_time=None, scheduled_actions=None,
+ max_records=None, next_token=None):
+ params = {}
+ if as_group:
+ params['AutoScalingGroupName'] = as_group
+ if scheduled_actions:
+ self.build_list_params(params, scheduled_actions, 'ScheduledActionNames')
+ if max_records:
+ params['MaxRecords'] = max_records
+ if next_token:
+ params['NextToken'] = next_token
+ #XXX
+ return self.get_object('DescribeScheduledActions', params, {})
+
+ def disable_metrics_collection(self, as_group, metrics=None):
+ """
+ Disables monitoring of group metrics for the Auto Scaling group
+ specified in AutoScalingGroupName. You can specify the list of affected
+ metrics with the Metrics parameter.
+ """
+ params = {
+ 'AutoScalingGroupName' : as_group,
+ }
+ if metrics:
+ self.build_list_params(params, metrics, 'Metrics')
+ return self.get_status('DisableMetricsCollection', params)
+
+ def enable_metrics_collection(self, as_group, granularity, metrics=None):
+ """
+ Enables monitoring of group metrics for the Auto Scaling group
+ specified in AutoScalingGroupName. You can specify the list of enabled
+ metrics with the Metrics parameter.
+
+ Auto scaling metrics collection can be turned on only if the
+ InstanceMonitoring.Enabled flag, in the Auto Scaling group's launch
+ configuration, is set to true.
+
+ :type autoscale_group: string
+ :param autoscale_group: The auto scaling group to get activities on.
+
+ :type granularity: string
+ :param granularity: The granularity to associate with the metrics to
+ collect. Currently, the only legal granularity is "1Minute".
+
+ :type metrics: string list
+ :param metrics: The list of metrics to collect. If no metrics are
+ specified, all metrics are enabled.
+ """
+ params = {
+ 'AutoScalingGroupName' : as_group,
+ 'Granularity' : granularity,
+ }
+ if metrics:
+ self.build_list_params(params, metrics, 'Metrics')
+ return self.get_status('EnableMetricsCollection', params)
+
+ def execute_policy(self, policy_name, as_group=None, honor_cooldown=None):
+ params = {
+ 'PolicyName' : policy_name,
+ }
+ if as_group:
+ params['AutoScalingGroupName'] = as_group
+ if honor_cooldown:
+ params['HonorCooldown'] = honor_cooldown
+ return self.get_status('ExecutePolicy', params)
+
+ def put_scaling_policy(self, policy_name, as_group, adjustment_type, scaling_adjustment, cooldown=None):
+ params = {
+ 'PolicyName' : policy_name,
+ 'AutoScalingGroupName' : as_group,
+ 'AdjustmentType' : adjustment_type,
+ 'ScalingAdjustment' : scaling_adjustment,
+ }
+ if cooldown:
+ params['Cooldown'] = cooldown
+ # XXX
+ return self.get_object('PutScalingPolicy', params, {})
+
def set_instance_health(self, instance_id, health_status,
should_respect_grace_period=True):
"""
diff --git a/boto/ec2/autoscale/activity.py b/boto/ec2/autoscale/activity.py
index f895d65e..01c0ba25 100644
--- a/boto/ec2/autoscale/activity.py
+++ b/boto/ec2/autoscale/activity.py
@@ -24,30 +24,41 @@ class Activity(object):
def __init__(self, connection=None):
self.connection = connection
self.start_time = None
+ self.end_time = None
self.activity_id = None
self.progress = None
self.status_code = None
self.cause = None
self.description = None
+ self.status_message = None
+ self.group_name = None
def __repr__(self):
- return 'Activity:%s status:%s progress:%s' % (self.description,
- self.status_code,
- self.progress)
+ return 'Activity<%s>: For group:%s, progress:%s, cause:%s' % (self.activity_id,
+ self.group_name,
+ self.status_message,
+ self.cause)
+
def startElement(self, name, attrs, connection):
return None
def endElement(self, name, value, connection):
if name == 'ActivityId':
self.activity_id = value
+ elif name == 'AutoScalingGroupName':
+ self.group_name = value
elif name == 'StartTime':
self.start_time = value
+ elif name == 'EndTime':
+ self.end_time = value
elif name == 'Progress':
self.progress = value
elif name == 'Cause':
self.cause = value
elif name == 'Description':
self.description = value
+ elif name == 'StatusMessage':
+ self.status_message = value
elif name == 'StatusCode':
self.status_code = value
else:
diff --git a/boto/ec2/autoscale/group.py b/boto/ec2/autoscale/group.py
index 9010a726..e3ffba45 100644
--- a/boto/ec2/autoscale/group.py
+++ b/boto/ec2/autoscale/group.py
@@ -22,37 +22,59 @@
import weakref
from boto.ec2.elb.listelement import ListElement
from boto.resultset import ResultSet
-from boto.ec2.autoscale.trigger import Trigger
from boto.ec2.autoscale.request import Request
+from boto.ec2.autoscale.instance import Instance
+from boto.ec2.autoscale.launchconfig import LaunchConfiguration
-class Instance(object):
+class SuspendedProcess(object):
def __init__(self, connection=None):
self.connection = connection
- self.instance_id = ''
+ self.process_name = None
+ self.reason = None
def __repr__(self):
- return 'Instance:%s' % self.instance_id
+ return 'SuspendedProcess(%s, %s)' % (self.process_name, self.reason)
def startElement(self, name, attrs, connection):
- return None
+ pass
def endElement(self, name, value, connection):
- if name == 'InstanceId':
- self.instance_id = value
- else:
- setattr(self, name, value)
+ if name == 'ProcessName':
+ self.process_name = value
+ elif name == 'SuspensionReason':
+ self.reason = value
+
+class EnabledMetric(object):
+ def __init__(self, connection=None, metric=None, granularity=None):
+ self.connection = connection
+ self.metric = metric
+ self.granularity = granularity
+
+ def __repr__(self):
+ return 'EnabledMetric(%s, %s)' % (self.metric, self.granularity)
+
+ def startElement(self, name, attrs, connection):
+ pass
+
+ def endElement(self, name, value, connection):
+ if name == 'Granularity':
+ self.granularity = value
+ elif name == 'Metric':
+ self.metric = value
class AutoScalingGroup(object):
- def __init__(self, connection=None, group_name=None,
- availability_zone=None, launch_config=None,
+ def __init__(self, connection=None, name=None,
+ launch_config=None,
availability_zones=None,
load_balancers=None, cooldown=0,
min_size=None, max_size=None,
group_arn=None, health_check_type=None,
health_check_period=None, suspended=None,
- placement_group=None, vpc_zone=None):
+ placement_group=None, vpc_zone=None,
+ default_cooldown=None,
+ desired_capacity=None):
"""
Creates a new AutoScalingGroup with the specified name.
@@ -64,18 +86,12 @@ class AutoScalingGroup(object):
:type name: str
:param name: Name of autoscaling group.
- :type availability_zone: str
- :param availability_zone: An availability zone. DEPRECATED - use the
- availability_zones parameter, which expects
- a list of availability zone
- strings
-
- :type availability_zone: list
- :param availability_zone: List of availability zones.
-
:type launch_config: str
:param launch_config: Name of launch configuration name.
+ :type availability_zones: list
+ :param availability_zones: List of availability zones.
+
:type load_balancers: list
:param load_balancers: List of load balancers.
@@ -85,29 +101,31 @@ class AutoScalingGroup(object):
:type maxsize: int
:param maxsize: Maximum size of group
- :type cooldown: int
- :param cooldown: Amount of time after a Scaling Activity completes
- before any further scaling activities can start.
+ :type default_cooldown: int
+ :param default_cooldown: Number of seconds after a Scaling Activity completes
+ before any further scaling activities can start.
+
+ :type desired_capacity: int
+ :param desired_capacity: The desired capacity for the group.
- :rtype: tuple
- :return: Updated healthcheck for the instances.
+ :rtype: autoscale group
+ :return: An autoscale group.
"""
- self.name = group_name
+ self.name = name
self.connection = connection
- self.min_size = min_size
- self.max_size = max_size
+ self.min_size = int(min_size) if min_size is not None else None
+ self.max_size = int(max_size) if max_size is not None else None
self.created_time = None
- self.cooldown = cooldown
+ self.default_cooldown = int(default_cooldown) if default_cooldown is not None else None
self.launch_config = launch_config
if self.launch_config:
self.launch_config_name = self.launch_config.name
else:
self.launch_config_name = None
- self.desired_capacity = None
+ self.desired_capacity = desired_capacity
lbs = load_balancers or []
self.load_balancers = ListElement(lbs)
zones = availability_zones or []
- self.availability_zone = availability_zone
self.availability_zones = ListElement(zones)
self.group_arn = group_arn
self.health_check_type = health_check_type
@@ -117,9 +135,25 @@ class AutoScalingGroup(object):
self.vpc_zone = vpc_zone
self.metrics = None
self.instances = None
+ self.placement_group = None
+ self.autoscaling_group_arn = None
+ self.healthcheck_grace_period = None
+ self.healthcheck_type = None
+ self.vpc_zone_identifier = None
+
+ # backwards compatible access to 'cooldown' param
+ def _get_cooldown(self):
+ return self.default_cooldown
+ def _set_cooldown(self, val):
+ self.default_cooldown = val
+ cooldown = property(_get_cooldown, _set_cooldown)
def __repr__(self):
- return 'AutoScalingGroup:%s' % self.name
+ return 'AutoScalingGroup<%s>: created:%s, minsize:%s, maxsize:%s, capacity:%s' % (self.name,
+ self.created_time,
+ self.min_size,
+ self.max_size,
+ self.desired_capacity)
def startElement(self, name, attrs, connection):
if name == 'Instances':
@@ -130,38 +164,37 @@ class AutoScalingGroup(object):
elif name == 'AvailabilityZones':
return self.availability_zones
elif name == 'EnabledMetrics':
- self.metrics = ResultSet([('member', AutoScalingGroupMetric)])
- return self.metrics
+ self.enabled_metrics = ResultSet([('member', EnabledMetric)])
+ elif name == 'SuspendedProcesses':
+ self.suspended_processes = ResultSet([('member', SuspendedProcess)])
else:
return
def endElement(self, name, value, connection):
if name == 'MinSize':
- self.min_size = value
+ self.min_size = int(value)
+ elif name == 'AutoScalingGroupARN':
+ self.autoscaling_group_arn = value
elif name == 'CreatedTime':
self.created_time = value
elif name == 'DefaultCooldown':
- self.cooldown = value
+ self.default_cooldown = int(value)
elif name == 'LaunchConfigurationName':
self.launch_config_name = value
elif name == 'DesiredCapacity':
- self.desired_capacity = value
+ self.desired_capacity = int(value)
elif name == 'MaxSize':
- self.max_size = value
+ self.max_size = int(value)
elif name == 'AutoScalingGroupName':
self.name = value
- elif name == 'AutoScalingGroupARN':
- self.group_arn = value
- elif name == 'HealthCheckType':
- self.health_check_type = value
- elif name == 'HealthCheckGracePeriod':
- self.health_check_period = value
- elif name == 'SuspendedProcesses':
- self.suspended = value
elif name == 'PlacementGroup':
self.placement_group = value
+ elif name == 'HealthCheckGracePeriod':
+ self.healthcheck_grace_period = int(value)
+ elif name == 'HealthCheckType':
+ self.healthcheck_type = value
elif name == 'VPCZoneIdentifier':
- self.vpc_zone = value
+ self.vpc_zone_identifier = value
else:
setattr(self, name, value)
@@ -188,25 +221,13 @@ class AutoScalingGroup(object):
self.max_size = 0
self.update()
- def get_all_triggers(self):
- """ Get all triggers for this auto scaling group. """
- params = {'AutoScalingGroupName' : self.name}
- triggers = self.connection.get_list('DescribeTriggers', params,
- [('member', Trigger)])
-
- # allow triggers to be able to access the autoscale group
- for tr in triggers:
- tr.autoscale_group = weakref.proxy(self)
-
- return triggers
-
def delete(self):
- """ Delete this auto-scaling group. """
- params = {'AutoScalingGroupName' : self.name}
- return self.connection.get_object('DeleteAutoScalingGroup', params,
- Request)
+ """ Delete this auto-scaling group if no instances attached or no
+ scaling activities in progress.
+ """
+ return self.connection.delete_auto_scaling_group(self.name)
- def get_activities(self, activity_ids=None, max_records=100):
+ def get_activities(self, activity_ids=None, max_records=50):
"""
Get all activies for this group.
"""
diff --git a/boto/ec2/autoscale/instance.py b/boto/ec2/autoscale/instance.py
index ffdd5b18..6eb89c2c 100644
--- a/boto/ec2/autoscale/instance.py
+++ b/boto/ec2/autoscale/instance.py
@@ -23,12 +23,21 @@
class Instance(object):
def __init__(self, connection=None):
self.connection = connection
- self.instance_id = ''
+ self.instance_id = None
+ self.health_status = None
+ self.launch_config_name = None
self.lifecycle_state = None
- self.availability_zone = ''
+ self.availability_zone = None
+ self.group_name = None
def __repr__(self):
- return 'Instance:%s' % self.instance_id
+ r = 'Instance<id:%s, state:%s, health:%s' % (self.instance_id,
+ self.lifecycle_state,
+ self.health_status)
+ if self.group_name:
+ r += ' group:%s' % self.group_name
+ r += '>'
+ return r
def startElement(self, name, attrs, connection):
return None
@@ -36,11 +45,16 @@ class Instance(object):
def endElement(self, name, value, connection):
if name == 'InstanceId':
self.instance_id = value
+ elif name == 'HealthStatus':
+ self.health_status = value
+ elif name == 'LaunchConfigurationName':
+ self.launch_config_name = value
elif name == 'LifecycleState':
self.lifecycle_state = value
elif name == 'AvailabilityZone':
self.availability_zone = value
+ elif name == 'AutoScalingGroupName':
+ self.group_name = value
else:
setattr(self, name, value)
-
diff --git a/boto/ec2/autoscale/launchconfig.py b/boto/ec2/autoscale/launchconfig.py
index 7587cb64..0c0c1cf3 100644
--- a/boto/ec2/autoscale/launchconfig.py
+++ b/boto/ec2/autoscale/launchconfig.py
@@ -20,15 +20,59 @@
# IN THE SOFTWARE.
+from boto.resultset import ResultSet
from boto.ec2.autoscale.request import Request
from boto.ec2.elb.listelement import ListElement
+# this should use the corresponding object from boto.ec2
+class Ebs(object):
+ def __init__(self, connection=None, snapshot_id=None, volume_size=None):
+ self.connection = connection
+ self.snapshot_id = snapshot_id
+ self.volume_size = volume_size
+
+ def __repr__(self):
+ return 'Ebs(%s, %s)' % (self.snapshot_id, self.volume_size)
+
+ def startElement(self, name, attrs, connection):
+ pass
+
+ def endElement(self, name, value, connection):
+ if name == 'SnapshotId':
+ self.snapshot_id = value
+ elif name == 'VolumeSize':
+ self.volume_size = value
+
+
+# this should use the BlockDeviceMapping from boto.ec2.blockdevicemapping
+class BlockDeviceMapping(object):
+ def __init__(self, connection=None, device_name=None, virtual_name=None):
+ self.connection = connection
+ self.device_name = None
+ self.virtual_name = None
+ self.ebs = None
+
+ def __repr__(self):
+ return 'BlockDeviceMapping(%s, %s)' % (self.device_name, self.virtual_name)
+
+ def startElement(self, name, attrs, connection):
+ if name == 'Ebs':
+ self.ebs = Ebs(self)
+ return self.ebs
+
+ def endElement(self, name, value, connection):
+ if name == 'DeviceName':
+ self.device_name = value
+ elif name == 'VirtualName':
+ self.virtual_name = value
+
class LaunchConfiguration(object):
def __init__(self, connection=None, name=None, image_id=None,
key_name=None, security_groups=None, user_data=None,
instance_type='m1.small', kernel_id=None,
- ramdisk_id=None, block_device_mappings=None):
+ ramdisk_id=None, block_device_mappings=None,
+ instance_monitoring=False):
"""
A launch configuration.
@@ -46,6 +90,23 @@ class LaunchConfiguration(object):
:param security_groups: Names of the security groups with which to
associate the EC2 instances.
+ :type user_data: str
+ :param user_data: The user data available to launched EC2 instances.
+
+ :type instance_type: str
+ :param instance_type: The instance type
+
+ :type kern_id: str
+ :param kern_id: Kernel id for instance
+
+ :type ramdisk_id: str
+ :param ramdisk_id: RAM disk id for instance
+
+ :type block_device_mappings: list
+ :param block_device_mappings: Specifies how block devices are exposed for instances
+
+ :type instance_monitoring: bool
+ :param instance_monitoring: Whether instances in group are launched with detailed monitoring.
"""
self.connection = connection
self.name = name
@@ -60,6 +121,8 @@ class LaunchConfiguration(object):
self.kernel_id = kernel_id
self.user_data = user_data
self.created_time = None
+ self.instance_monitoring = instance_monitoring
+ self.launch_configuration_arn = None
def __repr__(self):
return 'LaunchConfiguration:%s' % self.name
@@ -67,8 +130,9 @@ class LaunchConfiguration(object):
def startElement(self, name, attrs, connection):
if name == 'SecurityGroups':
return self.security_groups
- else:
- return
+ elif name == 'BlockDeviceMappings':
+ self.block_device_mappings = ResultSet([('member', BlockDeviceMapping)])
+ return self.instances
def endElement(self, name, value, connection):
if name == 'InstanceType':
@@ -87,12 +151,14 @@ class LaunchConfiguration(object):
self.ramdisk_id = value
elif name == 'UserData':
self.user_data = value
+ elif name == 'LaunchConfigurationARN':
+ self.launch_configuration_arn = value
+ elif name == 'InstanceMonitoring':
+ selfinstance_monitoring = value
else:
setattr(self, name, value)
def delete(self):
""" Delete this launch configuration. """
- params = {'LaunchConfigurationName' : self.name}
- return self.connection.get_object('DeleteLaunchConfiguration', params,
- Request)
+ return self.connection.delete_launch_configuration(self.name)
diff --git a/boto/ec2/autoscale/policy.py b/boto/ec2/autoscale/policy.py
new file mode 100644
index 00000000..4095359c
--- /dev/null
+++ b/boto/ec2/autoscale/policy.py
@@ -0,0 +1,146 @@
+# Copyright (c) 2009-2010 Reza Lotun http://reza.lotun.name/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+
+from boto.resultset import ResultSet
+from boto.ec2.autoscale.request import Request
+from boto.ec2.elb.listelement import ListElement
+
+
+class Alarm(object):
+ def __init__(self, connection=None):
+ self.connection = connection
+ self.name = None
+ self.alarm_arn = None
+
+ def __repr__(self):
+ return 'Alarm:%s' % self.name
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'AlarmName':
+ self.name = value
+ elif name == 'AlarmARN':
+ self.alarm_arn = value
+ else:
+ setattr(self, name, value)
+
+
+class AdjustmentTypes(object):
+ def __init__(self, connection=None):
+ self.connection = connection
+ self.adjustment_types = ListElement([])
+
+ def __repr__(self):
+ return 'AdjustmentTypes:%s' % self.adjustment_types
+
+ def startElement(self, name, attrs, connection):
+ if name == 'AdjustmentTypes':
+ return self.adjustment_types
+
+ def endElement(self, name, value, connection):
+ return
+
+
+class MetricCollectionTypes(object):
+ class BaseType(object):
+ arg = ''
+ def __init__(self, connection):
+ self.connection = connection
+ self.val = None
+ def __repr__(self):
+ return '%s:%s' % (self.arg, self.val)
+ def startElement(self, name, attrs, connection):
+ return
+ def endElement(self, name, value, connection):
+ if name == self.arg:
+ self.val = value
+ class Metric(BaseType):
+ arg = 'Metric'
+ class Granularity(BaseType):
+ arg = 'Granularity'
+
+ def __init__(self, connection=None):
+ self.connection = connection
+ self.metrics = []
+ self.granularities = []
+
+ def __repr__(self):
+ return 'MetricCollectionTypes:<%s, %s>' % (self.metrics, self.granularities)
+
+ def startElement(self, name, attrs, connection):
+ if name == 'Granularities':
+ self.granularities = ResultSet([('member', self.Granularity)])
+ return self.granularities
+ elif name == 'Metrics':
+ self.metrics = ResultSet([('member', self.Metric)])
+ return self.metrics
+
+ def endElement(self, name, value, connection):
+ return
+
+
+class ScalingPolicy(object):
+ def __init__(self, connection=None, name=None):
+ """
+ Scaling Policy
+
+ :type name: str
+ :param name: Name of scaling policy
+ """
+ self.connection = connection
+ self.name = name
+ self.group_name = None
+ self.policy_arn = None
+ self.scaling_adjustment = None
+ self.cooldown = None
+ self.adjustment_type = None
+ self.alarms = None
+
+ def __repr__(self):
+ return 'ScalingPolicy(%s group:%s adjustment:%s)' % (self.name,
+ self.group_name,
+ self.adjustment_type)
+
+ def startElement(self, name, attrs, connection):
+ if name == 'Alarms':
+ self.alarms = ResultSet([('member', Alarm)])
+ return self.alarms
+
+ def endElement(self, name, value, connection):
+ if name == 'PolicyName':
+ self.name = value
+ elif name == 'AutoScalingGroupName':
+ self.group_name = value
+ elif name == 'PolicyARN':
+ self.policy_arn = value
+ elif name == 'ScalingAdjustment':
+ self.scaling_adjustment = value
+ elif name == 'Cooldown':
+ self.cooldown = int(value)
+ elif name == 'AdjustmentType':
+ self.adjustment_type = int(value)
+
+ def delete(self, autoscale_group=None):
+ return self.connection.delete_policy(self.name, autoscale_group)
+
diff --git a/boto/ec2/autoscale/scheduled.py b/boto/ec2/autoscale/scheduled.py
new file mode 100644
index 00000000..66d716c9
--- /dev/null
+++ b/boto/ec2/autoscale/scheduled.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2009-2010 Reza Lotun http://reza.lotun.name/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+
+from boto.resultset import ResultSet
+from boto.ec2.autoscale.request import Request
+from boto.ec2.elb.listelement import ListElement
+
+
+class ScheduledUpdateGroupAction(object):
+ def __init__(self, connection=None):
+ self.connection = connection
+ self.name = None
+ self.alarm_arn = None
+
+ def __repr__(self):
+ return 'ScheduledUpdateGroupAction:%s' % self.name
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'DesiredCapacity':
+ self.desired_capacity = value
+ elif name = 'ScheduledActionName':
+ self.name = value
+ elif name == 'MaxSize':
+ self.max_size = int(value)
+ elif name == 'MinSize':
+ self.min_size = int(value)
+ elif name == 'ScheduledActionARN':
+ self.action_arn = value
+ elif name == 'Time':
+ self.time = value
+ else:
+ setattr(self, name, value)
+
diff --git a/boto/ec2/autoscale/trigger.py b/boto/ec2/autoscale/trigger.py
deleted file mode 100644
index 2840e67e..00000000
--- a/boto/ec2/autoscale/trigger.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright (c) 2009 Reza Lotun http://reza.lotun.name/
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish, dis-
-# tribute, sublicense, and/or sell copies of the Software, and to permit
-# persons to whom the Software is furnished to do so, subject to the fol-
-# lowing conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
-# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-import weakref
-
-from boto.ec2.autoscale.request import Request
-
-
-class Trigger(object):
- """
- An auto scaling trigger.
- """
-
- def __init__(self, connection=None, name=None, autoscale_group=None,
- dimensions=None, measure_name=None,
- statistic=None, unit=None, period=60,
- lower_threshold=None,
- lower_breach_scale_increment=None,
- upper_threshold=None,
- upper_breach_scale_increment=None,
- breach_duration=None):
- """
- Initialize an auto-scaling trigger object.
-
- :type name: str
- :param name: The name for this trigger
-
- :type autoscale_group: str
- :param autoscale_group: The name of the AutoScalingGroup that will be
- associated with the trigger. The AutoScalingGroup
- that will be affected by the trigger when it is
- activated.
-
- :type dimensions: list
- :param dimensions: List of tuples, i.e.
- ('ImageId', 'i-13lasde') etc.
-
- :type measure_name: str
- :param measure_name: The measure name associated with the metric used by
- the trigger to determine when to activate, for
- example, CPU, network I/O, or disk I/O.
-
- :type statistic: str
- :param statistic: The particular statistic used by the trigger when
- fetching metric statistics to examine.
-
- :type period: int
- :param period: The period associated with the metric statistics in
- seconds. Valid Values: 60 or a multiple of 60.
-
- :type unit: str
- :param unit: The unit of measurement.
- """
- self.name = name
- self.connection = connection
- self.dimensions = dimensions
- self.breach_duration = breach_duration
- self.upper_breach_scale_increment = upper_breach_scale_increment
- self.created_time = None
- self.upper_threshold = upper_threshold
- self.status = None
- self.lower_threshold = lower_threshold
- self.period = period
- self.lower_breach_scale_increment = lower_breach_scale_increment
- self.statistic = statistic
- self.unit = unit
- self.namespace = None
- if autoscale_group:
- self.autoscale_group = weakref.proxy(autoscale_group)
- else:
- self.autoscale_group = None
- self.measure_name = measure_name
-
- def __repr__(self):
- return 'Trigger:%s' % (self.name)
-
- def startElement(self, name, attrs, connection):
- return None
-
- def endElement(self, name, value, connection):
- if name == 'BreachDuration':
- self.breach_duration = value
- elif name == 'TriggerName':
- self.name = value
- elif name == 'Period':
- self.period = value
- elif name == 'CreatedTime':
- self.created_time = value
- elif name == 'Statistic':
- self.statistic = value
- elif name == 'Unit':
- self.unit = value
- elif name == 'Namespace':
- self.namespace = value
- elif name == 'AutoScalingGroupName':
- self.autoscale_group_name = value
- elif name == 'MeasureName':
- self.measure_name = value
- else:
- setattr(self, name, value)
-
- def update(self):
- """ Write out differences to trigger. """
- self.connection.create_trigger(self)
-
- def delete(self):
- """ Delete this trigger. """
- params = {
- 'TriggerName' : self.name,
- 'AutoScalingGroupName' : self.autoscale_group_name,
- }
- req =self.connection.get_object('DeleteTrigger', params,
- Request)
- self.connection.last_request = req
- return req
-