Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Unified Diff: boto/ec2/connection.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « boto/ec2/cloudwatch/metric.py ('k') | boto/ec2/ec2object.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: boto/ec2/connection.py
diff --git a/boto/ec2/connection.py b/boto/ec2/connection.py
index 89d1d4ee99b29cebc06fc74a496cd35612957f25..1e492594d6dd61118c83c27e25d3298a2d22089c 100644
--- a/boto/ec2/connection.py
+++ b/boto/ec2/connection.py
@@ -32,7 +32,8 @@ import boto
from boto.connection import AWSQueryConnection
from boto.resultset import ResultSet
from boto.ec2.image import Image, ImageAttribute
-from boto.ec2.instance import Reservation, Instance, ConsoleOutput, InstanceAttribute
+from boto.ec2.instance import Reservation, Instance
+from boto.ec2.instance import ConsoleOutput, InstanceAttribute
from boto.ec2.keypair import KeyPair
from boto.ec2.address import Address
from boto.ec2.volume import Volume
@@ -42,7 +43,8 @@ from boto.ec2.zone import Zone
from boto.ec2.securitygroup import SecurityGroup
from boto.ec2.regioninfo import RegionInfo
from boto.ec2.instanceinfo import InstanceInfo
-from boto.ec2.reservedinstance import ReservedInstancesOffering, ReservedInstance
+from boto.ec2.reservedinstance import ReservedInstancesOffering
+from boto.ec2.reservedinstance import ReservedInstance
from boto.ec2.spotinstancerequest import SpotInstanceRequest
from boto.ec2.spotpricehistory import SpotPriceHistory
from boto.ec2.spotdatafeedsubscription import SpotDatafeedSubscription
@@ -55,16 +57,18 @@ from boto.exception import EC2ResponseError
class EC2Connection(AWSQueryConnection):
- APIVersion = boto.config.get('Boto', 'ec2_version', '2010-08-31')
+ APIVersion = boto.config.get('Boto', 'ec2_version', '2011-01-01')
DefaultRegionName = boto.config.get('Boto', 'ec2_region_name', 'us-east-1')
DefaultRegionEndpoint = boto.config.get('Boto', 'ec2_region_endpoint',
'ec2.amazonaws.com')
ResponseError = EC2ResponseError
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
- is_secure=True, host=None, port=None, proxy=None, proxy_port=None,
+ is_secure=True, host=None, port=None,
+ proxy=None, proxy_port=None,
proxy_user=None, proxy_pass=None, debug=0,
- https_connection_factory=None, region=None, path='/'):
+ https_connection_factory=None, region=None, path='/',
+ api_version=None, security_token=None):
"""
Init method to create a new connection to EC2.
@@ -80,7 +84,10 @@ class EC2Connection(AWSQueryConnection):
is_secure, port, proxy, proxy_port,
proxy_user, proxy_pass,
self.region.endpoint, debug,
- https_connection_factory, path)
+ https_connection_factory, path,
+ security_token)
+ if api_version:
+ self.APIVersion = api_version
def _required_auth_capability(self):
return ['ec2']
@@ -90,8 +97,9 @@ class EC2Connection(AWSQueryConnection):
Returns a dictionary containing the value of of all of the keyword
arguments passed when constructing this connection.
"""
- param_names = ['aws_access_key_id', 'aws_secret_access_key', 'is_secure',
- 'port', 'proxy', 'proxy_port', 'proxy_user', 'proxy_pass',
+ param_names = ['aws_access_key_id', 'aws_secret_access_key',
+ 'is_secure', 'port', 'proxy', 'proxy_port',
+ 'proxy_user', 'proxy_pass',
'debug', 'https_connection_factory']
params = {}
for name in param_names:
@@ -101,7 +109,9 @@ class EC2Connection(AWSQueryConnection):
def build_filter_params(self, params, filters):
i = 1
for name in filters:
- aws_name = name.replace('_', '-')
+ aws_name = name
+ if not aws_name.startswith('tag:'):
+ aws_name = name.replace('_', '-')
params['Filter.%d.Name' % i] = aws_name
value = filters[name]
if not isinstance(value, list):
@@ -151,7 +161,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, executable_by, 'ExecutableBy')
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeImages', params, [('item', Image)], verb='POST')
+ return self.get_list('DescribeImages', params,
+ [('item', Image)], verb='POST')
def get_all_kernels(self, kernel_ids=None, owners=None):
"""
@@ -174,7 +185,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, owners, 'Owner')
filter = {'image-type' : 'kernel'}
self.build_filter_params(params, filter)
- return self.get_list('DescribeImages', params, [('item', Image)], verb='POST')
+ return self.get_list('DescribeImages', params,
+ [('item', Image)], verb='POST')
def get_all_ramdisks(self, ramdisk_ids=None, owners=None):
"""
@@ -197,7 +209,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, owners, 'Owner')
filter = {'image-type' : 'ramdisk'}
self.build_filter_params(params, filter)
- return self.get_list('DescribeImages', params, [('item', Image)], verb='POST')
+ return self.get_list('DescribeImages', params,
+ [('item', Image)], verb='POST')
def get_image(self, image_id):
"""
@@ -227,7 +240,8 @@ class EC2Connection(AWSQueryConnection):
:param description: The description of the AMI.
:type image_location: string
- :param image_location: Full path to your AMI manifest in Amazon S3 storage.
+ :param image_location: Full path to your AMI manifest in
+ Amazon S3 storage.
Only used for S3-based AMI's.
:type architecture: string
@@ -235,7 +249,8 @@ class EC2Connection(AWSQueryConnection):
i386 | x86_64
:type kernel_id: string
- :param kernel_id: The ID of the kernel with which to launch the instances
+ :param kernel_id: The ID of the kernel with which to launch
+ the instances
:type root_device_name: string
:param root_device_name: The root device name (e.g. /dev/sdh)
@@ -269,23 +284,41 @@ class EC2Connection(AWSQueryConnection):
image_id = getattr(rs, 'imageId', None)
return image_id
- def deregister_image(self, image_id):
+ def deregister_image(self, image_id, delete_snapshot=False):
"""
Unregister an AMI.
:type image_id: string
:param image_id: the ID of the Image to unregister
+ :type delete_snapshot: bool
+ :param delete_snapshot: Set to True if we should delete the
+ snapshot associated with an EBS volume
+ mounted at /dev/sda1
+
:rtype: bool
:return: True if successful
"""
- return self.get_status('DeregisterImage', {'ImageId':image_id}, verb='POST')
+ snapshot_id = None
+ if delete_snapshot:
+ image = self.get_image(image_id)
+ for key in image.block_device_mapping:
+ if key == "/dev/sda1":
+ snapshot_id = image.block_device_mapping[key].snapshot_id
+ break
+
+ result = self.get_status('DeregisterImage',
+ {'ImageId':image_id}, verb='POST')
+ if result and snapshot_id:
+ return result and self.delete_snapshot(snapshot_id)
+ return result
- def create_image(self, instance_id, name, description=None, no_reboot=False):
+ def create_image(self, instance_id, name,
+ description=None, no_reboot=False):
"""
Will create an AMI from the instance in the running or stopped
state.
-
+
:type instance_id: string
:param instance_id: the ID of the instance to image.
@@ -302,7 +335,7 @@ class EC2Connection(AWSQueryConnection):
bundling. If this flag is True, the responsibility
of maintaining file system integrity is left to the
owner of the instance.
-
+
:rtype: string
:return: The new image id
"""
@@ -314,7 +347,7 @@ class EC2Connection(AWSQueryConnection):
params['NoReboot'] = 'true'
img = self.get_object('CreateImage', params, Image, verb='POST')
return img.id
-
+
# ImageAttribute methods
def get_image_attribute(self, image_id, attribute='launchPermission'):
@@ -337,7 +370,8 @@ class EC2Connection(AWSQueryConnection):
"""
params = {'ImageId' : image_id,
'Attribute' : attribute}
- return self.get_object('DescribeImageAttribute', params, ImageAttribute, verb='POST')
+ return self.get_object('DescribeImageAttribute', params,
+ ImageAttribute, verb='POST')
def modify_image_attribute(self, image_id, attribute='launchPermission',
operation='add', user_ids=None, groups=None,
@@ -420,6 +454,11 @@ class EC2Connection(AWSQueryConnection):
if instance_ids:
self.build_list_params(params, instance_ids, 'InstanceId')
if filters:
+ if 'group-id' in filters:
+ warnings.warn("The group-id filter now requires a security "
+ "group identifier (sg-*) instead of a group "
+ "name. To filter by group name use the "
+ "'group-name' filter instead.", UserWarning)
self.build_filter_params(params, filters)
return self.get_list('DescribeInstances', params,
[('item', Reservation)], verb='POST')
@@ -434,7 +473,8 @@ class EC2Connection(AWSQueryConnection):
disable_api_termination=False,
instance_initiated_shutdown_behavior=None,
private_ip_address=None,
- placement_group=None, client_token=None):
+ placement_group=None, client_token=None,
+ security_group_ids=None):
"""
Runs an image on EC2.
@@ -459,7 +499,7 @@ class EC2Connection(AWSQueryConnection):
:type instance_type: string
:param instance_type: The type of instance to run:
-
+
* m1.small
* m1.large
* m1.xlarge
@@ -507,13 +547,12 @@ class EC2Connection(AWSQueryConnection):
:type instance_initiated_shutdown_behavior: string
:param instance_initiated_shutdown_behavior: Specifies whether the
- instance's EBS volumes are
- stopped (i.e. detached) or
- terminated (i.e. deleted)
- when the instance is
- shutdown by the
- owner. Valid values are:
-
+ instance stops or
+ terminates on
+ instance-initiated
+ shutdown.
+ Valid values are:
+
* stop
* terminate
@@ -529,12 +568,24 @@ class EC2Connection(AWSQueryConnection):
:rtype: Reservation
:return: The :class:`boto.ec2.instance.Reservation` associated with
the request for machines
+
+ :type security_group_ids: list of strings
+ :param security_group_ids: The ID of the VPC security groups with
+ which to associate instances
"""
params = {'ImageId':image_id,
'MinCount':min_count,
'MaxCount': max_count}
if key_name:
params['KeyName'] = key_name
+ if security_group_ids:
+ l = []
+ for group in security_group_ids:
+ if isinstance(group, SecurityGroup):
+ l.append(group.name)
+ else:
+ l.append(group)
+ self.build_list_params(params, l, 'SecurityGroupId')
if security_groups:
l = []
for group in security_groups:
@@ -587,18 +638,19 @@ class EC2Connection(AWSQueryConnection):
params = {}
if instance_ids:
self.build_list_params(params, instance_ids, 'InstanceId')
- return self.get_list('TerminateInstances', params, [('item', Instance)], verb='POST')
+ return self.get_list('TerminateInstances', params,
+ [('item', Instance)], verb='POST')
def stop_instances(self, instance_ids=None, force=False):
"""
Stop the instances specified
-
+
:type instance_ids: list
:param instance_ids: A list of strings of the Instance IDs to stop
:type force: bool
:param force: Forces the instance to stop
-
+
:rtype: list
:return: A list of the instances stopped
"""
@@ -607,22 +659,24 @@ class EC2Connection(AWSQueryConnection):
params['Force'] = 'true'
if instance_ids:
self.build_list_params(params, instance_ids, 'InstanceId')
- return self.get_list('StopInstances', params, [('item', Instance)], verb='POST')
+ return self.get_list('StopInstances', params,
+ [('item', Instance)], verb='POST')
def start_instances(self, instance_ids=None):
"""
Start the instances specified
-
+
:type instance_ids: list
:param instance_ids: A list of strings of the Instance IDs to start
-
+
:rtype: list
:return: A list of the instances started
"""
params = {}
if instance_ids:
self.build_list_params(params, instance_ids, 'InstanceId')
- return self.get_list('StartInstances', params, [('item', Instance)], verb='POST')
+ return self.get_list('StartInstances', params,
+ [('item', Instance)], verb='POST')
def get_console_output(self, instance_id):
"""
@@ -636,7 +690,8 @@ class EC2Connection(AWSQueryConnection):
"""
params = {}
self.build_list_params(params, [instance_id], 'InstanceId')
- return self.get_object('GetConsoleOutput', params, ConsoleOutput, verb='POST')
+ return self.get_object('GetConsoleOutput', params,
+ ConsoleOutput, verb='POST')
def reboot_instances(self, instance_ids=None):
"""
@@ -653,7 +708,8 @@ class EC2Connection(AWSQueryConnection):
def confirm_product_instance(self, product_code, instance_id):
params = {'ProductCode' : product_code,
'InstanceId' : instance_id}
- rs = self.get_object('ConfirmProductInstance', params, ResultSet, verb='POST')
+ rs = self.get_object('ConfirmProductInstance', params,
+ ResultSet, verb='POST')
return (rs.status, rs.ownerId)
# InstanceAttribute methods
@@ -668,7 +724,7 @@ class EC2Connection(AWSQueryConnection):
:type attribute: string
:param attribute: The attribute you need information about
Valid choices are:
-
+
* instanceType|kernel|ramdisk|userData|
* disableApiTermination|
* instanceInitiatedShutdownBehavior|
@@ -693,7 +749,7 @@ class EC2Connection(AWSQueryConnection):
:type attribute: string
:param attribute: The attribute you wish to change.
-
+
* AttributeName - Expected value (default)
* instanceType - A valid instance type (m1.small)
* kernel - Kernel ID (None)
@@ -745,10 +801,10 @@ class EC2Connection(AWSQueryConnection):
filters=None):
"""
Retrieve all the spot instances requests associated with your account.
-
+
:type request_ids: list
:param request_ids: A list of strings of spot instance request IDs
-
+
:type filters: dict
:param filters: Optional filters that can be used to limit
the results returned. Filters are provided
@@ -767,30 +823,41 @@ class EC2Connection(AWSQueryConnection):
if request_ids:
self.build_list_params(params, request_ids, 'SpotInstanceRequestId')
if filters:
+ if 'launch.group-id' in filters:
+ warnings.warn("The 'launch.group-id' filter now requires a "
+ "security group id (sg-*) and no longer supports "
+ "filtering by group name. Please update your "
+ "filters accordingly.", UserWarning)
self.build_filter_params(params, filters)
return self.get_list('DescribeSpotInstanceRequests', params,
[('item', SpotInstanceRequest)], verb='POST')
def get_spot_price_history(self, start_time=None, end_time=None,
- instance_type=None, product_description=None):
+ instance_type=None, product_description=None,
+ availability_zone=None):
"""
Retrieve the recent history of spot instances pricing.
-
+
:type start_time: str
:param start_time: An indication of how far back to provide price
changes for. An ISO8601 DateTime string.
-
+
:type end_time: str
:param end_time: An indication of how far forward to provide price
changes for. An ISO8601 DateTime string.
-
+
:type instance_type: str
:param instance_type: Filter responses to a particular instance type.
-
+
:type product_description: str
- :param product_descripton: Filter responses to a particular platform.
- Valid values are currently: Linux
-
+ :param product_description: Filter responses to a particular platform.
+ Valid values are currently: "Linux/UNIX",
+ "SUSE Linux", and "Windows"
+
+ :type availability_zone: str
+ :param availability_zone: The availability zone for which prices
+ should be returned
+
:rtype: list
:return: A list tuples containing price and timestamp.
"""
@@ -803,6 +870,8 @@ class EC2Connection(AWSQueryConnection):
params['InstanceType'] = instance_type
if product_description:
params['ProductDescription'] = product_description
+ if availability_zone:
+ params['AvailabilityZone'] = availability_zone
return self.get_list('DescribeSpotPriceHistory', params,
[('item', SpotPriceHistory)], verb='POST')
@@ -820,13 +889,13 @@ class EC2Connection(AWSQueryConnection):
:type price: str
:param price: The maximum price of your bid
-
+
:type image_id: string
:param image_id: The ID of the image to run
:type count: int
:param count: The of instances to requested
-
+
:type type: str
:param type: Type of request. Can be 'one-time' or 'persistent'.
Default is one-time.
@@ -840,12 +909,12 @@ class EC2Connection(AWSQueryConnection):
:type launch_group: str
:param launch_group: If supplied, all requests will be fulfilled
as a group.
-
+
:type availability_zone_group: str
:param availability_zone_group: If supplied, all requests will be
fulfilled within a single
availability zone.
-
+
:type key_name: string
:param key_name: The name of the key pair with which to launch instances
@@ -858,7 +927,7 @@ class EC2Connection(AWSQueryConnection):
:type instance_type: string
:param instance_type: The type of instance to run:
-
+
* m1.small
* m1.large
* m1.xlarge
@@ -943,14 +1012,14 @@ class EC2Connection(AWSQueryConnection):
[('item', SpotInstanceRequest)],
verb='POST')
-
+
def cancel_spot_instance_requests(self, request_ids):
"""
Cancel the specified Spot Instance Requests.
-
+
:type request_ids: list
:param request_ids: A list of strings of the Request IDs to terminate
-
+
:rtype: list
:return: A list of the instances terminated
"""
@@ -964,7 +1033,7 @@ class EC2Connection(AWSQueryConnection):
"""
Return the current spot instance data feed subscription
associated with this account, if any.
-
+
:rtype: :class:`boto.ec2.spotdatafeedsubscription.SpotDatafeedSubscription`
:return: The datafeed subscription object or None
"""
@@ -984,7 +1053,7 @@ class EC2Connection(AWSQueryConnection):
:type prefix: str or unicode
:param prefix: An optional prefix that will be pre-pended to all
data files written to the bucket.
-
+
:rtype: :class:`boto.ec2.spotdatafeedsubscription.SpotDatafeedSubscription`
:return: The datafeed subscription object or None
"""
@@ -998,11 +1067,12 @@ class EC2Connection(AWSQueryConnection):
"""
Delete the current spot instance data feed subscription
associated with this account
-
+
:rtype: bool
:return: True if successful
"""
- return self.get_status('DeleteSpotDatafeedSubscription', None, verb='POST')
+ return self.get_status('DeleteSpotDatafeedSubscription',
+ None, verb='POST')
# Zone methods
@@ -1033,11 +1103,12 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, zones, 'ZoneName')
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeAvailabilityZones', params, [('item', Zone)], verb='POST')
+ return self.get_list('DescribeAvailabilityZones', params,
+ [('item', Zone)], verb='POST')
# Address methods
- def get_all_addresses(self, addresses=None, filters=None):
+ def get_all_addresses(self, addresses=None, filters=None, allocation_ids=None):
"""
Get all EIP's associated with the current credentials.
@@ -1056,65 +1127,106 @@ class EC2Connection(AWSQueryConnection):
being performed. Check the EC2 API guide
for details.
+ :type allocation_ids: list
+ :param allocation_ids: Optional list of allocation IDs. If this list is
+ present, only the Addresses associated with the given
+ allocation IDs will be returned.
+
:rtype: list of :class:`boto.ec2.address.Address`
:return: The requested Address objects
"""
params = {}
if addresses:
self.build_list_params(params, addresses, 'PublicIp')
+ if allocation_ids:
+ self.build_list_params(params, allocation_ids, 'AllocationId')
if filters:
self.build_filter_params(params, filters)
return self.get_list('DescribeAddresses', params, [('item', Address)], verb='POST')
- def allocate_address(self):
+ def allocate_address(self, domain=None):
"""
Allocate a new Elastic IP address and associate it with your account.
:rtype: :class:`boto.ec2.address.Address`
:return: The newly allocated Address
"""
- return self.get_object('AllocateAddress', {}, Address, verb='POST')
+ params = {}
- def associate_address(self, instance_id, public_ip):
+ if domain is not None:
+ params['Domain'] = domain
+
+ return self.get_object('AllocateAddress', params, Address, verb='POST')
+
+ def associate_address(self, instance_id, public_ip=None, allocation_id=None):
"""
Associate an Elastic IP address with a currently running instance.
+ This requires one of ``public_ip`` or ``allocation_id`` depending
+ on if you're associating a VPC address or a plain EC2 address.
:type instance_id: string
:param instance_id: The ID of the instance
:type public_ip: string
- :param public_ip: The public IP address
+ :param public_ip: The public IP address for EC2 based allocations.
+
+ :type allocation_id: string
+ :param allocation_id: The allocation ID for a VPC-based elastic IP.
:rtype: bool
:return: True if successful
"""
- params = {'InstanceId' : instance_id, 'PublicIp' : public_ip}
+ params = { 'InstanceId' : instance_id }
+
+ if public_ip is not None:
+ params['PublicIp'] = public_ip
+ elif allocation_id is not None:
+ params['AllocationId'] = allocation_id
+
return self.get_status('AssociateAddress', params, verb='POST')
- def disassociate_address(self, public_ip):
+ def disassociate_address(self, public_ip=None, association_id=None):
"""
Disassociate an Elastic IP address from a currently running instance.
:type public_ip: string
- :param public_ip: The public IP address
+ :param public_ip: The public IP address for EC2 elastic IPs.
+
+ :type association_id: string
+ :param association_id: The association ID for a VPC based elastic ip.
:rtype: bool
:return: True if successful
"""
- params = {'PublicIp' : public_ip}
+ params = {}
+
+ if public_ip is not None:
+ params['PublicIp'] = public_ip
+ elif association_id is not None:
+ params['AssociationId'] = association_id
+
return self.get_status('DisassociateAddress', params, verb='POST')
- def release_address(self, public_ip):
+ def release_address(self, public_ip=None, allocation_id=None):
"""
- Free up an Elastic IP address
+ Free up an Elastic IP address.
:type public_ip: string
- :param public_ip: The public IP address
+ :param public_ip: The public IP address for EC2 elastic IPs.
+
+ :type allocation_id: string
+ :param allocation_id: The ID for VPC elastic IPs.
:rtype: bool
:return: True if successful
"""
- params = {'PublicIp' : public_ip}
+ params = {}
+
+ if public_ip is not None:
+ params['PublicIp'] = public_ip
+ elif allocation_id is not None:
+ params['AllocationId'] = allocation_id
+
return self.get_status('ReleaseAddress', params, verb='POST')
# Volume methods
@@ -1124,9 +1236,9 @@ class EC2Connection(AWSQueryConnection):
Get all Volumes associated with the current credentials.
:type volume_ids: list
- :param volume_ids: Optional list of volume ids. If this list is present,
- only the volumes associated with these volume ids
- will be returned.
+ :param volume_ids: Optional list of volume ids. If this list
+ is present, only the volumes associated with
+ these volume ids will be returned.
:type filters: dict
:param filters: Optional filters that can be used to limit
@@ -1146,7 +1258,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, volume_ids, 'VolumeId')
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeVolumes', params, [('item', Volume)], verb='POST')
+ return self.get_list('DescribeVolumes', params,
+ [('item', Volume)], verb='POST')
def create_volume(self, size, zone, snapshot=None):
"""
@@ -1261,7 +1374,7 @@ class EC2Connection(AWSQueryConnection):
:type owner: str
:param owner: If present, only the snapshots owned by the specified user
will be returned. Valid values are:
-
+
* self
* amazon
* AWS Account ID
@@ -1292,7 +1405,8 @@ class EC2Connection(AWSQueryConnection):
params['RestorableBy'] = restorable_by
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeSnapshots', params, [('item', Snapshot)], verb='POST')
+ return self.get_list('DescribeSnapshots', params,
+ [('item', Snapshot)], verb='POST')
def create_snapshot(self, volume_id, description=None):
"""
@@ -1311,7 +1425,8 @@ class EC2Connection(AWSQueryConnection):
params = {'VolumeId' : volume_id}
if description:
params['Description'] = description[0:255]
- snapshot = self.get_object('CreateSnapshot', params, Snapshot, verb='POST')
+ snapshot = self.get_object('CreateSnapshot', params,
+ Snapshot, verb='POST')
volume = self.get_all_volumes([volume_id])[0]
volume_name = volume.tags.get('Name')
if volume_name:
@@ -1322,21 +1437,26 @@ class EC2Connection(AWSQueryConnection):
params = {'SnapshotId': snapshot_id}
return self.get_status('DeleteSnapshot', params, verb='POST')
- def trim_snapshots(self, hourly_backups = 8, daily_backups = 7, weekly_backups = 4):
+ def trim_snapshots(self, hourly_backups = 8, daily_backups = 7,
+ weekly_backups = 4):
"""
- Trim excess snapshots, based on when they were taken. More current snapshots are
- retained, with the number retained decreasing as you move back in time.
+ Trim excess snapshots, based on when they were taken. More current
+ snapshots are retained, with the number retained decreasing as you
+ move back in time.
- If ebs volumes have a 'Name' tag with a value, their snapshots will be assigned the same
- tag when they are created. The values of the 'Name' tags for snapshots are used by this
- function to group snapshots taken from the same volume (or from a series of like-named
- volumes over time) for trimming.
+ If ebs volumes have a 'Name' tag with a value, their snapshots
+ will be assigned the same tag when they are created. The values
+ of the 'Name' tags for snapshots are used by this function to
+ group snapshots taken from the same volume (or from a series
+ of like-named volumes over time) for trimming.
- For every group of like-named snapshots, this function retains the newest and oldest
- snapshots, as well as, by default, the first snapshots taken in each of the last eight
- hours, the first snapshots taken in each of the last seven days, the first snapshots
- taken in the last 4 weeks (counting Midnight Sunday morning as the start of the week),
- and the first snapshot from the first Sunday of each month forever.
+ For every group of like-named snapshots, this function retains
+ the newest and oldest snapshots, as well as, by default, the
+ first snapshots taken in each of the last eight hours, the first
+ snapshots taken in each of the last seven days, the first snapshots
+ taken in the last 4 weeks (counting Midnight Sunday morning as
+ the start of the week), and the first snapshot from the first
+ Sunday of each month forever.
:type hourly_backups: int
:param hourly_backups: How many recent hourly backups should be saved.
@@ -1348,15 +1468,18 @@ class EC2Connection(AWSQueryConnection):
:param weekly_backups: How many recent weekly backups should be saved.
"""
- # This function first builds up an ordered list of target times that snapshots should be saved for
- # (last 8 hours, last 7 days, etc.). Then a map of snapshots is constructed, with the keys being
- # the snapshot / volume names and the values being arrays of chornologically sorted snapshots.
- # Finally, for each array in the map, we go through the snapshot array and the target time array
- # in an interleaved fashion, deleting snapshots whose start_times don't immediately follow a
- # target time (we delete a snapshot if there's another snapshot that was made closer to the
- # preceding target time).
+ # This function first builds up an ordered list of target times
+ # that snapshots should be saved for (last 8 hours, last 7 days, etc.).
+ # Then a map of snapshots is constructed, with the keys being
+ # the snapshot / volume names and the values being arrays of
+ # chronologically sorted snapshots.
+ # Finally, for each array in the map, we go through the snapshot
+ # array and the target time array in an interleaved fashion,
+ # deleting snapshots whose start_times don't immediately follow a
+ # target time (we delete a snapshot if there's another snapshot
+ # that was made closer to the preceding target time).
- now = datetime.utcnow() # work with UTC time, which is what the snapshot start time is reported in
+ now = datetime.utcnow()
last_hour = datetime(now.year, now.month, now.day, now.hour)
last_midnight = datetime(now.year, now.month, now.day)
last_sunday = datetime(now.year, now.month, now.day) - timedelta(days = (now.weekday() + 1) % 7)
@@ -1364,7 +1487,8 @@ class EC2Connection(AWSQueryConnection):
target_backup_times = []
- oldest_snapshot_date = datetime(2007, 1, 1) # there are no snapshots older than 1/1/2007
+ # there are no snapshots older than 1/1/2007
+ oldest_snapshot_date = datetime(2007, 1, 1)
for hour in range(0, hourly_backups):
target_backup_times.append(last_hour - timedelta(hours = hour))
@@ -1377,13 +1501,16 @@ class EC2Connection(AWSQueryConnection):
one_day = timedelta(days = 1)
while start_of_month > oldest_snapshot_date:
- # append the start of the month to the list of snapshot dates to save:
+ # append the start of the month to the list of
+ # snapshot dates to save:
target_backup_times.append(start_of_month)
# there's no timedelta setting for one month, so instead:
- # decrement the day by one, so we go to the final day of the previous month...
+ # decrement the day by one, so we go to the final day of
+ # the previous month...
start_of_month -= one_day
# ... and then go to the first day of that previous month:
- start_of_month = datetime(start_of_month.year, start_of_month.month, 1)
+ start_of_month = datetime(start_of_month.year,
+ start_of_month.month, 1)
temp = []
@@ -1392,14 +1519,18 @@ class EC2Connection(AWSQueryConnection):
temp.append(t)
target_backup_times = temp
- target_backup_times.reverse() # make the oldest date first
+ # make the oldeest dates first, and make sure the month start
+ # and last four week's start are in the proper order
+ target_backup_times.sort()
- # get all the snapshots, sort them by date and time, and organize them into one array for each volume:
+ # get all the snapshots, sort them by date and time, and
+ # organize them into one array for each volume:
all_snapshots = self.get_all_snapshots(owner = 'self')
- all_snapshots.sort(cmp = lambda x, y: cmp(x.start_time, y.start_time)) # oldest first
+ all_snapshots.sort(cmp = lambda x, y: cmp(x.start_time, y.start_time))
snaps_for_each_volume = {}
for snap in all_snapshots:
- # the snapshot name and the volume name are the same. The snapshot name is set from the volume
+ # the snapshot name and the volume name are the same.
+ # The snapshot name is set from the volume
# name at the time the snapshot is taken
volume_name = snap.tags.get('Name')
if volume_name:
@@ -1410,34 +1541,46 @@ class EC2Connection(AWSQueryConnection):
snaps_for_each_volume[volume_name] = snaps_for_volume
snaps_for_volume.append(snap)
- # Do a running comparison of snapshot dates to desired time periods, keeping the oldest snapshot in each
+ # Do a running comparison of snapshot dates to desired time
+ #periods, keeping the oldest snapshot in each
# time period and deleting the rest:
for volume_name in snaps_for_each_volume:
snaps = snaps_for_each_volume[volume_name]
- snaps = snaps[:-1] # never delete the newest snapshot, so remove it from consideration
+ snaps = snaps[:-1] # never delete the newest snapshot
time_period_number = 0
snap_found_for_this_time_period = False
for snap in snaps:
check_this_snap = True
while check_this_snap and time_period_number < target_backup_times.__len__():
- snap_date = datetime.strptime(snap.start_time, '%Y-%m-%dT%H:%M:%S.000Z')
+ snap_date = datetime.strptime(snap.start_time,
+ '%Y-%m-%dT%H:%M:%S.000Z')
if snap_date < target_backup_times[time_period_number]:
- # the snap date is before the cutoff date. Figure out if it's the first snap in this
- # date range and act accordingly (since both date the date ranges and the snapshots
- # are sorted chronologically, we know this snapshot isn't in an earlier date range):
+ # the snap date is before the cutoff date.
+ # Figure out if it's the first snap in this
+ # date range and act accordingly (since both
+ #date the date ranges and the snapshots
+ # are sorted chronologically, we know this
+ #snapshot isn't in an earlier date range):
if snap_found_for_this_time_period == True:
if not snap.tags.get('preserve_snapshot'):
- # as long as the snapshot wasn't marked with the 'preserve_snapshot' tag, delete it:
- self.delete_snapshot(snap.id)
- boto.log.info('Trimmed snapshot %s (%s)' % (snap.tags['Name'], snap.start_time))
- # go on and look at the next snapshot, leaving the time period alone
+ # as long as the snapshot wasn't marked
+ # with the 'preserve_snapshot' tag, delete it:
+ try:
+ self.delete_snapshot(snap.id)
+ boto.log.info('Trimmed snapshot %s (%s)' % (snap.tags['Name'], snap.start_time))
+ except EC2ResponseError:
+ boto.log.error('Attempt to trim snapshot %s (%s) failed. Possible result of a race condition with trimming on another server?' % (snap.tags['Name'], snap.start_time))
+ # go on and look at the next snapshot,
+ #leaving the time period alone
else:
- # this was the first snapshot found for this time period. Leave it alone and look at the
+ # this was the first snapshot found for this
+ #time period. Leave it alone and look at the
# next snapshot:
snap_found_for_this_time_period = True
check_this_snap = False
else:
- # the snap is after the cutoff date. Check it against the next cutoff date
+ # the snap is after the cutoff date. Check it
+ # against the next cutoff date
time_period_number += 1
snap_found_for_this_time_period = False
@@ -1453,7 +1596,7 @@ class EC2Connection(AWSQueryConnection):
:type attribute: str
:param attribute: The requested attribute. Valid values are:
-
+
* createVolumePermission
:rtype: list of :class:`boto.ec2.snapshotattribute.SnapshotAttribute`
@@ -1545,7 +1688,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, keynames, 'KeyName')
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeKeyPairs', params, [('item', KeyPair)], verb='POST')
+ return self.get_list('DescribeKeyPairs', params,
+ [('item', KeyPair)], verb='POST')
def get_key_pair(self, keyname):
"""
@@ -1621,13 +1765,14 @@ class EC2Connection(AWSQueryConnection):
The material attribute of the new KeyPair object
will contain the the unencrypted PEM encoded RSA private key.
"""
+ public_key_material = base64.b64encode(public_key_material)
params = {'KeyName' : key_name,
'PublicKeyMaterial' : public_key_material}
return self.get_object('ImportKeyPair', params, KeyPair, verb='POST')
# SecurityGroup methods
- def get_all_security_groups(self, groupnames=None, filters=None):
+ def get_all_security_groups(self, groupnames=None, group_ids=None, filters=None):
"""
Get all security groups associated with your account in a region.
@@ -1636,6 +1781,10 @@ class EC2Connection(AWSQueryConnection):
If not provided, all security groups will be
returned.
+ :type group_ids: list
+ :param group_ids: A list of IDs of security groups to retrieve for
+ security groups within a VPC.
+
:type filters: dict
:param filters: Optional filters that can be used to limit
the results returned. Filters are provided
@@ -1650,14 +1799,17 @@ class EC2Connection(AWSQueryConnection):
:return: A list of :class:`boto.ec2.securitygroup.SecurityGroup`
"""
params = {}
- if groupnames:
+ if groupnames is not None:
self.build_list_params(params, groupnames, 'GroupName')
- if filters:
+ if group_ids is not None:
+ self.build_list_params(params, group_ids, 'GroupId')
+ if filters is not None:
self.build_filter_params(params, filters)
+
return self.get_list('DescribeSecurityGroups', params,
[('item', SecurityGroup)], verb='POST')
- def create_security_group(self, name, description):
+ def create_security_group(self, name, description, vpc_id=None):
"""
Create a new security group for your account.
This will create the security group within the region you
@@ -1669,35 +1821,60 @@ class EC2Connection(AWSQueryConnection):
:type description: string
:param description: The description of the new security group
+ :type vpc_id: string
+ :param vpc_id: The ID of the VPC to create the security group in,
+ if any.
+
:rtype: :class:`boto.ec2.securitygroup.SecurityGroup`
:return: The newly created :class:`boto.ec2.keypair.KeyPair`.
"""
- params = {'GroupName':name, 'GroupDescription':description}
- group = self.get_object('CreateSecurityGroup', params, SecurityGroup, verb='POST')
+ params = {
+ 'GroupName': name,
+ 'GroupDescription': description
+ }
+
+ if vpc_id is not None:
+ params['VpcId'] = vpc_id
+
+ group = self.get_object('CreateSecurityGroup', params,
+ SecurityGroup, verb='POST')
group.name = name
group.description = description
return group
- def delete_security_group(self, name):
+ def delete_security_group(self, name=None, group_id=None):
"""
Delete a security group from your account.
- :type key_name: string
- :param key_name: The name of the keypair to delete
+ :type name: string
+ :param name: The name of the security group to delete.
+
+ :type group_id: string
+ :param group_id: The ID of the security group to delete within
+ a VPC.
+
+ :rtype: bool
+ :return: True if successful.
"""
- params = {'GroupName':name}
+ params = {}
+
+ if name is not None:
+ params['GroupName'] = name
+ elif group_id is not None:
+ params['GroupId'] = group_id
+
return self.get_status('DeleteSecurityGroup', params, verb='POST')
- def _authorize_deprecated(self, group_name, src_security_group_name=None,
- src_security_group_owner_id=None):
+ def authorize_security_group_deprecated(self, group_name,
+ src_security_group_name=None,
+ src_security_group_owner_id=None,
+ ip_protocol=None,
+ from_port=None, to_port=None,
+ cidr_ip=None):
"""
- This method is called only when someone tries to authorize a group
- without specifying a from_port or to_port. Until recently, that was
- the only way to do group authorization but the EC2 API has been
- changed to now require a from_port and to_port when specifying a
- group. This is a much better approach but I don't want to break
- existing boto applications that depend on the old behavior, hence
- this kludge.
+ NOTE: This method uses the old-style request parameters
+ that did not allow a port to be specified when
+ authorizing a group.
:type group_name: string
:param group_name: The name of the security group you are adding
@@ -1711,22 +1888,43 @@ class EC2Connection(AWSQueryConnection):
:param src_security_group_owner_id: The ID of the owner of the security
group you are granting access to.
+ :type ip_protocol: string
+ :param ip_protocol: Either tcp | udp | icmp
+
+ :type from_port: int
+ :param from_port: The beginning port number you are enabling
+
+ :type to_port: int
+ :param to_port: The ending port number you are enabling
+
+ :type to_port: string
+ :param to_port: The CIDR block you are providing access to.
+ See http://goo.gl/Yj5QC
+
:rtype: bool
:return: True if successful.
"""
- warnings.warn('FromPort and ToPort now required for group authorization',
- DeprecationWarning)
params = {'GroupName':group_name}
if src_security_group_name:
params['SourceSecurityGroupName'] = src_security_group_name
if src_security_group_owner_id:
params['SourceSecurityGroupOwnerId'] = src_security_group_owner_id
- return self.get_status('AuthorizeSecurityGroupIngress', params, verb='POST')
+ if ip_protocol:
+ params['IpProtocol'] = ip_protocol
+ if from_port:
+ params['FromPort'] = from_port
+ if to_port:
+ params['ToPort'] = to_port
+ if cidr_ip:
+ params['CidrIp'] = cidr_ip
+ return self.get_status('AuthorizeSecurityGroupIngress', params)
- def authorize_security_group(self, group_name, src_security_group_name=None,
+ def authorize_security_group(self, group_name=None,
+ src_security_group_name=None,
src_security_group_owner_id=None,
ip_protocol=None, from_port=None, to_port=None,
- cidr_ip=None):
+ cidr_ip=None, group_id=None,
+ src_security_group_group_id=None):
"""
Add a new rule to an existing security group.
You need to pass in either src_security_group_name and
@@ -1757,70 +1955,163 @@ class EC2Connection(AWSQueryConnection):
:type cidr_ip: string
:param cidr_ip: The CIDR block you are providing access to.
- See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
+ See http://goo.gl/Yj5QC
+
+ :type group_id: string
+ :param group_id: ID of the EC2 or VPC security group to modify.
+ This is required for VPC security groups and
+ can be used instead of group_name for EC2
+ security groups.
+
+ :type group_id: string
+ :param group_id: ID of the EC2 or VPC source security group.
+ This is required for VPC security groups and
+ can be used instead of group_name for EC2
+ security groups.
:rtype: bool
:return: True if successful.
"""
if src_security_group_name:
if from_port is None and to_port is None and ip_protocol is None:
- return self._authorize_deprecated(group_name,
- src_security_group_name,
- src_security_group_owner_id)
- params = {'GroupName':group_name}
+ return self.authorize_security_group_deprecated(
+ group_name, src_security_group_name,
+ src_security_group_owner_id)
+
+ params = {}
+
+ if group_name:
+ params['GroupName'] = group_name
+ if group_id:
+ params['GroupId'] = group_id
if src_security_group_name:
- params['IpPermissions.1.Groups.1.GroupName'] = src_security_group_name
+ param_name = 'IpPermissions.1.Groups.1.GroupName'
+ params[param_name] = src_security_group_name
if src_security_group_owner_id:
- params['IpPermissions.1.Groups.1.UserId'] = src_security_group_owner_id
+ param_name = 'IpPermissions.1.Groups.1.UserId'
+ params[param_name] = src_security_group_owner_id
+ if src_security_group_group_id:
+ param_name = 'IpPermissions.1.Groups.1.GroupId'
+ params[param_name] = src_security_group_group_id
if ip_protocol:
params['IpPermissions.1.IpProtocol'] = ip_protocol
- if from_port:
+ if from_port is not None:
params['IpPermissions.1.FromPort'] = from_port
- if to_port:
+ if to_port is not None:
params['IpPermissions.1.ToPort'] = to_port
if cidr_ip:
params['IpPermissions.1.IpRanges.1.CidrIp'] = cidr_ip
- return self.get_status('AuthorizeSecurityGroupIngress', params, verb='POST')
- def _revoke_deprecated(self, group_name, src_security_group_name=None,
- src_security_group_owner_id=None):
+ return self.get_status('AuthorizeSecurityGroupIngress',
+ params, verb='POST')
+
+ def authorize_security_group_egress(group_id,
+ ip_protocol,
+ from_port=None,
+ to_port=None,
+ src_group_id=None,
+ cidr_ip=None):
+ """
+ The action adds one or more egress rules to a VPC security
+ group. Specifically, this action permits instances in a
+ security group to send traffic to one or more destination
+ CIDR IP address ranges, or to one or more destination
+ security groups in the same VPC.
"""
- This method is called only when someone tries to revoke a group
- without specifying a from_port or to_port. Until recently, that was
- the only way to do group revocation but the EC2 API has been
- changed to now require a from_port and to_port when specifying a
- group. This is a much better approach but I don't want to break
- existing boto applications that depend on the old behavior, hence
- this kludge.
+ params = {
+ 'GroupId': group_id,
+ 'IpPermissions.1.IpProtocol': ip_protocol
+ }
+
+ if from_port is not None:
+ params['IpPermissions.1.FromPort'] = from_port
+ if to_port is not None:
+ params['IpPermissions.1.ToPort'] = to_port
+ if src_group_id is not None:
+ params['IpPermissions.1.Groups.1.GroupId'] = src_group_id
+ if cidr_ip is not None:
+ params['IpPermissions.1.Groups.1.CidrIp'] = cidr_ip
+
+ return self.get_status('AuthorizeSecurityGroupEgress',
+ params, verb='POST')
+
+ def revoke_security_group_deprecated(self, group_name,
+ src_security_group_name=None,
+ src_security_group_owner_id=None,
+ ip_protocol=None,
+ from_port=None, to_port=None,
+ cidr_ip=None):
+ """
+ NOTE: This method uses the old-style request parameters
+ that did not allow a port to be specified when
+ authorizing a group.
+
+ Remove an existing rule from an existing security group.
+ You need to pass in either src_security_group_name and
+ src_security_group_owner_id OR ip_protocol, from_port, to_port,
+ and cidr_ip. In other words, either you are revoking another
+ group or you are revoking some ip-based rule.
:type group_name: string
- :param group_name: The name of the security group you are adding
- the rule to.
+ :param group_name: The name of the security group you are removing
+ the rule from.
:type src_security_group_name: string
:param src_security_group_name: The name of the security group you are
- granting access to.
+ revoking access to.
:type src_security_group_owner_id: string
:param src_security_group_owner_id: The ID of the owner of the security
- group you are granting access to.
+ group you are revoking access to.
+
+ :type ip_protocol: string
+ :param ip_protocol: Either tcp | udp | icmp
+
+ :type from_port: int
+ :param from_port: The beginning port number you are disabling
+
+ :type to_port: int
+ :param to_port: The ending port number you are disabling
+
+ :type to_port: string
+ :param to_port: The CIDR block you are revoking access to.
+ http://goo.gl/Yj5QC
+
+ :type group_id: string
+ :param group_id: ID of the EC2 or VPC security group to modify.
+ This is required for VPC security groups and
+ can be used instead of group_name for EC2
+ security groups.
+
+ :type group_id: string
+ :param group_id: ID of the EC2 or VPC source security group.
+ This is required for VPC security groups and
+ can be used instead of group_name for EC2
+ security groups.
:rtype: bool
:return: True if successful.
"""
- warnings.warn('FromPort and ToPort now required for group authorization',
- DeprecationWarning)
params = {'GroupName':group_name}
if src_security_group_name:
params['SourceSecurityGroupName'] = src_security_group_name
if src_security_group_owner_id:
params['SourceSecurityGroupOwnerId'] = src_security_group_owner_id
- return self.get_status('RevokeSecurityGroupIngress', params, verb='POST')
+ if ip_protocol:
+ params['IpProtocol'] = ip_protocol
+ if from_port:
+ params['FromPort'] = from_port
+ if to_port:
+ params['ToPort'] = to_port
+ if cidr_ip:
+ params['CidrIp'] = cidr_ip
+ return self.get_status('RevokeSecurityGroupIngress', params)
def revoke_security_group(self, group_name, src_security_group_name=None,
src_security_group_owner_id=None,
ip_protocol=None, from_port=None, to_port=None,
- cidr_ip=None):
+ cidr_ip=None, group_id=None,
+ src_security_group_group_id=None):
"""
Remove an existing rule from an existing security group.
You need to pass in either src_security_group_name and
@@ -1851,30 +2142,35 @@ class EC2Connection(AWSQueryConnection):
:type cidr_ip: string
:param cidr_ip: The CIDR block you are revoking access to.
- See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
+ See http://goo.gl/Yj5QC
:rtype: bool
:return: True if successful.
"""
if src_security_group_name:
if from_port is None and to_port is None and ip_protocol is None:
- return self._revoke_deprecated(group_name,
- src_security_group_name,
- src_security_group_owner_id)
- params = {'GroupName':group_name}
+ return self.revoke_security_group_deprecated(
+ group_name, src_security_group_name,
+ src_security_group_owner_id)
+ params = {}
+ if group_name:
+ params['GroupName'] = group_name
if src_security_group_name:
- params['IpPermissions.1.Groups.1.GroupName'] = src_security_group_name
+ param_name = 'IpPermissions.1.Groups.1.GroupName'
+ params[param_name] = src_security_group_name
if src_security_group_owner_id:
- params['IpPermissions.1.Groups.1.UserId'] = src_security_group_owner_id
+ param_name = 'IpPermissions.1.Groups.1.UserId'
+ params[param_name] = src_security_group_owner_id
if ip_protocol:
params['IpPermissions.1.IpProtocol'] = ip_protocol
- if from_port:
+ if from_port is not None:
params['IpPermissions.1.FromPort'] = from_port
- if to_port:
+ if to_port is not None:
params['IpPermissions.1.ToPort'] = to_port
if cidr_ip:
params['IpPermissions.1.IpRanges.1.CidrIp'] = cidr_ip
- return self.get_status('RevokeSecurityGroupIngress', params, verb='POST')
+ return self.get_status('RevokeSecurityGroupIngress',
+ params, verb='POST')
#
# Regions
@@ -1905,7 +2201,8 @@ class EC2Connection(AWSQueryConnection):
self.build_list_params(params, region_names, 'RegionName')
if filters:
self.build_filter_params(params, filters)
- regions = self.get_list('DescribeRegions', params, [('item', RegionInfo)], verb='POST')
+ regions = self.get_list('DescribeRegions', params,
+ [('item', RegionInfo)], verb='POST')
for region in regions:
region.connection_cls = EC2Connection
return regions
@@ -1964,7 +2261,8 @@ class EC2Connection(AWSQueryConnection):
self.build_filter_params(params, filters)
return self.get_list('DescribeReservedInstancesOfferings',
- params, [('item', ReservedInstancesOffering)], verb='POST')
+ params, [('item', ReservedInstancesOffering)],
+ verb='POST')
def get_all_reserved_instances(self, reserved_instances_id=None,
filters=None):
@@ -1998,7 +2296,8 @@ class EC2Connection(AWSQueryConnection):
return self.get_list('DescribeReservedInstances',
params, [('item', ReservedInstance)], verb='POST')
- def purchase_reserved_instance_offering(self, reserved_instances_offering_id,
+ def purchase_reserved_instance_offering(self,
+ reserved_instances_offering_id,
instance_count=1):
"""
Purchase a Reserved Instance for use with your account.
@@ -2017,8 +2316,9 @@ class EC2Connection(AWSQueryConnection):
:rtype: :class:`boto.ec2.reservedinstance.ReservedInstance`
:return: The newly created Reserved Instance
"""
- params = {'ReservedInstancesOfferingId' : reserved_instances_offering_id,
- 'InstanceCount' : instance_count}
+ params = {
+ 'ReservedInstancesOfferingId' : reserved_instances_offering_id,
+ 'InstanceCount' : instance_count}
return self.get_object('PurchaseReservedInstancesOffering', params,
ReservedInstance, verb='POST')
@@ -2026,8 +2326,24 @@ class EC2Connection(AWSQueryConnection):
# Monitoring
#
+ def monitor_instances(self, instance_ids):
+ """
+ Enable CloudWatch monitoring for the supplied instances.
+
+ :type instance_id: list of strings
+ :param instance_id: The instance ids
+
+ :rtype: list
+ :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo`
+ """
+ params = {}
+ self.build_list_params(params, instance_ids, 'InstanceId')
+ return self.get_list('MonitorInstances', params,
+ [('item', InstanceInfo)], verb='POST')
+
def monitor_instance(self, instance_id):
"""
+ Deprecated Version, maintained for backward compatibility.
Enable CloudWatch monitoring for the supplied instance.
:type instance_id: string
@@ -2036,12 +2352,26 @@ class EC2Connection(AWSQueryConnection):
:rtype: list
:return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo`
"""
- params = {'InstanceId' : instance_id}
- return self.get_list('MonitorInstances', params,
+ return self.monitor_instances([instance_id])
+
+ def unmonitor_instances(self, instance_ids):
+ """
+ Disable CloudWatch monitoring for the supplied instance.
+
+ :type instance_id: list of string
+ :param instance_id: The instance id
+
+ :rtype: list
+ :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo`
+ """
+ params = {}
+ self.build_list_params(params, instance_ids, 'InstanceId')
+ return self.get_list('UnmonitorInstances', params,
[('item', InstanceInfo)], verb='POST')
def unmonitor_instance(self, instance_id):
"""
+ Deprecated Version, maintained for backward compatibility.
Disable CloudWatch monitoring for the supplied instance.
:type instance_id: string
@@ -2050,16 +2380,14 @@ class EC2Connection(AWSQueryConnection):
:rtype: list
:return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo`
"""
- params = {'InstanceId' : instance_id}
- return self.get_list('UnmonitorInstances', params,
- [('item', InstanceInfo)], verb='POST')
+ return self.unmonitor_instances([instance_id])
- #
+ #
# Bundle Windows Instances
#
def bundle_instance(self, instance_id,
- s3_bucket,
+ s3_bucket,
s3_prefix,
s3_upload_policy):
"""
@@ -2084,11 +2412,13 @@ class EC2Connection(AWSQueryConnection):
'Storage.S3.Bucket' : s3_bucket,
'Storage.S3.Prefix' : s3_prefix,
'Storage.S3.UploadPolicy' : s3_upload_policy}
- s3auth = boto.auth.get_auth_handler(None, boto.config, self.provider, ['s3'])
+ s3auth = boto.auth.get_auth_handler(None, boto.config,
+ self.provider, ['s3'])
params['Storage.S3.AWSAccessKeyId'] = self.aws_access_key_id
signature = s3auth.sign_string(s3_upload_policy)
params['Storage.S3.UploadPolicySignature'] = signature
- return self.get_object('BundleInstance', params, BundleInstanceTask, verb='POST')
+ return self.get_object('BundleInstance', params,
+ BundleInstanceTask, verb='POST')
def get_all_bundle_tasks(self, bundle_ids=None, filters=None):
"""
@@ -2096,9 +2426,9 @@ class EC2Connection(AWSQueryConnection):
tasks are retrieved.
:type bundle_ids: list
- :param bundle_ids: A list of strings containing identifiers for
+ :param bundle_ids: A list of strings containing identifiers for
previously created bundling tasks.
-
+
:type filters: dict
:param filters: Optional filters that can be used to limit
the results returned. Filters are provided
@@ -2110,7 +2440,7 @@ class EC2Connection(AWSQueryConnection):
for details.
"""
-
+
params = {}
if bundle_ids:
self.build_list_params(params, bundle_ids, 'BundleId')
@@ -2122,13 +2452,14 @@ class EC2Connection(AWSQueryConnection):
def cancel_bundle_task(self, bundle_id):
"""
Cancel a previously submitted bundle task
-
+
:type bundle_id: string
:param bundle_id: The identifier of the bundle task to cancel.
- """
+ """
params = {'BundleId' : bundle_id}
- return self.get_object('CancelBundleTask', params, BundleInstanceTask, verb='POST')
+ return self.get_object('CancelBundleTask', params,
+ BundleInstanceTask, verb='POST')
def get_password_data(self, instance_id):
"""
@@ -2143,7 +2474,7 @@ class EC2Connection(AWSQueryConnection):
rs = self.get_object('GetPasswordData', params, ResultSet, verb='POST')
return rs.passwordData
- #
+ #
# Cluster Placement Groups
#
@@ -2190,8 +2521,8 @@ class EC2Connection(AWSQueryConnection):
:param strategy: The placement strategy of the new placement group.
Currently, the only acceptable value is "cluster".
- :rtype: :class:`boto.ec2.placementgroup.PlacementGroup`
- :return: The newly created :class:`boto.ec2.keypair.KeyPair`.
+ :rtype: bool
+ :return: True if successful
"""
params = {'GroupName':name, 'Strategy':strategy}
group = self.get_status('CreatePlacementGroup', params, verb='POST')
@@ -2219,14 +2550,11 @@ class EC2Connection(AWSQueryConnection):
if value is not None:
params['Tag.%d.Value'%i] = value
i += 1
-
- def get_all_tags(self, tags=None, filters=None):
+
+ def get_all_tags(self, filters=None):
"""
Retrieve all the metadata tags associated with your account.
- :type tags: list
- :param tags: A list of mumble
-
:type filters: dict
:param filters: Optional filters that can be used to limit
the results returned. Filters are provided
@@ -2241,11 +2569,10 @@ class EC2Connection(AWSQueryConnection):
:return: A dictionary containing metadata tags
"""
params = {}
- if tags:
- self.build_list_params(params, instance_ids, 'InstanceId')
if filters:
self.build_filter_params(params, filters)
- return self.get_list('DescribeTags', params, [('item', Tag)], verb='POST')
+ return self.get_list('DescribeTags', params,
+ [('item', Tag)], verb='POST')
def create_tags(self, resource_ids, tags):
"""
@@ -2255,7 +2582,10 @@ class EC2Connection(AWSQueryConnection):
:param resource_ids: List of strings
:type tags: dict
- :param tags: A dictionary containing the name/value pairs
+ :param tags: A dictionary containing the name/value pairs.
+ If you want to create only a tag name, the
+ value for that tag should be the empty string
+ (e.g. '').
"""
params = {}
@@ -2275,7 +2605,9 @@ class EC2Connection(AWSQueryConnection):
or a list containing just tag names.
If you pass in a dictionary, the values must
match the actual tag values or the tag will
- not be deleted.
+ not be deleted. If you pass in a value of None
+ for the tag value, all tags with that name will
+ be deleted.
"""
if isinstance(tags, list):
« no previous file with comments | « boto/ec2/cloudwatch/metric.py ('k') | boto/ec2/ec2object.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698