diff options
author | Jann Kleen <jann@pocketvillage.com> | 2011-03-27 20:50:56 +0200 |
---|---|---|
committer | Jann Kleen <jann@pocketvillage.com> | 2011-03-27 20:50:56 +0200 |
commit | 34c7ca71f725b3971b1e8ca9151e1568bcd48fd0 (patch) | |
tree | a0daa8d4a98e432ae06bf416a508187dce8058a1 | |
parent | 19c57e3b2e36d0201a6c352fe75c134133d0e0af (diff) | |
parent | c20653804a474658e396f9fb42f52c139fe9b7ba (diff) | |
download | boto-34c7ca71f725b3971b1e8ca9151e1568bcd48fd0.tar.gz |
merged with rlotun autoscale-branch
-rw-r--r-- | boto/ec2/autoscale/__init__.py | 334 | ||||
-rw-r--r-- | boto/ec2/autoscale/activity.py | 17 | ||||
-rw-r--r-- | boto/ec2/autoscale/group.py | 163 | ||||
-rw-r--r-- | boto/ec2/autoscale/instance.py | 22 | ||||
-rw-r--r-- | boto/ec2/autoscale/launchconfig.py | 78 | ||||
-rw-r--r-- | boto/ec2/autoscale/policy.py | 146 | ||||
-rw-r--r-- | boto/ec2/autoscale/scheduled.py | 55 |
7 files changed, 629 insertions, 186 deletions
diff --git a/boto/ec2/autoscale/__init__.py b/boto/ec2/autoscale/__init__.py index 96c6aa40..43f61080 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 @@ -24,58 +24,21 @@ This module provides an interface to the Elastic Compute Cloud (EC2) Auto Scaling service. """ -import base64 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 - -RegionData = { - 'us-east-1' : 'autoscaling.us-east-1.amazonaws.com', - 'us-west-1' : 'autoscaling.us-west-1.amazonaws.com', - 'eu-west-1' : 'autoscaling.eu-west-1.amazonaws.com', - 'ap-southeast-1' : 'autoscaling.ap-southeast-1.amazonaws.com'} - -def regions(): - """ - Get all available regions for the Auto Scaling service. - - :rtype: list - :return: A list of :class:`boto.RegionInfo` instances - """ - regions = [] - for region_name in RegionData: - region = RegionInfo(name=region_name, - endpoint=RegionData[region_name], - connection_cls=AutoScaleConnection) - regions.append(region) - return regions - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ec2.autoscale.AutoScaleConnection`. - - :param str region_name: The name of the region to connect to. - - :rtype: :class:`boto.ec2.AutoScaleConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None +from boto.ec2.autoscale.policy import AdjustmentTypes, MetricCollectionTypes, ScalingPolicy +from boto.ec2.autoscale.instance import Instance class AutoScaleConnection(AWSQueryConnection): APIVersion = boto.config.get('Boto', 'autoscale_version', '2010-08-01') DefaultRegionEndpoint = boto.config.get('Boto', 'autoscale_endpoint', - 'autoscaling.amazonaws.com') + 'autoscaling.amazonaws.com') DefaultRegionName = boto.config.get('Boto', 'autoscale_region_name', 'us-east-1') def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, @@ -122,20 +85,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 +118,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,12 +137,13 @@ 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) + params['UserData'] = launch_config.user_data if launch_config.kernel_id: params['KernelId'] = launch_config.kernel_id if launch_config.ramdisk_id: @@ -167,40 +151,37 @@ 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): - # """ - # - # """ - # 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, **kwargs): + Request) + + 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. """ - Get all autoscaling groups. + 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. :type names: list :param names: List of group names which should be searched for. @@ -212,10 +193,10 @@ class AutoScaleConnection(AWSQueryConnection): :returns: List of :class:`boto.ec2.autoscale.group.AutoScalingGroup` instances. """ params = {} - max_records = kwargs.get('max_records', None) - names = kwargs.get('names', None) - if max_records is not None: + 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, @@ -223,7 +204,11 @@ class AutoScaleConnection(AWSQueryConnection): def get_all_launch_configurations(self, **kwargs): """ - Get launch configurations. + 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. :type names: list :param names: List of configuration names which should be searched for. @@ -244,9 +229,7 @@ class AutoScaleConnection(AWSQueryConnection): 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. @@ -260,15 +243,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 = { @@ -278,6 +281,143 @@ 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 6f7a86e4..a27ec65d 100644 --- a/boto/ec2/autoscale/group.py +++ b/boto/ec2/autoscale/group.py @@ -20,39 +20,58 @@ # IN THE SOFTWARE. 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): + load_balancers=None, default_cooldown=None, + desired_capacity=None, + min_size=None, max_size=None): """ Creates a new AutoScalingGroup with the specified name. @@ -64,18 +83,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,41 +98,52 @@ 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. - :rtype: tuple - :return: Updated healthcheck for the instances. + :type desired_capacity: int + :param desired_capacity: The desired capacity for the group. + + :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 - self.health_check_period = health_check_period - self.suspended = suspended - self.placement_group = placement_group - 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 +154,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 +211,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) + |