1# Copyright (c) 2009-2011 Reza Lotun http://reza.lotun.name/
2# Copyright (c) 2011 Jann Kleen
3# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
4# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.  All Rights Reserved
5#
6# Permission is hereby granted, free of charge, to any person obtaining a
7# copy of this software and associated documentation files (the
8# "Software"), to deal in the Software without restriction, including
9# without limitation the rights to use, copy, modify, merge, publish, dis-
10# tribute, sublicense, and/or sell copies of the Software, and to permit
11# persons to whom the Software is furnished to do so, subject to the fol-
12# lowing conditions:
13#
14# The above copyright notice and this permission notice shall be included
15# in all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
19# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
20# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23# IN THE SOFTWARE.
24
25"""
26This module provides an interface to the Elastic Compute Cloud (EC2)
27Auto Scaling service.
28"""
29
30import base64
31
32import boto
33from boto.connection import AWSQueryConnection
34from boto.regioninfo import RegionInfo, get_regions, load_regions
35from boto.ec2.autoscale.request import Request
36from boto.ec2.autoscale.launchconfig import LaunchConfiguration
37from boto.ec2.autoscale.group import AutoScalingGroup
38from boto.ec2.autoscale.group import ProcessType
39from boto.ec2.autoscale.activity import Activity
40from boto.ec2.autoscale.policy import AdjustmentType
41from boto.ec2.autoscale.policy import MetricCollectionTypes
42from boto.ec2.autoscale.policy import ScalingPolicy
43from boto.ec2.autoscale.policy import TerminationPolicies
44from boto.ec2.autoscale.instance import Instance
45from boto.ec2.autoscale.scheduled import ScheduledUpdateGroupAction
46from boto.ec2.autoscale.tag import Tag
47from boto.ec2.autoscale.limits import AccountLimits
48from boto.compat import six
49
50RegionData = load_regions().get('autoscaling', {})
51
52
53def regions():
54    """
55    Get all available regions for the Auto Scaling service.
56
57    :rtype: list
58    :return: A list of :class:`boto.RegionInfo` instances
59    """
60    return get_regions('autoscaling', connection_cls=AutoScaleConnection)
61
62
63def connect_to_region(region_name, **kw_params):
64    """
65    Given a valid region name, return a
66    :class:`boto.ec2.autoscale.AutoScaleConnection`.
67
68    :param str region_name: The name of the region to connect to.
69
70    :rtype: :class:`boto.ec2.AutoScaleConnection` or ``None``
71    :return: A connection to the given region, or None if an invalid region
72        name is given
73    """
74    for region in regions():
75        if region.name == region_name:
76            return region.connect(**kw_params)
77    return None
78
79
80class AutoScaleConnection(AWSQueryConnection):
81    APIVersion = boto.config.get('Boto', 'autoscale_version', '2011-01-01')
82    DefaultRegionEndpoint = boto.config.get('Boto', 'autoscale_endpoint',
83                                            'autoscaling.us-east-1.amazonaws.com')
84    DefaultRegionName = boto.config.get('Boto', 'autoscale_region_name',
85                                        'us-east-1')
86
87    def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
88                 is_secure=True, port=None, proxy=None, proxy_port=None,
89                 proxy_user=None, proxy_pass=None, debug=0,
90                 https_connection_factory=None, region=None, path='/',
91                 security_token=None, validate_certs=True, profile_name=None,
92                 use_block_device_types=False):
93        """
94        Init method to create a new connection to the AutoScaling service.
95
96        B{Note:} The host argument is overridden by the host specified in the
97                 boto configuration file.
98
99
100        """
101        if not region:
102            region = RegionInfo(self, self.DefaultRegionName,
103                                self.DefaultRegionEndpoint,
104                                AutoScaleConnection)
105        self.region = region
106        self.use_block_device_types = use_block_device_types
107        super(AutoScaleConnection, self).__init__(aws_access_key_id,
108                                                  aws_secret_access_key,
109                                                  is_secure, port, proxy, proxy_port,
110                                                  proxy_user, proxy_pass,
111                                                  self.region.endpoint, debug,
112                                                  https_connection_factory, path=path,
113                                                  security_token=security_token,
114                                                  validate_certs=validate_certs,
115                                                  profile_name=profile_name)
116
117    def _required_auth_capability(self):
118        return ['hmac-v4']
119
120    def build_list_params(self, params, items, label):
121        """
122        Items is a list of dictionaries or strings::
123
124            [
125                {
126                    'Protocol' : 'HTTP',
127                    'LoadBalancerPort' : '80',
128                    'InstancePort' : '80'
129                },
130                ..
131            ] etc.
132
133        or::
134
135            ['us-east-1b',...]
136        """
137        # different from EC2 list params
138        for i in range(1, len(items) + 1):
139            if isinstance(items[i - 1], dict):
140                for k, v in six.iteritems(items[i - 1]):
141                    if isinstance(v, dict):
142                        for kk, vv in six.iteritems(v):
143                            params['%s.member.%d.%s.%s' % (label, i, k, kk)] = vv
144                    else:
145                        params['%s.member.%d.%s' % (label, i, k)] = v
146            elif isinstance(items[i - 1], six.string_types):
147                params['%s.member.%d' % (label, i)] = items[i - 1]
148
149    def _update_group(self, op, as_group):
150        params = {'AutoScalingGroupName': as_group.name,
151                  'LaunchConfigurationName': as_group.launch_config_name,
152                  'MinSize': as_group.min_size,
153                  'MaxSize': as_group.max_size}
154        # get availability zone information (required param)
155        zones = as_group.availability_zones
156        self.build_list_params(params, zones, 'AvailabilityZones')
157        if as_group.desired_capacity is not None:
158            params['DesiredCapacity'] = as_group.desired_capacity
159        if as_group.vpc_zone_identifier:
160            params['VPCZoneIdentifier'] = as_group.vpc_zone_identifier
161        if as_group.health_check_period:
162            params['HealthCheckGracePeriod'] = as_group.health_check_period
163        if as_group.health_check_type:
164            params['HealthCheckType'] = as_group.health_check_type
165        if as_group.default_cooldown:
166            params['DefaultCooldown'] = as_group.default_cooldown
167        if as_group.placement_group:
168            params['PlacementGroup'] = as_group.placement_group
169        if as_group.instance_id:
170            params['InstanceId'] = as_group.instance_id
171        if as_group.termination_policies:
172            self.build_list_params(params, as_group.termination_policies,
173                                   'TerminationPolicies')
174        if op.startswith('Create'):
175            # you can only associate load balancers with an autoscale
176            # group at creation time
177            if as_group.load_balancers:
178                self.build_list_params(params, as_group.load_balancers,
179                                       'LoadBalancerNames')
180            if as_group.tags:
181                for i, tag in enumerate(as_group.tags):
182                    tag.build_params(params, i + 1)
183        return self.get_object(op, params, Request)
184
185    def attach_instances(self, name, instance_ids):
186        """
187        Attach instances to an autoscaling group.
188        """
189        params = {
190            'AutoScalingGroupName': name,
191        }
192        self.build_list_params(params, instance_ids, 'InstanceIds')
193        return self.get_status('AttachInstances', params)
194
195    def detach_instances(self, name, instance_ids, decrement_capacity=True):
196        """
197        Detach instances from an Auto Scaling group.
198
199        :type name: str
200        :param name: The name of the Auto Scaling group from which to detach instances.
201
202        :type instance_ids: list
203        :param instance_ids: Instance ids to be detached from the Auto Scaling group.
204
205        :type decrement_capacity: bool
206        :param decrement_capacity: Whether to decrement the size of the
207            Auto Scaling group or not.
208        """
209
210        params = {'AutoScalingGroupName': name}
211        params['ShouldDecrementDesiredCapacity'] = 'true' if decrement_capacity else 'false'
212
213        self.build_list_params(params, instance_ids, 'InstanceIds')
214        return self.get_status('DetachInstances', params)
215
216    def create_auto_scaling_group(self, as_group):
217        """
218        Create auto scaling group.
219        """
220        return self._update_group('CreateAutoScalingGroup', as_group)
221
222    def delete_auto_scaling_group(self, name, force_delete=False):
223        """
224        Deletes the specified auto scaling group if the group has no instances
225        and no scaling activities in progress.
226        """
227        if(force_delete):
228            params = {'AutoScalingGroupName': name, 'ForceDelete': 'true'}
229        else:
230            params = {'AutoScalingGroupName': name}
231        return self.get_object('DeleteAutoScalingGroup', params, Request)
232
233    def create_launch_configuration(self, launch_config):
234        """
235        Creates a new Launch Configuration.
236
237        :type launch_config: :class:`boto.ec2.autoscale.launchconfig.LaunchConfiguration`
238        :param launch_config: LaunchConfiguration object.
239        """
240        params = {'ImageId': launch_config.image_id,
241                  'LaunchConfigurationName': launch_config.name,
242                  'InstanceType': launch_config.instance_type}
243        if launch_config.key_name:
244            params['KeyName'] = launch_config.key_name
245        if launch_config.user_data:
246            user_data = launch_config.user_data
247            if isinstance(user_data, six.text_type):
248                user_data = user_data.encode('utf-8')
249            params['UserData'] = base64.b64encode(user_data).decode('utf-8')
250        if launch_config.kernel_id:
251            params['KernelId'] = launch_config.kernel_id
252        if launch_config.ramdisk_id:
253            params['RamdiskId'] = launch_config.ramdisk_id
254        if launch_config.block_device_mappings:
255            [x.autoscale_build_list_params(params) for x in launch_config.block_device_mappings]
256        if launch_config.security_groups:
257            self.build_list_params(params, launch_config.security_groups,
258                                   'SecurityGroups')
259        if launch_config.instance_monitoring:
260            params['InstanceMonitoring.Enabled'] = 'true'
261        else:
262            params['InstanceMonitoring.Enabled'] = 'false'
263        if launch_config.spot_price is not None:
264            params['SpotPrice'] = str(launch_config.spot_price)
265        if launch_config.instance_profile_name is not None:
266            params['IamInstanceProfile'] = launch_config.instance_profile_name
267        if launch_config.ebs_optimized:
268            params['EbsOptimized'] = 'true'
269        else:
270            params['EbsOptimized'] = 'false'
271        if launch_config.associate_public_ip_address is True:
272            params['AssociatePublicIpAddress'] = 'true'
273        elif launch_config.associate_public_ip_address is False:
274            params['AssociatePublicIpAddress'] = 'false'
275        if launch_config.volume_type:
276            params['VolumeType'] = launch_config.volume_type
277        if launch_config.delete_on_termination:
278            params['DeleteOnTermination'] = 'true'
279        else:
280            params['DeleteOnTermination'] = 'false'
281        if launch_config.iops:
282            params['Iops'] = launch_config.iops
283        if launch_config.classic_link_vpc_id:
284            params['ClassicLinkVPCId'] = launch_config.classic_link_vpc_id
285        if launch_config.classic_link_vpc_security_groups:
286            self.build_list_params(
287                params,
288                launch_config.classic_link_vpc_security_groups,
289                'ClassicLinkVPCSecurityGroups'
290            )
291        return self.get_object('CreateLaunchConfiguration', params,
292                               Request, verb='POST')
293
294    def get_account_limits(self):
295        """
296        Returns the limits for the Auto Scaling resources currently granted for
297        your AWS account.
298        """
299        params = {}
300        return self.get_object('DescribeAccountLimits', params, AccountLimits)
301
302    def create_scaling_policy(self, scaling_policy):
303        """
304        Creates a new Scaling Policy.
305
306        :type scaling_policy: :class:`boto.ec2.autoscale.policy.ScalingPolicy`
307        :param scaling_policy: ScalingPolicy object.
308        """
309        params = {'AdjustmentType': scaling_policy.adjustment_type,
310                  'AutoScalingGroupName': scaling_policy.as_name,
311                  'PolicyName': scaling_policy.name,
312                  'ScalingAdjustment': scaling_policy.scaling_adjustment}
313
314        if scaling_policy.adjustment_type == "PercentChangeInCapacity" and \
315           scaling_policy.min_adjustment_step is not None:
316            params['MinAdjustmentStep'] = scaling_policy.min_adjustment_step
317
318        if scaling_policy.cooldown is not None:
319            params['Cooldown'] = scaling_policy.cooldown
320
321        return self.get_object('PutScalingPolicy', params, Request)
322
323    def delete_launch_configuration(self, launch_config_name):
324        """
325        Deletes the specified LaunchConfiguration.
326
327        The specified launch configuration must not be attached to an Auto
328        Scaling group. Once this call completes, the launch configuration is no
329        longer available for use.
330        """
331        params = {'LaunchConfigurationName': launch_config_name}
332        return self.get_object('DeleteLaunchConfiguration', params, Request)
333
334    def get_all_groups(self, names=None, max_records=None, next_token=None):
335        """
336        Returns a full description of each Auto Scaling group in the given
337        list. This includes all Amazon EC2 instances that are members of the
338        group. If a list of names is not provided, the service returns the full
339        details of all Auto Scaling groups.
340
341        This action supports pagination by returning a token if there are more
342        pages to retrieve. To get the next page, call this action again with
343        the returned token as the NextToken parameter.
344
345        :type names: list
346        :param names: List of group names which should be searched for.
347
348        :type max_records: int
349        :param max_records: Maximum amount of groups to return.
350
351        :rtype: list
352        :returns: List of :class:`boto.ec2.autoscale.group.AutoScalingGroup`
353            instances.
354        """
355        params = {}
356        if max_records:
357            params['MaxRecords'] = max_records
358        if next_token:
359            params['NextToken'] = next_token
360        if names:
361            self.build_list_params(params, names, 'AutoScalingGroupNames')
362        return self.get_list('DescribeAutoScalingGroups', params,
363                             [('member', AutoScalingGroup)])
364
365    def get_all_launch_configurations(self, **kwargs):
366        """
367        Returns a full description of the launch configurations given the
368        specified names.
369
370        If no names are specified, then the full details of all launch
371        configurations are returned.
372
373        :type names: list
374        :param names: List of configuration names which should be searched for.
375
376        :type max_records: int
377        :param max_records: Maximum amount of configurations to return.
378
379        :type next_token: str
380        :param next_token: If you have more results than can be returned
381            at once, pass in this  parameter to page through all results.
382
383        :rtype: list
384        :returns: List of
385            :class:`boto.ec2.autoscale.launchconfig.LaunchConfiguration`
386            instances.
387        """
388        params = {}
389        max_records = kwargs.get('max_records', None)
390        names = kwargs.get('names', None)
391        if max_records is not None:
392            params['MaxRecords'] = max_records
393        if names:
394            self.build_list_params(params, names, 'LaunchConfigurationNames')
395        next_token = kwargs.get('next_token')
396        if next_token:
397            params['NextToken'] = next_token
398        return self.get_list('DescribeLaunchConfigurations', params,
399                             [('member', LaunchConfiguration)])
400
401    def get_all_activities(self, autoscale_group, activity_ids=None,
402                           max_records=None, next_token=None):
403        """
404        Get all activities for the given autoscaling group.
405
406        This action supports pagination by returning a token if there are more
407        pages to retrieve. To get the next page, call this action again with
408        the returned token as the NextToken parameter
409
410        :type autoscale_group: str or
411            :class:`boto.ec2.autoscale.group.AutoScalingGroup` object
412        :param autoscale_group: The auto scaling group to get activities on.
413
414        :type max_records: int
415        :param max_records: Maximum amount of activities to return.
416
417        :rtype: list
418        :returns: List of
419            :class:`boto.ec2.autoscale.activity.Activity` instances.
420        """
421        name = autoscale_group
422        if isinstance(autoscale_group, AutoScalingGroup):
423            name = autoscale_group.name
424        params = {'AutoScalingGroupName': name}
425        if max_records:
426            params['MaxRecords'] = max_records
427        if next_token:
428            params['NextToken'] = next_token
429        if activity_ids:
430            self.build_list_params(params, activity_ids, 'ActivityIds')
431        return self.get_list('DescribeScalingActivities',
432                             params, [('member', Activity)])
433
434    def get_termination_policies(self):
435        """Gets all valid termination policies.
436
437        These values can then be used as the termination_policies arg
438        when creating and updating autoscale groups.
439        """
440        return self.get_object('DescribeTerminationPolicyTypes',
441                               {}, TerminationPolicies)
442
443    def delete_scheduled_action(self, scheduled_action_name,
444                                autoscale_group=None):
445        """
446        Deletes a previously scheduled action.
447
448        :type scheduled_action_name: str
449        :param scheduled_action_name: The name of the action you want
450            to delete.
451
452        :type autoscale_group: str
453        :param autoscale_group: The name of the autoscale group.
454        """
455        params = {'ScheduledActionName': scheduled_action_name}
456        if autoscale_group:
457            params['AutoScalingGroupName'] = autoscale_group
458        return self.get_status('DeleteScheduledAction', params)
459
460    def terminate_instance(self, instance_id, decrement_capacity=True):
461        """
462        Terminates the specified instance. The desired group size can
463        also be adjusted, if desired.
464
465        :type instance_id: str
466        :param instance_id: The ID of the instance to be terminated.
467
468        :type decrement_capability: bool
469        :param decrement_capacity: Whether to decrement the size of the
470            autoscaling group or not.
471        """
472        params = {'InstanceId': instance_id}
473        if decrement_capacity:
474            params['ShouldDecrementDesiredCapacity'] = 'true'
475        else:
476            params['ShouldDecrementDesiredCapacity'] = 'false'
477        return self.get_object('TerminateInstanceInAutoScalingGroup', params,
478                               Activity)
479
480    def delete_policy(self, policy_name, autoscale_group=None):
481        """
482        Delete a policy.
483
484        :type policy_name: str
485        :param policy_name: The name or ARN of the policy to delete.
486
487        :type autoscale_group: str
488        :param autoscale_group: The name of the autoscale group.
489        """
490        params = {'PolicyName': policy_name}
491        if autoscale_group:
492            params['AutoScalingGroupName'] = autoscale_group
493        return self.get_status('DeletePolicy', params)
494
495    def get_all_adjustment_types(self):
496        return self.get_list('DescribeAdjustmentTypes', {},
497                             [('member', AdjustmentType)])
498
499    def get_all_autoscaling_instances(self, instance_ids=None,
500                                      max_records=None, next_token=None):
501        """
502        Returns a description of each Auto Scaling instance in the instance_ids
503        list. If a list is not provided, the service returns the full details
504        of all instances up to a maximum of fifty.
505
506        This action supports pagination by returning a token if there are more
507        pages to retrieve. To get the next page, call this action again with
508        the returned token as the NextToken parameter.
509
510        :type instance_ids: list
511        :param instance_ids: List of Autoscaling Instance IDs which should be
512            searched for.
513
514        :type max_records: int
515        :param max_records: Maximum number of results to return.
516
517        :rtype: list
518        :returns: List of
519            :class:`boto.ec2.autoscale.instance.Instance` objects.
520        """
521        params = {}
522        if instance_ids:
523            self.build_list_params(params, instance_ids, 'InstanceIds')
524        if max_records:
525            params['MaxRecords'] = max_records
526        if next_token:
527            params['NextToken'] = next_token
528        return self.get_list('DescribeAutoScalingInstances',
529                             params, [('member', Instance)])
530
531    def get_all_metric_collection_types(self):
532        """
533        Returns a list of metrics and a corresponding list of granularities
534        for each metric.
535        """
536        return self.get_object('DescribeMetricCollectionTypes',
537                               {}, MetricCollectionTypes)
538
539    def get_all_policies(self, as_group=None, policy_names=None,
540                         max_records=None, next_token=None):
541        """
542        Returns descriptions of what each policy does. This action supports
543        pagination. If the response includes a token, there are more records
544        available. To get the additional records, repeat the request with the
545        response token as the NextToken parameter.
546
547        If no group name or list of policy names are provided, all
548        available policies are returned.
549
550        :type as_group: str
551        :param as_group: The name of the
552            :class:`boto.ec2.autoscale.group.AutoScalingGroup` to filter for.
553
554        :type policy_names: list
555        :param policy_names: List of policy names which should be searched for.
556
557        :type max_records: int
558        :param max_records: Maximum amount of groups to return.
559
560        :type next_token: str
561        :param next_token: If you have more results than can be returned
562            at once, pass in this  parameter to page through all results.
563        """
564        params = {}
565        if as_group:
566            params['AutoScalingGroupName'] = as_group
567        if policy_names:
568            self.build_list_params(params, policy_names, 'PolicyNames')
569        if max_records:
570            params['MaxRecords'] = max_records
571        if next_token:
572            params['NextToken'] = next_token
573        return self.get_list('DescribePolicies', params,
574                             [('member', ScalingPolicy)])
575
576    def get_all_scaling_process_types(self):
577        """
578        Returns scaling process types for use in the ResumeProcesses and
579        SuspendProcesses actions.
580        """
581        return self.get_list('DescribeScalingProcessTypes', {},
582                             [('member', ProcessType)])
583
584    def suspend_processes(self, as_group, scaling_processes=None):
585        """
586        Suspends Auto Scaling processes for an Auto Scaling group.
587
588        :type as_group: string
589        :param as_group: The auto scaling group to suspend processes on.
590
591        :type scaling_processes: list
592        :param scaling_processes: Processes you want to suspend. If omitted,
593            all processes will be suspended.
594        """
595        params = {'AutoScalingGroupName': as_group}
596        if scaling_processes:
597            self.build_list_params(params, scaling_processes,
598                                   'ScalingProcesses')
599        return self.get_status('SuspendProcesses', params)
600
601    def resume_processes(self, as_group, scaling_processes=None):
602        """
603        Resumes Auto Scaling processes for an Auto Scaling group.
604
605        :type as_group: string
606        :param as_group: The auto scaling group to resume processes on.
607
608        :type scaling_processes: list
609        :param scaling_processes: Processes you want to resume. If omitted, all
610            processes will be resumed.
611        """
612        params = {'AutoScalingGroupName': as_group}
613
614        if scaling_processes:
615            self.build_list_params(params, scaling_processes,
616                                   'ScalingProcesses')
617        return self.get_status('ResumeProcesses', params)
618
619    def create_scheduled_group_action(self, as_group, name, time=None,
620                                      desired_capacity=None,
621                                      min_size=None, max_size=None,
622                                      start_time=None, end_time=None,
623                                      recurrence=None):
624        """
625        Creates a scheduled scaling action for a Auto Scaling group. If you
626        leave a parameter unspecified, the corresponding value remains
627        unchanged in the affected Auto Scaling group.
628
629        :type as_group: string
630        :param as_group: The auto scaling group to get activities on.
631
632        :type name: string
633        :param name: Scheduled action name.
634
635        :type time: datetime.datetime
636        :param time: The time for this action to start. (Depracated)
637
638        :type desired_capacity: int
639        :param desired_capacity: The number of EC2 instances that should
640            be running in this group.
641
642        :type min_size: int
643        :param min_size: The minimum size for the new auto scaling group.
644
645        :type max_size: int
646        :param max_size: The minimum size for the new auto scaling group.
647
648        :type start_time: datetime.datetime
649        :param start_time: The time for this action to start. When StartTime and EndTime are specified with Recurrence, they form the boundaries of when the recurring action will start and stop.
650
651        :type end_time: datetime.datetime
652        :param end_time: The time for this action to end. When StartTime and EndTime are specified with Recurrence, they form the boundaries of when the recurring action will start and stop.
653
654        :type recurrence: string
655        :param recurrence: The time when recurring future actions will start. Start time is specified by the user following the Unix cron syntax format. EXAMPLE: '0 10 * * *'
656        """
657        params = {'AutoScalingGroupName': as_group,
658                  'ScheduledActionName': name}
659        if start_time is not None:
660            params['StartTime'] = start_time.isoformat()
661        if end_time is not None:
662            params['EndTime'] = end_time.isoformat()
663        if recurrence is not None:
664            params['Recurrence'] = recurrence
665        if time:
666            params['Time'] = time.isoformat()
667        if desired_capacity is not None:
668            params['DesiredCapacity'] = desired_capacity
669        if min_size is not None:
670            params['MinSize'] = min_size
671        if max_size is not None:
672            params['MaxSize'] = max_size
673        return self.get_status('PutScheduledUpdateGroupAction', params)
674
675    def get_all_scheduled_actions(self, as_group=None, start_time=None,
676                                  end_time=None, scheduled_actions=None,
677                                  max_records=None, next_token=None):
678        params = {}
679        if as_group:
680            params['AutoScalingGroupName'] = as_group
681        if scheduled_actions:
682            self.build_list_params(params, scheduled_actions,
683                                   'ScheduledActionNames')
684        if max_records:
685            params['MaxRecords'] = max_records
686        if next_token:
687            params['NextToken'] = next_token
688        return self.get_list('DescribeScheduledActions', params,
689                             [('member', ScheduledUpdateGroupAction)])
690
691    def disable_metrics_collection(self, as_group, metrics=None):
692        """
693        Disables monitoring of group metrics for the Auto Scaling group
694        specified in AutoScalingGroupName. You can specify the list of affected
695        metrics with the Metrics parameter.
696        """
697        params = {'AutoScalingGroupName': as_group}
698
699        if metrics:
700            self.build_list_params(params, metrics, 'Metrics')
701        return self.get_status('DisableMetricsCollection', params)
702
703    def enable_metrics_collection(self, as_group, granularity, metrics=None):
704        """
705        Enables monitoring of group metrics for the Auto Scaling group
706        specified in AutoScalingGroupName. You can specify the list of enabled
707        metrics with the Metrics parameter.
708
709        Auto scaling metrics collection can be turned on only if the
710        InstanceMonitoring.Enabled flag, in the Auto Scaling group's launch
711        configuration, is set to true.
712
713        :type autoscale_group: string
714        :param autoscale_group: The auto scaling group to get activities on.
715
716        :type granularity: string
717        :param granularity: The granularity to associate with the metrics to
718            collect. Currently, the only legal granularity is "1Minute".
719
720        :type metrics: string list
721        :param metrics: The list of metrics to collect. If no metrics are
722                        specified, all metrics are enabled.
723        """
724        params = {'AutoScalingGroupName': as_group,
725                  'Granularity': granularity}
726        if metrics:
727            self.build_list_params(params, metrics, 'Metrics')
728        return self.get_status('EnableMetricsCollection', params)
729
730    def execute_policy(self, policy_name, as_group=None, honor_cooldown=None):
731        params = {'PolicyName': policy_name}
732        if as_group:
733            params['AutoScalingGroupName'] = as_group
734        if honor_cooldown:
735            params['HonorCooldown'] = honor_cooldown
736        return self.get_status('ExecutePolicy', params)
737
738    def put_notification_configuration(self, autoscale_group, topic, notification_types):
739        """
740        Configures an Auto Scaling group to send notifications when
741        specified events take place.
742
743        :type autoscale_group: str or
744            :class:`boto.ec2.autoscale.group.AutoScalingGroup` object
745        :param autoscale_group: The Auto Scaling group to put notification
746            configuration on.
747
748        :type topic: str
749        :param topic: The Amazon Resource Name (ARN) of the Amazon Simple
750            Notification Service (SNS) topic.
751
752        :type notification_types: list
753        :param notification_types: The type of events that will trigger
754            the notification. Valid types are:
755            'autoscaling:EC2_INSTANCE_LAUNCH',
756            'autoscaling:EC2_INSTANCE_LAUNCH_ERROR',
757            'autoscaling:EC2_INSTANCE_TERMINATE',
758            'autoscaling:EC2_INSTANCE_TERMINATE_ERROR',
759            'autoscaling:TEST_NOTIFICATION'
760        """
761
762        name = autoscale_group
763        if isinstance(autoscale_group, AutoScalingGroup):
764            name = autoscale_group.name
765
766        params = {'AutoScalingGroupName': name,
767                  'TopicARN': topic}
768        self.build_list_params(params, notification_types, 'NotificationTypes')
769        return self.get_status('PutNotificationConfiguration', params)
770
771    def delete_notification_configuration(self, autoscale_group, topic):
772        """
773        Deletes notifications created by put_notification_configuration.
774
775        :type autoscale_group: str or
776            :class:`boto.ec2.autoscale.group.AutoScalingGroup` object
777        :param autoscale_group: The Auto Scaling group to put notification
778            configuration on.
779
780        :type topic: str
781        :param topic: The Amazon Resource Name (ARN) of the Amazon Simple
782            Notification Service (SNS) topic.
783        """
784
785        name = autoscale_group
786        if isinstance(autoscale_group, AutoScalingGroup):
787            name = autoscale_group.name
788
789        params = {'AutoScalingGroupName': name,
790                  'TopicARN': topic}
791
792        return self.get_status('DeleteNotificationConfiguration', params)
793
794    def set_instance_health(self, instance_id, health_status,
795                            should_respect_grace_period=True):
796        """
797        Explicitly set the health status of an instance.
798
799        :type instance_id: str
800        :param instance_id: The identifier of the EC2 instance.
801
802        :type health_status: str
803        :param health_status: The health status of the instance.
804            "Healthy" means that the instance is healthy and should remain
805            in service. "Unhealthy" means that the instance is unhealthy.
806            Auto Scaling should terminate and replace it.
807
808        :type should_respect_grace_period: bool
809        :param should_respect_grace_period: If True, this call should
810            respect the grace period associated with the group.
811        """
812        params = {'InstanceId': instance_id,
813                  'HealthStatus': health_status}
814        if should_respect_grace_period:
815            params['ShouldRespectGracePeriod'] = 'true'
816        else:
817            params['ShouldRespectGracePeriod'] = 'false'
818        return self.get_status('SetInstanceHealth', params)
819
820    def set_desired_capacity(self, group_name, desired_capacity, honor_cooldown=False):
821        """
822        Adjusts the desired size of the AutoScalingGroup by initiating scaling
823        activities. When reducing the size of the group, it is not possible to define
824        which Amazon EC2 instances will be terminated. This applies to any Auto Scaling
825        decisions that might result in terminating instances.
826
827        :type group_name: string
828        :param group_name: name of the auto scaling group
829
830        :type desired_capacity: integer
831        :param desired_capacity: new capacity setting for auto scaling group
832
833        :type honor_cooldown: boolean
834        :param honor_cooldown: by default, overrides any cooldown period
835        """
836        params = {'AutoScalingGroupName': group_name,
837                  'DesiredCapacity': desired_capacity}
838        if honor_cooldown:
839            params['HonorCooldown'] = 'true'
840
841        return self.get_status('SetDesiredCapacity', params)
842
843    # Tag methods
844
845    def get_all_tags(self, filters=None, max_records=None, next_token=None):
846        """
847        Lists the Auto Scaling group tags.
848
849        This action supports pagination by returning a token if there
850        are more pages to retrieve. To get the next page, call this
851        action again with the returned token as the NextToken
852        parameter.
853
854        :type filters: dict
855        :param filters: The value of the filter type used to identify
856            the tags to be returned.  NOT IMPLEMENTED YET.
857
858        :type max_records: int
859        :param max_records: Maximum number of tags to return.
860
861        :rtype: list
862        :returns: List of :class:`boto.ec2.autoscale.tag.Tag`
863            instances.
864        """
865        params = {}
866        if max_records:
867            params['MaxRecords'] = max_records
868        if next_token:
869            params['NextToken'] = next_token
870        return self.get_list('DescribeTags', params,
871                             [('member', Tag)])
872
873    def create_or_update_tags(self, tags):
874        """
875        Creates new tags or updates existing tags for an Auto Scaling group.
876
877        :type tags: List of :class:`boto.ec2.autoscale.tag.Tag`
878        :param tags: The new or updated tags.
879        """
880        params = {}
881        for i, tag in enumerate(tags):
882            tag.build_params(params, i + 1)
883        return self.get_status('CreateOrUpdateTags', params, verb='POST')
884
885    def delete_tags(self, tags):
886        """
887        Deletes existing tags for an Auto Scaling group.
888
889        :type tags: List of :class:`boto.ec2.autoscale.tag.Tag`
890        :param tags: The new or updated tags.
891        """
892        params = {}
893        for i, tag in enumerate(tags):
894            tag.build_params(params, i + 1)
895        return self.get_status('DeleteTags', params, verb='POST')
896