## Amazon SimpleDB library ## Author: Michal Ludvig <michal@logix.cz> ## http://www.logix.cz/michal ## License: GPL Version 2 """ Low-level class for working with Amazon SimpleDB """ import time import urllib import base64 import hmac import sha import httplib from logging import debug, info, warning, error from Utils import convertTupleListToDict from SortedDict import SortedDict from Exceptions import * class SimpleDB(object): # API Version # See http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/ Version = "2007-11-07" SignatureVersion = 1 def __init__(self, config): self.config = config def ListDomains(self, MaxNumberOfDomains = 100): ''' Lists all domains associated with our Access Key. Returns domain names up to the limit set by MaxNumberOfDomains. ''' parameters = SortedDict() parameters['MaxNumberOfDomains'] = MaxNumberOfDomains response = self.send_request("ListDomains", domain = None, parameters = parameters) return response def send_request(self, *args, **kwargs): request = self.create_request(*args, **kwargs) debug("Request: %s" % repr(request)) conn = self.get_connection() conn.request("GET", self.format_uri(request['uri_params'])) http_response = conn.getresponse() response = {} response["status"] = http_response.status response["reason"] = http_response.reason response["headers"] = convertTupleListToDict(http_response.getheaders()) response["data"] = http_response.read() debug("Response: " + str(response)) conn.close() if response["status"] < 200 or response["status"] > 299: raise S3Error(response) return response def create_request(self, action, domain, parameters = None): if not parameters: parameters = SortedDict() parameters['AWSAccessKeyId'] = self.config.access_key parameters['Version'] = self.Version parameters['SignatureVersion'] = self.SignatureVersion parameters['Action'] = action parameters['Timestamp'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) if domain: parameters['DomainName'] = domain parameters['Signature'] = self.sign_request(parameters) parameters.keys_return_lowercase = False uri_params = urllib.urlencode(parameters) request = {} request['uri_params'] = uri_params request['parameters'] = parameters return request def sign_request(self, parameters): h = "" parameters.keys_sort_lowercase = True parameters.keys_return_lowercase = False for key in parameters: h += "%s%s" % (key, parameters[key]) debug("SignRequest: %s" % h) return base64.encodestring(hmac.new(self.config.secret_key, h, sha).digest()).strip() def get_connection(self): if self.config.proxy_host != "": return httplib.HTTPConnection(self.config.proxy_host, self.config.proxy_port) else: if self.config.use_https: return httplib.HTTPSConnection(self.config.simpledb_host) else: return httplib.HTTPConnection(self.config.simpledb_host) def format_uri(self, uri_params): if self.config.proxy_host != "": uri = "http://%s/?%s" % (self.config.simpledb_host, uri_params) else: uri = "/?%s" % uri_params debug('format_uri(): ' + uri) return uri