Upgrade boto to 2.32.1

This commit is contained in:
Matthew Jones
2014-08-06 13:57:39 -04:00
parent 6f6f8675f9
commit 7899463ac8
183 changed files with 8546 additions and 2028 deletions

View File

@@ -45,6 +45,7 @@ from boto.ec2.autoscale.instance import Instance
from boto.ec2.autoscale.scheduled import ScheduledUpdateGroupAction
from boto.ec2.autoscale.tag import Tag
from boto.ec2.autoscale.limits import AccountLimits
from boto.compat import six
RegionData = load_regions().get('autoscaling', {})
@@ -134,15 +135,15 @@ class AutoScaleConnection(AWSQueryConnection):
['us-east-1b',...]
"""
# different from EC2 list params
for i in xrange(1, len(items) + 1):
for i in range(1, len(items) + 1):
if isinstance(items[i - 1], dict):
for k, v in items[i - 1].iteritems():
for k, v in six.iteritems(items[i - 1]):
if isinstance(v, dict):
for kk, vv in v.iteritems():
for kk, vv in six.iteritems(v):
params['%s.member.%d.%s.%s' % (label, i, k, kk)] = vv
else:
params['%s.member.%d.%s' % (label, i, k)] = v
elif isinstance(items[i - 1], basestring):
elif isinstance(items[i - 1], six.string_types):
params['%s.member.%d' % (label, i)] = items[i - 1]
def _update_group(self, op, as_group):
@@ -221,7 +222,7 @@ class AutoScaleConnection(AWSQueryConnection):
if launch_config.key_name:
params['KeyName'] = launch_config.key_name
if launch_config.user_data:
params['UserData'] = base64.b64encode(launch_config.user_data)
params['UserData'] = base64.b64encode(launch_config.user_data).decode('utf-8')
if launch_config.kernel_id:
params['KernelId'] = launch_config.kernel_id
if launch_config.ramdisk_id:

View File

@@ -18,7 +18,6 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
import boto.ec2
from boto.sdb.db.property import StringProperty, IntegerProperty
from boto.manage import propget
@@ -66,19 +65,19 @@ if __name__ == "__main__":
obj.get(params)
offerings = obj.ec2.get_all_reserved_instances_offerings(instance_type=params['instance_type'],
availability_zone=params['zone'].name)
print '\nThe following Reserved Instances Offerings are available:\n'
print('\nThe following Reserved Instances Offerings are available:\n')
for offering in offerings:
offering.describe()
prop = StringProperty(name='offering', verbose_name='Offering',
choices=offerings)
offering = propget.get(prop)
print '\nYou have chosen this offering:'
print('\nYou have chosen this offering:')
offering.describe()
unit_price = float(offering.fixed_price)
total_price = unit_price * params['quantity']
print '!!! You are about to purchase %d of these offerings for a total of $%.2f !!!' % (params['quantity'], total_price)
print('!!! You are about to purchase %d of these offerings for a total of $%.2f !!!' % (params['quantity'], total_price))
answer = raw_input('Are you sure you want to do this? If so, enter YES: ')
if answer.strip().lower() == 'yes':
offering.purchase(params['quantity'])
else:
print 'Purchase cancelled'
print('Purchase cancelled')

View File

@@ -23,7 +23,7 @@
This module provides an interface to the Elastic Compute Cloud (EC2)
CloudWatch service from AWS.
"""
from boto.compat import json
from boto.compat import json, map, six, zip
from boto.connection import AWSQueryConnection
from boto.ec2.cloudwatch.metric import Metric
from boto.ec2.cloudwatch.alarm import MetricAlarm, MetricAlarms, AlarmHistoryItem
@@ -110,7 +110,7 @@ class CloudWatchConnection(AWSQueryConnection):
for dim_name in dimension:
dim_value = dimension[dim_name]
if dim_value:
if isinstance(dim_value, basestring):
if isinstance(dim_value, six.string_types):
dim_value = [dim_value]
for value in dim_value:
params['%s.%d.Name' % (prefix, i+1)] = dim_name
@@ -121,12 +121,12 @@ class CloudWatchConnection(AWSQueryConnection):
i += 1
def build_list_params(self, params, items, label):
if isinstance(items, basestring):
if isinstance(items, six.string_types):
items = [items]
for index, item in enumerate(items):
i = index + 1
if isinstance(item, dict):
for k, v in item.iteritems():
for k, v in six.iteritems(item):
params[label % (i, 'Name')] = k
if v is not None:
params[label % (i, 'Value')] = v
@@ -171,7 +171,7 @@ class CloudWatchConnection(AWSQueryConnection):
else:
raise Exception('Must specify a value or statistics to put.')
for key, val in metric_data.iteritems():
for key, val in six.iteritems(metric_data):
params['MetricData.member.%d.%s' % (index + 1, key)] = val
def get_metric_statistics(self, period, start_time, end_time, metric_name,

View File

@@ -21,10 +21,10 @@
#
from datetime import datetime
from boto.resultset import ResultSet
from boto.ec2.cloudwatch.listelement import ListElement
from boto.ec2.cloudwatch.dimension import Dimension
from boto.compat import json
from boto.compat import six
class MetricAlarms(list):
@@ -57,7 +57,7 @@ class MetricAlarm(object):
'<': 'LessThanThreshold',
'<=': 'LessThanOrEqualToThreshold',
}
_rev_cmp_map = dict((v, k) for (k, v) in _cmp_map.iteritems())
_rev_cmp_map = dict((v, k) for (k, v) in six.iteritems(_cmp_map))
def __init__(self, connection=None, name=None, metric=None,
namespace=None, statistic=None, comparison=None,
@@ -252,11 +252,11 @@ class MetricAlarm(object):
def add_alarm_action(self, action_arn=None):
"""
Adds an alarm action, represented as an SNS topic, to this alarm.
Adds an alarm action, represented as an SNS topic, to this alarm.
What do do when alarm is triggered.
:type action_arn: str
:param action_arn: SNS topics to which notification should be
:param action_arn: SNS topics to which notification should be
sent if the alarm goes to state ALARM.
"""
if not action_arn:
@@ -270,21 +270,21 @@ class MetricAlarm(object):
this alarm. What to do when the insufficient_data state is reached.
:type action_arn: str
:param action_arn: SNS topics to which notification should be
:param action_arn: SNS topics to which notification should be
sent if the alarm goes to state INSUFFICIENT_DATA.
"""
if not action_arn:
return
self.actions_enabled = 'true'
self.insufficient_data_actions.append(action_arn)
def add_ok_action(self, action_arn=None):
"""
Adds an ok action, represented as an SNS topic, to this alarm. What
to do when the ok state is reached.
:type action_arn: str
:param action_arn: SNS topics to which notification should be
:param action_arn: SNS topics to which notification should be
sent if the alarm goes to state INSUFFICIENT_DATA.
"""
if not action_arn:
@@ -320,4 +320,3 @@ class AlarmHistoryItem(object):
'%Y-%m-%dT%H:%M:%S.%fZ')
except ValueError:
self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')

View File

@@ -37,4 +37,3 @@ class Datapoint(dict):
self[name] = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
elif name != 'member':
self[name] = value

View File

@@ -35,4 +35,3 @@ class Dimension(dict):
self[self._name] = [value]
else:
setattr(self, name, value)

View File

@@ -27,5 +27,3 @@ class ListElement(list):
def endElement(self, name, value, connection):
if name == 'member':
self.append(value)

View File

@@ -65,13 +65,14 @@ from boto.ec2.networkinterface import NetworkInterface
from boto.ec2.attributes import AccountAttribute, VPCAttribute
from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
from boto.exception import EC2ResponseError
from boto.compat import six
#boto.set_stream_logger('ec2')
class EC2Connection(AWSQueryConnection):
APIVersion = boto.config.get('Boto', 'ec2_version', '2013-10-15')
APIVersion = boto.config.get('Boto', 'ec2_version', '2014-05-01')
DefaultRegionName = boto.config.get('Boto', 'ec2_region_name', 'us-east-1')
DefaultRegionEndpoint = boto.config.get('Boto', 'ec2_region_endpoint',
'ec2.us-east-1.amazonaws.com')
@@ -109,7 +110,7 @@ class EC2Connection(AWSQueryConnection):
def get_params(self):
"""
Returns a dictionary containing the value of of all of the keyword
Returns a dictionary containing the value of all of the keyword
arguments passed when constructing this connection.
"""
param_names = ['aws_access_key_id', 'aws_secret_access_key',
@@ -122,6 +123,9 @@ class EC2Connection(AWSQueryConnection):
return params
def build_filter_params(self, params, filters):
if not isinstance(filters, dict):
filters = dict(filters)
i = 1
for name in filters:
aws_name = name
@@ -266,7 +270,8 @@ class EC2Connection(AWSQueryConnection):
root_device_name=None, block_device_map=None,
dry_run=False, virtualization_type=None,
sriov_net_support=None,
snapshot_id=None):
snapshot_id=None,
delete_root_volume_on_termination=False):
"""
Register an image.
@@ -315,6 +320,12 @@ class EC2Connection(AWSQueryConnection):
as root device for the image. Mutually exclusive with
block_device_map, requires root_device_name
:type delete_root_volume_on_termination: bool
:param delete_root_volume_on_termination: Whether to delete the root
volume of the image after instance termination. Only applies when
creating image from snapshot_id. Defaults to False. Note that
leaving volumes behind after instance termination is not free.
:rtype: string
:return: The new image id
"""
@@ -334,7 +345,8 @@ class EC2Connection(AWSQueryConnection):
if root_device_name:
params['RootDeviceName'] = root_device_name
if snapshot_id:
root_vol = BlockDeviceType(snapshot_id=snapshot_id)
root_vol = BlockDeviceType(snapshot_id=snapshot_id,
delete_on_termination=delete_root_volume_on_termination)
block_device_map = BlockDeviceMapping()
block_device_map[root_device_name] = root_vol
if block_device_map:
@@ -602,15 +614,24 @@ class EC2Connection(AWSQueryConnection):
:rtype: list
:return: A list of :class:`boto.ec2.instance.Instance`
"""
reservations = self.get_all_reservations(instance_ids=instance_ids,
filters=filters,
dry_run=dry_run,
max_results=max_results)
return [instance for reservation in reservations
for instance in reservation.instances]
next_token = None
retval = []
while True:
reservations = self.get_all_reservations(instance_ids=instance_ids,
filters=filters,
dry_run=dry_run,
max_results=max_results,
next_token=next_token)
retval.extend([instance for reservation in reservations for
instance in reservation.instances])
next_token = reservations.next_token
if not next_token:
break
return retval
def get_all_reservations(self, instance_ids=None, filters=None,
dry_run=False, max_results=None):
dry_run=False, max_results=None, next_token=None):
"""
Retrieve all the instance reservations associated with your account.
@@ -632,6 +653,10 @@ class EC2Connection(AWSQueryConnection):
:param max_results: The maximum number of paginated instance
items per response.
:type next_token: str
:param next_token: A string specifying the next paginated set
of results to return.
:rtype: list
:return: A list of :class:`boto.ec2.instance.Reservation`
"""
@@ -652,12 +677,15 @@ class EC2Connection(AWSQueryConnection):
params['DryRun'] = 'true'
if max_results is not None:
params['MaxResults'] = max_results
if next_token:
params['NextToken'] = next_token
return self.get_list('DescribeInstances', params,
[('item', Reservation)], verb='POST')
def get_all_instance_status(self, instance_ids=None,
max_results=None, next_token=None,
filters=None, dry_run=False):
filters=None, dry_run=False,
include_all_instances=False):
"""
Retrieve all the instances in your account scheduled for maintenance.
@@ -685,6 +713,11 @@ class EC2Connection(AWSQueryConnection):
:type dry_run: bool
:param dry_run: Set to True if the operation should not actually run.
:type include_all_instances: bool
:param include_all_instances: Set to True if all
instances should be returned. (Only running
instances are included by default.)
:rtype: list
:return: A list of instances that have maintenance scheduled.
"""
@@ -699,6 +732,8 @@ class EC2Connection(AWSQueryConnection):
self.build_filter_params(params, filters)
if dry_run:
params['DryRun'] = 'true'
if include_all_instances:
params['IncludeAllInstances'] = 'true'
return self.get_object('DescribeInstanceStatus', params,
InstanceStatusSet, verb='POST')
@@ -775,6 +810,9 @@ class EC2Connection(AWSQueryConnection):
* i2.2xlarge
* i2.4xlarge
* i2.8xlarge
* t2.micro
* t2.small
* t2.medium
:type placement: string
:param placement: The Availability Zone to launch the instance into.
@@ -788,7 +826,7 @@ class EC2Connection(AWSQueryConnection):
instances.
:type monitoring_enabled: bool
:param monitoring_enabled: Enable CloudWatch monitoring on
:param monitoring_enabled: Enable detailed CloudWatch monitoring on
the instance.
:type subnet_id: string
@@ -856,9 +894,9 @@ class EC2Connection(AWSQueryConnection):
provide optimal EBS I/O performance. This optimization
isn't available with all instance types.
:type network_interfaces: list
:param network_interfaces: A list of
:class:`boto.ec2.networkinterface.NetworkInterfaceSpecification`
:type network_interfaces: :class:`boto.ec2.networkinterface.NetworkInterfaceCollection`
:param network_interfaces: A NetworkInterfaceCollection data
structure containing the ENI specifications for the instance.
:type dry_run: bool
:param dry_run: Set to True if the operation should not actually run.
@@ -889,7 +927,9 @@ class EC2Connection(AWSQueryConnection):
l.append(group)
self.build_list_params(params, l, 'SecurityGroup')
if user_data:
params['UserData'] = base64.b64encode(user_data)
if isinstance(user_data, six.text_type):
user_data = user_data.encode('utf-8')
params['UserData'] = base64.b64encode(user_data).decode('utf-8')
if addressing_type:
params['AddressingType'] = addressing_type
if instance_type:
@@ -1470,6 +1510,9 @@ class EC2Connection(AWSQueryConnection):
* i2.2xlarge
* i2.4xlarge
* i2.8xlarge
* t2.micro
* t2.small
* t2.medium
:type placement: string
:param placement: The availability zone in which to launch
@@ -1484,7 +1527,7 @@ class EC2Connection(AWSQueryConnection):
instances
:type monitoring_enabled: bool
:param monitoring_enabled: Enable CloudWatch monitoring on
:param monitoring_enabled: Enable detailed CloudWatch monitoring on
the instance.
:type subnet_id: string
@@ -2223,8 +2266,8 @@ class EC2Connection(AWSQueryConnection):
params['DryRun'] = 'true'
return self.get_status('ModifyVolumeAttribute', params, verb='POST')
def create_volume(self, size, zone, snapshot=None,
volume_type=None, iops=None, dry_run=False):
def create_volume(self, size, zone, snapshot=None, volume_type=None,
iops=None, encrypted=False, dry_run=False):
"""
Create a new EBS Volume.
@@ -2240,12 +2283,16 @@ class EC2Connection(AWSQueryConnection):
:type volume_type: string
:param volume_type: The type of the volume. (optional). Valid
values are: standard | io1.
values are: standard | io1 | gp2.
:type iops: int
:param iops: The provisioned IOPs you want to associate with
:param iops: The provisioned IOPS you want to associate with
this volume. (optional)
:type encrypted: bool
:param encrypted: Specifies whether the volume should be encrypted.
(optional)
:type dry_run: bool
:param dry_run: Set to True if the operation should not actually run.
@@ -2263,6 +2310,8 @@ class EC2Connection(AWSQueryConnection):
params['VolumeType'] = volume_type
if iops:
params['Iops'] = str(iops)
if encrypted:
params['Encrypted'] = 'true'
if dry_run:
params['DryRun'] = 'true'
return self.get_object('CreateVolume', params, Volume, verb='POST')
@@ -2790,7 +2839,7 @@ class EC2Connection(AWSQueryConnection):
keynames=[keyname],
dry_run=dry_run
)[0]
except self.ResponseError, e:
except self.ResponseError as e:
if e.code == 'InvalidKeyPair.NotFound':
return None
else:
@@ -3819,7 +3868,7 @@ class EC2Connection(AWSQueryConnection):
def monitor_instances(self, instance_ids, dry_run=False):
"""
Enable CloudWatch monitoring for the supplied instances.
Enable detailed CloudWatch monitoring for the supplied instances.
:type instance_id: list of strings
:param instance_id: The instance ids
@@ -3840,7 +3889,7 @@ class EC2Connection(AWSQueryConnection):
def monitor_instance(self, instance_id, dry_run=False):
"""
Deprecated Version, maintained for backward compatibility.
Enable CloudWatch monitoring for the supplied instance.
Enable detailed CloudWatch monitoring for the supplied instance.
:type instance_id: string
:param instance_id: The instance id
@@ -3876,7 +3925,7 @@ class EC2Connection(AWSQueryConnection):
def unmonitor_instance(self, instance_id, dry_run=False):
"""
Deprecated Version, maintained for backward compatibility.
Disable CloudWatch monitoring for the supplied instance.
Disable detailed CloudWatch monitoring for the supplied instance.
:type instance_id: string
:param instance_id: The instance id
@@ -4184,11 +4233,14 @@ class EC2Connection(AWSQueryConnection):
# Network Interface methods
def get_all_network_interfaces(self, filters=None, dry_run=False):
def get_all_network_interfaces(self, network_interface_ids=None, filters=None, dry_run=False):
"""
Retrieve all of the Elastic Network Interfaces (ENI's)
associated with your account.
:type network_interface_ids: list
:param network_interface_ids: a list of strings representing ENI IDs
:type filters: dict
:param filters: Optional filters that can be used to limit
the results returned. Filters are provided
@@ -4206,6 +4258,8 @@ class EC2Connection(AWSQueryConnection):
:return: A list of :class:`boto.ec2.networkinterface.NetworkInterface`
"""
params = {}
if network_interface_ids:
self.build_list_params(params, network_interface_ids, 'NetworkInterfaceId')
if filters:
self.build_filter_params(params, filters)
if dry_run:
@@ -4339,7 +4393,8 @@ class EC2Connection(AWSQueryConnection):
"""
:type dry_run: bool
:param dry_run: Set to True if the operation should not actually run.
:rtype: :class:`boto.ec2.image.CopyImage`
:return: Object containing the image_id of the copied image.
"""
params = {
'SourceRegion': source_region,

View File

@@ -85,6 +85,27 @@ class TaggedEC2Object(EC2Object):
self.tags = TagSet()
self.tags[key] = value
def add_tags(self, tags, dry_run=False):
"""
Add tags to this object. Tags are stored by AWS and can be used
to organize and filter resources. Adding tags involves a round-trip
to the EC2 service.
:type tags: dict
:param tags: A dictionary of key-value pairs for the tags being stored.
If for some tags you want only the name and no value, the
corresponding value for that tag name should be an empty
string.
"""
status = self.connection.create_tags(
[self.id],
tags,
dry_run=dry_run
)
if self.tags is None:
self.tags = TagSet()
self.tags.update(tags)
def remove_tag(self, key, value=None, dry_run=False):
"""
Remove a tag from this object. Removing a tag involves a round-trip
@@ -102,7 +123,7 @@ class TaggedEC2Object(EC2Object):
NOTE: There is an important distinction between
a value of '' and a value of None.
"""
if value:
if value is not None:
tags = {key : value}
else:
tags = [key]

View File

@@ -30,9 +30,9 @@ from boto.ec2.instanceinfo import InstanceInfo
from boto.ec2.elb.loadbalancer import LoadBalancer, LoadBalancerZones
from boto.ec2.elb.instancestate import InstanceState
from boto.ec2.elb.healthcheck import HealthCheck
from boto.ec2.elb.listelement import ListElement
from boto.regioninfo import RegionInfo, get_regions, load_regions
import boto
from boto.compat import six
RegionData = load_regions().get('elasticloadbalancing', {})
@@ -68,8 +68,9 @@ class ELBConnection(AWSQueryConnection):
APIVersion = boto.config.get('Boto', 'elb_version', '2012-06-01')
DefaultRegionName = boto.config.get('Boto', 'elb_region_name', 'us-east-1')
DefaultRegionEndpoint = boto.config.get('Boto', 'elb_region_endpoint',
'elasticloadbalancing.us-east-1.amazonaws.com')
DefaultRegionEndpoint = boto.config.get(
'Boto', 'elb_region_endpoint',
'elasticloadbalancing.us-east-1.amazonaws.com')
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
is_secure=True, port=None, proxy=None, proxy_port=None,
@@ -87,31 +88,37 @@ class ELBConnection(AWSQueryConnection):
self.DefaultRegionEndpoint)
self.region = region
super(ELBConnection, self).__init__(aws_access_key_id,
aws_secret_access_key,
is_secure, port, proxy, proxy_port,
proxy_user, proxy_pass,
self.region.endpoint, debug,
https_connection_factory, path,
security_token,
validate_certs=validate_certs,
profile_name=profile_name)
aws_secret_access_key,
is_secure, port, proxy, proxy_port,
proxy_user, proxy_pass,
self.region.endpoint, debug,
https_connection_factory, path,
security_token,
validate_certs=validate_certs,
profile_name=profile_name)
def _required_auth_capability(self):
return ['ec2']
def build_list_params(self, params, items, label):
if isinstance(items, basestring):
if isinstance(items, six.string_types):
items = [items]
for index, item in enumerate(items):
params[label % (index + 1)] = item
def get_all_load_balancers(self, load_balancer_names=None):
def get_all_load_balancers(self, load_balancer_names=None, marker=None):
"""
Retrieve all load balancers associated with your account.
:type load_balancer_names: list
:keyword load_balancer_names: An optional list of load balancer names.
:type marker: string
:param marker: Use this only when paginating results and only
in follow-up request after you've received a response
where the results are truncated. Set this to the value of
the Marker element in the response you just received.
:rtype: :py:class:`boto.resultset.ResultSet`
:return: A ResultSet containing instances of
:class:`boto.ec2.elb.loadbalancer.LoadBalancer`
@@ -120,11 +127,16 @@ class ELBConnection(AWSQueryConnection):
if load_balancer_names:
self.build_list_params(params, load_balancer_names,
'LoadBalancerNames.member.%d')
if marker:
params['Marker'] = marker
return self.get_list('DescribeLoadBalancers', params,
[('member', LoadBalancer)])
def create_load_balancer(self, name, zones, listeners=None, subnets=None,
security_groups=None, scheme='internet-facing', complex_listeners=None):
security_groups=None, scheme='internet-facing',
complex_listeners=None):
"""
Create a new load balancer for your account. By default the load
balancer will be created in EC2. To create a load balancer inside a
@@ -170,13 +182,14 @@ class ELBConnection(AWSQueryConnection):
:type complex_listeners: List of tuples
:param complex_listeners: Each tuple contains four or five values,
(LoadBalancerPortNumber, InstancePortNumber, Protocol, InstanceProtocol,
SSLCertificateId).
(LoadBalancerPortNumber, InstancePortNumber, Protocol,
InstanceProtocol, SSLCertificateId).
Where:
- LoadBalancerPortNumber and InstancePortNumber are integer
values between 1 and 65535
- Protocol and InstanceProtocol is a string containing either 'TCP',
- Protocol and InstanceProtocol is a string containing
either 'TCP',
'SSL', 'HTTP', or 'HTTPS'
- SSLCertificateId is the ARN of an SSL certificate loaded into
AWS IAM
@@ -224,7 +237,7 @@ class ELBConnection(AWSQueryConnection):
if security_groups:
self.build_list_params(params, security_groups,
'SecurityGroups.member.%d')
'SecurityGroups.member.%d')
load_balancer = self.get_object('CreateLoadBalancer',
params, LoadBalancer)
@@ -235,7 +248,8 @@ class ELBConnection(AWSQueryConnection):
load_balancer.security_groups = security_groups
return load_balancer
def create_load_balancer_listeners(self, name, listeners=None, complex_listeners=None):
def create_load_balancer_listeners(self, name, listeners=None,
complex_listeners=None):
"""
Creates a Listener (or group of listeners) for an existing
Load Balancer
@@ -254,13 +268,14 @@ class ELBConnection(AWSQueryConnection):
:type complex_listeners: List of tuples
:param complex_listeners: Each tuple contains four or five values,
(LoadBalancerPortNumber, InstancePortNumber, Protocol, InstanceProtocol,
SSLCertificateId).
(LoadBalancerPortNumber, InstancePortNumber, Protocol,
InstanceProtocol, SSLCertificateId).
Where:
- LoadBalancerPortNumber and InstancePortNumber are integer
values between 1 and 65535
- Protocol and InstanceProtocol is a string containing either 'TCP',
- Protocol and InstanceProtocol is a string containing
either 'TCP',
'SSL', 'HTTP', or 'HTTPS'
- SSLCertificateId is the ARN of an SSL certificate loaded into
AWS IAM
@@ -347,7 +362,7 @@ class ELBConnection(AWSQueryConnection):
self.build_list_params(params, zones_to_add,
'AvailabilityZones.member.%d')
obj = self.get_object('EnableAvailabilityZonesForLoadBalancer',
params, LoadBalancerZones)
params, LoadBalancerZones)
return obj.zones
def disable_availability_zones(self, load_balancer_name, zones_to_remove):
@@ -372,7 +387,7 @@ class ELBConnection(AWSQueryConnection):
self.build_list_params(params, zones_to_remove,
'AvailabilityZones.member.%d')
obj = self.get_object('DisableAvailabilityZonesForLoadBalancer',
params, LoadBalancerZones)
params, LoadBalancerZones)
return obj.zones
def modify_lb_attribute(self, load_balancer_name, attribute, value):
@@ -386,6 +401,7 @@ class ELBConnection(AWSQueryConnection):
* crossZoneLoadBalancing - Boolean (true)
* accessLog - :py:class:`AccessLogAttribute` instance
* connectionDraining - :py:class:`ConnectionDrainingAttribute` instance
:type value: string
:param value: The new value for the attribute
@@ -415,6 +431,11 @@ class ELBConnection(AWSQueryConnection):
value.s3_bucket_prefix
params['LoadBalancerAttributes.AccessLog.EmitInterval'] = \
value.emit_interval
elif attribute.lower() == 'connectiondraining':
params['LoadBalancerAttributes.ConnectionDraining.Enabled'] = \
value.enabled and 'true' or 'false'
params['LoadBalancerAttributes.ConnectionDraining.Timeout'] = \
value.timeout
else:
raise ValueError('InvalidAttribute', attribute)
return self.get_status('ModifyLoadBalancerAttributes', params,
@@ -445,14 +466,21 @@ class ELBConnection(AWSQueryConnection):
:type attribute: string
:param attribute: The attribute you wish to see.
* accessLog - :py:class:`AccessLogAttribute` instance
* crossZoneLoadBalancing - Boolean
* connectionDraining - :py:class:`ConnectionDrainingAttribute`
instance
:rtype: Attribute dependent
:return: The new value for the attribute
"""
attributes = self.get_all_lb_attributes(load_balancer_name)
if attribute.lower() == 'accesslog':
return attributes.access_log
if attribute.lower() == 'crosszoneloadbalancing':
return attributes.cross_zone_load_balancing.enabled
if attribute.lower() == 'connectiondraining':
return attributes.connection_draining
return None
def register_instances(self, load_balancer_name, instances):
@@ -601,17 +629,19 @@ class ELBConnection(AWSQueryConnection):
params['CookieExpirationPeriod'] = cookie_expiration_period
return self.get_status('CreateLBCookieStickinessPolicy', params)
def create_lb_policy(self, lb_name, policy_name, policy_type, policy_attributes):
def create_lb_policy(self, lb_name, policy_name, policy_type,
policy_attributes):
"""
Creates a new policy that contais the necessary attributes depending on
the policy type. Policies are settings that are saved for your load
balancer and that can be applied to the front-end listener, or
the back-end application server.
Creates a new policy that contains the necessary attributes
depending on the policy type. Policies are settings that are
saved for your load balancer and that can be applied to the
front-end listener, or the back-end application server.
"""
params = {'LoadBalancerName': lb_name,
'PolicyName': policy_name,
'PolicyTypeName': policy_type}
for index, (name, value) in enumerate(policy_attributes.iteritems(), 1):
for index, (name, value) in enumerate(six.iteritems(policy_attributes), 1):
params['PolicyAttributes.member.%d.AttributeName' % index] = name
params['PolicyAttributes.member.%d.AttributeValue' % index] = value
else:
@@ -635,10 +665,14 @@ class ELBConnection(AWSQueryConnection):
"""
params = {'LoadBalancerName': lb_name,
'LoadBalancerPort': lb_port}
self.build_list_params(params, policies, 'PolicyNames.member.%d')
if len(policies):
self.build_list_params(params, policies, 'PolicyNames.member.%d')
else:
params['PolicyNames'] = ''
return self.get_status('SetLoadBalancerPoliciesOfListener', params)
def set_lb_policies_of_backend_server(self, lb_name, instance_port, policies):
def set_lb_policies_of_backend_server(self, lb_name, instance_port,
policies):
"""
Replaces the current set of policies associated with a port on which
the back-end server is listening with a new set of policies.
@@ -649,7 +683,8 @@ class ELBConnection(AWSQueryConnection):
self.build_list_params(params, policies, 'PolicyNames.member.%d')
else:
params['PolicyNames'] = ''
return self.get_status('SetLoadBalancerPoliciesForBackendServer', params)
return self.get_status('SetLoadBalancerPoliciesForBackendServer',
params)
def apply_security_groups_to_lb(self, name, security_groups):
"""

View File

@@ -74,6 +74,31 @@ class AccessLogAttribute(object):
elif name == 'EmitInterval':
self.emit_interval = int(value)
class ConnectionDrainingAttribute(object):
"""
Represents the ConnectionDraining segment of ELB attributes.
"""
def __init__(self, connection=None):
self.enabled = None
self.timeout = None
def __repr__(self):
return 'ConnectionDraining(%s, %s)' % (
self.enabled,
self.timeout
)
def startElement(self, name, attrs, connection):
pass
def endElement(self, name, value, connection):
if name == 'Enabled':
if value.lower() == 'true':
self.enabled = True
else:
self.enabled = False
elif name == 'Timeout':
self.timeout = int(value)
class LbAttributes(object):
"""
@@ -84,17 +109,21 @@ class LbAttributes(object):
self.cross_zone_load_balancing = CrossZoneLoadBalancingAttribute(
self.connection)
self.access_log = AccessLogAttribute(self.connection)
self.connection_draining = ConnectionDrainingAttribute(self.connection)
def __repr__(self):
return 'LbAttributes(%s, %s)' % (
return 'LbAttributes(%s, %s, %s)' % (
repr(self.cross_zone_load_balancing),
repr(self.access_log))
repr(self.access_log),
repr(self.connection_draining))
def startElement(self, name, attrs, connection):
if name == 'CrossZoneLoadBalancing':
return self.cross_zone_load_balancing
if name == 'AccessLog':
return self.access_log
if name == 'ConnectionDraining':
return self.connection_draining
def endElement(self, name, value, connection):
pass

