Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' of ssh://github.com/boto/boto
Browse files Browse the repository at this point in the history
  • Loading branch information
kopertop committed Jan 13, 2012
2 parents 937e25e + 2d2510e commit 73d721a
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 105 deletions.
4 changes: 2 additions & 2 deletions boto/ec2/cloudwatch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@

from boto.connection import AWSQueryConnection
from boto.ec2.cloudwatch.metric import Metric
from boto.ec2.cloudwatch.alarm import MetricAlarm, AlarmHistoryItem
from boto.ec2.cloudwatch.alarm import MetricAlarm, MetricAlarms, AlarmHistoryItem
from boto.ec2.cloudwatch.datapoint import Datapoint
from boto.regioninfo import RegionInfo
import boto
Expand Down Expand Up @@ -478,7 +478,7 @@ def describe_alarms(self, action_prefix=None, alarm_name_prefix=None,
if state_value:
params['StateValue'] = state_value
return self.get_list('DescribeAlarms', params,
[('member', MetricAlarm)])
[('MetricAlarms', MetricAlarms)])[0]

def describe_alarm_history(self, alarm_name=None,
start_date=None, end_date=None,
Expand Down
24 changes: 24 additions & 0 deletions boto/ec2/cloudwatch/alarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,32 @@
from datetime import datetime
from boto.resultset import ResultSet
from boto.ec2.cloudwatch.listelement import ListElement
from boto.ec2.cloudwatch.dimension import Dimension

try:
import simplejson as json
except ImportError:
import json


class MetricAlarms(list):
def __init__(self, connection=None):
"""
Parses a list of MetricAlarms.
"""
list.__init__(self)
self.connection = connection

def startElement(self, name, attrs, connection):
if name == 'member':
metric_alarm = MetricAlarm(connection)
self.append(metric_alarm)
return metric_alarm

def endElement(self, name, value, connection):
pass


class MetricAlarm(object):

OK = 'OK'
Expand Down Expand Up @@ -156,6 +177,9 @@ def startElement(self, name, attrs, connection):
elif name == 'OKActions':
self.ok_actions = ListElement()
return self.ok_actions
elif name == 'Dimensions':
self.dimensions = Dimension()
return self.dimensions
else:
pass

Expand Down
38 changes: 38 additions & 0 deletions boto/ec2/cloudwatch/dimension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#

class Dimension(dict):

def startElement(self, name, attrs, connection):
pass

def endElement(self, name, value, connection):
if name == 'Name':
self._name = value
elif name == 'Value':
if self._name in self:
self[self._name].append(value)
else:
self[self._name] = [value]
else:
setattr(self, name, value)

17 changes: 1 addition & 16 deletions boto/ec2/cloudwatch/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,7 @@
#

from boto.ec2.cloudwatch.alarm import MetricAlarm

class Dimension(dict):

def startElement(self, name, attrs, connection):
pass

def endElement(self, name, value, connection):
if name == 'Name':
self._name = value
elif name == 'Value':
if self._name in self:
self[self._name].append(value)
else:
self[self._name] = [value]
else:
setattr(self, name, value)
from boto.ec2.cloudwatch.dimension import Dimension

class Metric(object):

Expand Down
22 changes: 10 additions & 12 deletions boto/rds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,16 @@ def create_dbinstance(self, id, allocated_storage, instance_class,
:rtype: :class:`boto.rds.dbinstance.DBInstance`
:return: The new db instance.
"""
params = {'DBInstanceIdentifier' : id,
'AllocatedStorage' : allocated_storage,
'DBInstanceClass' : instance_class,
'Engine' : engine,
'MasterUsername' : master_username,
'MasterUserPassword' : master_password}
if port:
params['Port'] = port
params = {'DBInstanceIdentifier': id,
'AllocatedStorage': allocated_storage,
'DBInstanceClass': instance_class,
'Engine': engine,
'MasterUsername': master_username,
'MasterUserPassword': master_password,
'Port': port,
'MultiAZ': str(multi_az).lower(),
'AutoMinorVersionUpgrade':
str(auto_minor_version_upgrade).lower()}
if db_name:
params['DBName'] = db_name
if param_group:
Expand All @@ -261,12 +263,8 @@ def create_dbinstance(self, id, allocated_storage, instance_class,
params['BackupRetentionPeriod'] = backup_retention_period
if preferred_backup_window:
params['PreferredBackupWindow'] = preferred_backup_window
if multi_az:
params['MultiAZ'] = 'true'
if engine_version:
params['EngineVersion'] = engine_version
if auto_minor_version_upgrade is False:
params['AutoMinorVersionUpgrade'] = 'false'

return self.get_object('CreateDBInstance', params, DBInstance)

Expand Down
119 changes: 70 additions & 49 deletions boto/s3/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from boto.s3.multipart import MultiPartUpload
from boto.s3.multipart import CompleteMultiPartUpload
from boto.s3.multidelete import MultiDeleteResult
from boto.s3.multidelete import Error
from boto.s3.bucketlistresultset import BucketListResultSet
from boto.s3.bucketlistresultset import VersionedBucketListResultSet
from boto.s3.bucketlistresultset import MultiPartUploadListResultSet
Expand Down Expand Up @@ -462,8 +463,8 @@ def delete_keys(self, keys, quiet=False, mfa_token=None, headers=None):
"""
Deletes a set of keys using S3's Multi-object delete API. If a
VersionID is specified for that key then that version is removed.
Returns the XML response from S3, which contains Deleted and Error
elements for each key you ask to delete.
Returns a MultiDeleteResult Object, which contains Deleted
and Error elements for each key you ask to delete.
:type keys: list
:param keys: A list of either key_names or (key_name, versionid) pairs
Expand All @@ -482,56 +483,76 @@ def delete_keys(self, keys, quiet=False, mfa_token=None, headers=None):
This value is required anytime you are
deleting versioned objects from a bucket
that has the MFADelete option on the bucket.
:returns: An instance of MultiDeleteResult
"""
if len(keys) > 1000:
raise BotoClientError('Max of 1000 keys can be deleted')
headers = headers or {}
query_args = 'delete'
ikeys = iter(keys)
result = MultiDeleteResult(self)
provider = self.connection.provider
data = """<?xml version="1.0" encoding="UTF-8"?>"""
data += "<Delete>"
if quiet:
data += "<Quiet>true</Quiet>"
skipped = []
for key in keys:
if isinstance(key, basestring):
key_name = key
version_id = None
elif isinstance(key, tuple) and len(tuple) == 2:
key_name, version_id = key
elif isinstance(key, Key) or isinstance(key, DeleteMarker):
key_name = key.name
version_id = key.version_id
else:
skipped.append(key)
continue
data += "<Object><Key>%s</Key>" % xml.sax.saxutils.escape(key_name)
if version_id:
data += "<VersionId>%s</VersionId>"
data += "</Object>"
data += "</Delete>"
if isinstance(data, unicode):
query_args = 'delete'
def delete_keys2(hdrs):
hdrs = hdrs or {}
data = u"""<?xml version="1.0" encoding="UTF-8"?>"""
data += u"<Delete>"
if quiet:
data += u"<Quiet>true</Quiet>"
count = 0
while count < 1000:
try:
key = ikeys.next()
except StopIteration:
break
if isinstance(key, basestring):
key_name = key
version_id = None
elif isinstance(key, tuple) and len(key) == 2:
key_name, version_id = key
elif (isinstance(key, Key) or isinstance(key, DeleteMarker)) and key.name:
key_name = key.name
version_id = key.version_id
else:
if isinstance(key, Prefix):
key_name = key.name
code = 'PrefixSkipped' # Don't delete Prefix
else:
key_name = repr(key) # try get a string
code = 'InvalidArgument' # other unknown type
message = 'Invalid. No delete action taken for this object.'
error = Error(key_name, code=code, message=message)
result.errors.append(error)
continue
count += 1
#key_name = key_name.decode('utf-8')
data += u"<Object><Key>%s</Key>" % xml.sax.saxutils.escape(key_name)
if version_id:
data += u"<VersionId>%s</VersionId>" % version_id
data += u"</Object>"
data += u"</Delete>"
if count <= 0:
return False # no more
data = data.encode('utf-8')
fp = StringIO.StringIO(data)
md5 = boto.utils.compute_md5(fp)
headers['Content-MD5'] = md5[1]
headers['Content-Type'] = 'text/xml'
if mfa_token:
headers[provider.mfa_header] = ' '.join(mfa_token)
response = self.connection.make_request('POST', self.name,
headers=headers,
query_args=query_args,
data=data)
body = response.read()
if response.status == 200:
result = MultiDeleteResult(self)
h = handler.XmlHandler(result, self)
xml.sax.parseString(body, h)
return result
else:
raise provider.storage_response_error(response.status,
response.reason,
body)
fp = StringIO.StringIO(data)
md5 = boto.utils.compute_md5(fp)
hdrs['Content-MD5'] = md5[1]
hdrs['Content-Type'] = 'text/xml'
if mfa_token:
hdrs[provider.mfa_header] = ' '.join(mfa_token)
response = self.connection.make_request('POST', self.name,
headers=hdrs,
query_args=query_args,
data=data)
body = response.read()
if response.status == 200:
h = handler.XmlHandler(result, self)
xml.sax.parseString(body, h)
return count >= 1000 # more?
else:
raise provider.storage_response_error(response.status,
response.reason,
body)
while delete_keys2(headers):
pass
return result

def delete_key(self, key_name, headers=None,
version_id=None, mfa_token=None):
Expand Down
3 changes: 2 additions & 1 deletion boto/s3/deletemarker.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class DeleteMarker:
def __init__(self, bucket=None, name=None):
self.bucket = bucket
self.name = name
self.version_id = None
self.is_latest = False
self.last_modified = None
self.owner = None
Expand All @@ -38,7 +39,7 @@ def startElement(self, name, attrs, connection):

def endElement(self, name, value, connection):
if name == 'Key':
self.name = value.encode('utf-8')
self.name = value
elif name == 'IsLatest':
if value == 'true':
self.is_latest = True
Expand Down
2 changes: 1 addition & 1 deletion boto/s3/key.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def startElement(self, name, attrs, connection):

def endElement(self, name, value, connection):
if name == 'Key':
self.name = value.encode('utf-8')
self.name = value
elif name == 'ETag':
self.etag = value
elif name == 'LastModified':
Expand Down
10 changes: 4 additions & 6 deletions boto/s3/multidelete.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,11 @@ def startElement(self, name, attrs, connection):
self.deleted.append(d)
return d
elif name == 'Error':
d = Error()
self.deleted.append(d)
return d
e = Error()
self.errors.append(e)
return e
return None

def endElement(self, name, value, connection):
setattr(self, name, value)




Loading

0 comments on commit 73d721a

Please sign in to comment.