View File

@@ -27,6 +27,7 @@ from boto.ec2.elb.policies import Policies, OtherPolicy
from boto.ec2.elb.securitygroup import SecurityGroup
from boto.ec2.instanceinfo import InstanceInfo
from boto.resultset import ResultSet
from boto.compat import six
class Backend(object):
@@ -67,6 +68,7 @@ class LoadBalancerZones(object):
def endElement(self, name, value, connection):
pass
class LoadBalancer(object):
"""
Represents an EC2 Load Balancer.
@@ -82,6 +84,7 @@ class LoadBalancer(object):
check policy for this load balancer.
:ivar boto.ec2.elb.policies.Policies policies: Cookie stickiness and
other policies.
:ivar str name: The name of the Load Balancer.
:ivar str dns_name: The external DNS name for the balancer.
:ivar str created_time: A date+time string showing when the
load balancer was created.
@@ -186,7 +189,7 @@ class LoadBalancer(object):
:param zones: The name of the zone(s) to add.
"""
if isinstance(zones, basestring):
if isinstance(zones, six.string_types):
zones = [zones]
new_zones = self.connection.enable_availability_zones(self.name, zones)
self.availability_zones = new_zones
@@ -199,9 +202,10 @@ class LoadBalancer(object):
:param zones: The name of the zone(s) to add.
"""
if isinstance(zones, basestring):
if isinstance(zones, six.string_types):
zones = [zones]
new_zones = self.connection.disable_availability_zones(self.name, zones)
new_zones = self.connection.disable_availability_zones(
self.name, zones)
self.availability_zones = new_zones
def get_attributes(self, force=False):
@@ -266,7 +270,7 @@ class LoadBalancer(object):
to add to this load balancer.
"""
if isinstance(instances, basestring):
if isinstance(instances, six.string_types):
instances = [instances]
new_instances = self.connection.register_instances(self.name,
instances)
@@ -281,7 +285,7 @@ class LoadBalancer(object):
to remove from this load balancer.
"""
if isinstance(instances, basestring):
if isinstance(instances, six.string_types):
instances = [instances]
new_instances = self.connection.deregister_instances(self.name,
instances)
@@ -348,14 +352,13 @@ class LoadBalancer(object):
policies)
def set_policies_of_backend_server(self, instance_port, policies):
return self.connection.set_lb_policies_of_backend_server(self.name,
instance_port,
policies)
return self.connection.set_lb_policies_of_backend_server(
self.name, instance_port, policies)
def create_cookie_stickiness_policy(self, cookie_expiration_period,
policy_name):
return self.connection.create_lb_cookie_stickiness_policy(cookie_expiration_period, self.name, policy_name)
return self.connection.create_lb_cookie_stickiness_policy(
cookie_expiration_period, self.name, policy_name)
def create_app_cookie_stickiness_policy(self, name, policy_name):
return self.connection.create_app_cookie_stickiness_policy(name,
@@ -363,12 +366,12 @@ class LoadBalancer(object):
policy_name)
def set_listener_SSL_certificate(self, lb_port, ssl_certificate_id):
return self.connection.set_lb_listener_SSL_certificate(self.name,
lb_port,
ssl_certificate_id)
return self.connection.set_lb_listener_SSL_certificate(
self.name, lb_port, ssl_certificate_id)
def create_lb_policy(self, policy_name, policy_type, policy_attribute):
return self.connection.create_lb_policy(self.name, policy_name, policy_type, policy_attribute)
return self.connection.create_lb_policy(
self.name, policy_name, policy_type, policy_attribute)
def attach_subnets(self, subnets):
"""
@@ -380,7 +383,7 @@ class LoadBalancer(object):
:param subnets: The name of the subnet(s) to add.
"""
if isinstance(subnets, basestring):
if isinstance(subnets, six.string_types):
subnets = [subnets]
new_subnets = self.connection.attach_lb_to_subnets(self.name, subnets)
self.subnets = new_subnets
@@ -393,9 +396,10 @@ class LoadBalancer(object):
:param subnets: The name of the subnet(s) to detach.
"""
if isinstance(subnets, basestring):
if isinstance(subnets, six.string_types):
subnets = [subnets]
new_subnets = self.connection.detach_lb_from_subnets(self.name, subnets)
new_subnets = self.connection.detach_lb_from_subnets(
self.name, subnets)
self.subnets = new_subnets
def apply_security_groups(self, security_groups):
@@ -408,8 +412,8 @@ class LoadBalancer(object):
:param security_groups: The name of the security group(s) to add.
"""
if isinstance(security_groups, basestring):
if isinstance(security_groups, six.string_types):
security_groups = [security_groups]
new_sgs = self.connection.apply_security_groups_to_lb(
self.name, security_groups)
self.name, security_groups)
self.security_groups = new_sgs

View File

@@ -233,6 +233,9 @@ class Image(TaggedEC2Object):
* i2.2xlarge
* i2.4xlarge
* i2.8xlarge
* t2.micro
* t2.small
* t2.medium
:type placement: string
:param placement: The Availability Zone to launch the instance into.

View File

@@ -83,7 +83,7 @@ class KeyPair(EC2Object):
fp = open(file_path, 'wb')
fp.write(self.material)
fp.close()
os.chmod(file_path, 0600)
os.chmod(file_path, 0o600)
return True
else:
raise BotoClientError('KeyPair contains no material')

View File

@@ -167,6 +167,70 @@ class NetworkInterface(TaggedEC2Object):
else:
setattr(self, name, value)
def _update(self, updated):
self.__dict__.update(updated.__dict__)
def update(self, validate=False, dry_run=False):
"""
Update the data associated with this ENI by querying EC2.
:type validate: bool
:param validate: By default, if EC2 returns no data about the
ENI the update method returns quietly. If
the validate param is True, however, it will
raise a ValueError exception if no data is
returned from EC2.
"""
rs = self.connection.get_all_network_interfaces(
[self.id],
dry_run=dry_run
)
if len(rs) > 0:
self._update(rs[0])
elif validate:
raise ValueError('%s is not a valid ENI ID' % self.id)
return self.status
def attach(self, instance_id, device_index, dry_run=False):
"""
Attach this ENI to an EC2 instance.
:type instance_id: str
:param instance_id: The ID of the EC2 instance to which it will
be attached.
:type device_index: int
:param device_index: The interface nunber, N, on the instance (eg. ethN)
:rtype: bool
:return: True if successful
"""
return self.connection.attach_network_interface(
self.id,
instance_id,
device_index,
dry_run=dry_run
)
def detach(self, force=False, dry_run=False):
"""
Detach this ENI from an EC2 instance.
:type force: bool
:param force: Forces detachment if the previous detachment
attempt did not occur cleanly.
:rtype: bool
:return: True if successful
"""
attachment_id = getattr(self.attachment, 'id', None)
return self.connection.detach_network_interface(
attachment_id,
force,
dry_run=dry_run
)
def delete(self, dry_run=False):
return self.connection.delete_network_interface(
self.id,

View File

@@ -18,7 +18,6 @@
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
from boto.resultset import ResultSet
from boto.ec2.ec2object import EC2Object
from boto.utils import parse_ts
@@ -82,13 +81,13 @@ class ReservedInstancesOffering(EC2Object):
self.marketplace = True if value == 'true' else False
def describe(self):
print 'ID=%s' % self.id
print '\tInstance Type=%s' % self.instance_type
print '\tZone=%s' % self.availability_zone
print '\tDuration=%s' % self.duration
print '\tFixed Price=%s' % self.fixed_price
print '\tUsage Price=%s' % self.usage_price
print '\tDescription=%s' % self.description
print('ID=%s' % self.id)
print('\tInstance Type=%s' % self.instance_type)
print('\tZone=%s' % self.availability_zone)
print('\tDuration=%s' % self.duration)
print('\tFixed Price=%s' % self.fixed_price)
print('\tUsage Price=%s' % self.usage_price)
print('\tDescription=%s' % self.description)
def purchase(self, instance_count=1, dry_run=False):
return self.connection.purchase_reserved_instance_offering(

View File

@@ -41,6 +41,7 @@ class Snapshot(TaggedEC2Object):
self.owner_alias = None
self.volume_size = None
self.description = None
self.encrypted = None
def __repr__(self):
return 'Snapshot:%s' % self.id
@@ -65,6 +66,8 @@ class Snapshot(TaggedEC2Object):
self.volume_size = value
elif name == 'description':
self.description = value
elif name == 'encrypted':
self.encrypted = (value.lower() == 'true')
else:
setattr(self, name, value)
@@ -152,6 +155,7 @@ class Snapshot(TaggedEC2Object):
self.id,
volume_type,
iops,
self.encrypted,
dry_run=dry_run
)

View File

@@ -44,6 +44,7 @@ class Volume(TaggedEC2Object):
:ivar type: The type of volume (standard or consistent-iops)
:ivar iops: If this volume is of type consistent-iops, this is
the number of IOPS provisioned (10-300).
:ivar encrypted: True if this volume is encrypted.
"""
def __init__(self, connection=None):
@@ -57,6 +58,7 @@ class Volume(TaggedEC2Object):
self.zone = None
self.type = None
self.iops = None
self.encrypted = None
def __repr__(self):
return 'Volume:%s' % self.id
@@ -92,6 +94,8 @@ class Volume(TaggedEC2Object):
self.type = value
elif name == 'iops':
self.iops = int(value)
elif name == 'encrypted':
self.encrypted = (value.lower() == 'true')
else:
setattr(self, name, value)