Permalink
Browse files

Merge remote branch 'boto/master'

Conflicts:
	boto/ec2/connection.py
  • Loading branch information...
2 parents 4c76ccf + 9967ff1 commit b19803368a8581a2726df1f7241aea6c3427853b @KonishchevDmitry KonishchevDmitry committed Feb 9, 2011
View
@@ -1,4 +1,4 @@
*.pyc
.*.swp
*.log
-
+boto.egg-info
View
@@ -16,7 +16,8 @@ HEADERS = {
'State': {'get': attrgetter('state'), 'length':15},
'Image': {'get': attrgetter('image_id'), 'length':15},
'Type': {'get': attrgetter('instance_type'), 'length':15},
- 'IP': {'get': attrgetter('ip_address'), 'length':15},
+ 'IP': {'get': attrgetter('ip_address'), 'length':16},
+ 'PrivateIP': {'get': attrgetter('private_ip_address'), 'length':16},
'Key': {'get': attrgetter('key_name'), 'length':25},
'T:': {'length': 30},
}
View
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+# Author: Chris Moyer
+#
+# route53 is similar to sdbadmin for Route53, it's a simple
+# console utility to perform the most frequent tasks with Route53
+
+def _print_zone_info(zoneinfo):
+ print "="*80
+ print "| ID: %s" % zoneinfo['Id'].split("/")[-1]
+ print "| Name: %s" % zoneinfo['Name']
+ print "| Ref: %s" % zoneinfo['CallerReference']
+ print "="*80
+ print zoneinfo['Config']
+ print
+
+
+def create(conn, hostname, caller_reference=None, comment=''):
+ """Create a hosted zone, returning the nameservers"""
+ response = conn.create_hosted_zone(hostname, caller_reference, comment)
+ print "Pending, please add the following Name Servers:"
+ for ns in response.NameServers:
+ print "\t", ns
+
+def delete_zone(conn, hosted_zone_id):
+ """Delete a hosted zone by ID"""
+ response = conn.delete_hosted_zone(hosted_zone_id)
+ print response
+
+def ls(conn):
+ """List all hosted zones"""
+ response = conn.get_all_hosted_zones()
+ for zoneinfo in response['ListHostedZonesResponse']['HostedZones']:
+ _print_zone_info(zoneinfo)
+
+def get(conn, hosted_zone_id, type=None, name=None, maxitems=None):
+ """Get all the records for a single zone"""
+ response = conn.get_all_rrsets(hosted_zone_id, type, name, maxitems=maxitems)
+ print '%-20s %-20s %-20s %s' % ("Name", "Type", "TTL", "Value(s)")
+ for record in response:
+ print '%-20s %-20s %-20s %s' % (record.name, record.type, record.ttl, ",".join(record.resource_records))
+
+
+def add_record(conn, hosted_zone_id, name, type, value, ttl=600, comment=""):
+ """Add a new record to a zone"""
+ from boto.route53.record import ResourceRecordSets
+ changes = ResourceRecordSets(conn, hosted_zone_id, comment)
+ change = changes.add_change("CREATE", name, type, ttl)
+ change.add_value(value)
+ print changes.commit()
+
+def help(conn, fnc=None):
+ """Prints this help message"""
+ import inspect
+ self = sys.modules['__main__']
+ if fnc:
+ try:
+ cmd = getattr(self, fnc)
+ except:
+ cmd = None
+ if not inspect.isfunction(cmd):
+ print "No function named: %s found" % fnc
+ sys.exit(2)
+ (args, varargs, varkw, defaults) = inspect.getargspec(cmd)
+ print cmd.__doc__
+ print "Usage: %s %s" % (fnc, " ".join([ "[%s]" % a for a in args[1:]]))
+ else:
+ print "Usage: route53 [command]"
+ for cname in dir(self):
+ if not cname.startswith("_"):
+ cmd = getattr(self, cname)
+ if inspect.isfunction(cmd):
+ doc = cmd.__doc__
+ print "\t%s - %s" % (cname, doc)
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ import boto
+ import sys
+ conn = boto.connect_route53()
+ self = sys.modules['__main__']
+ if len(sys.argv) >= 2:
+ try:
+ cmd = getattr(self, sys.argv[1])
+ except:
+ cmd = None
+ args = sys.argv[2:]
+ else:
+ cmd = help
+ args = []
+ if not cmd:
+ cmd = help
+ try:
+ cmd(conn, *args)
+ except TypeError, e:
+ print e
+ help(conn, cmd.__name__)
View
@@ -369,6 +369,20 @@ def connect_walrus(host, aws_access_key_id=None, aws_secret_access_key=None,
calling_format=OrdinaryCallingFormat(),
is_secure=is_secure, **kwargs)
+def connect_ses(aws_access_key_id=None, aws_secret_access_key=None, **kwargs):
+ """
+ :type aws_access_key_id: string
+ :param aws_access_key_id: Your AWS Access Key ID
+
+ :type aws_secret_access_key: string
+ :param aws_secret_access_key: Your AWS Secret Access Key
+
+ :rtype: :class:`boto.ses.SESConnection`
+ :return: A connection to Amazon's SES
+ """
+ from boto.ses import SESConnection
+ return SESConnection(aws_access_key_id, aws_secret_access_key, **kwargs)
+
def check_extensions(module_name, module_path):
"""
This function checks for extensions to boto modules. It should be called in the
View
@@ -106,7 +106,7 @@ def __init__(self, host, config, provider):
HmacKeys.__init__(self, host, config, provider)
self._hmac_256 = None
- def add_auth(self, http_request):
+ def add_auth(self, http_request, **kwargs):
headers = http_request.headers
method = http_request.method
auth_path = http_request.auth_path
@@ -133,7 +133,7 @@ def __init__(self, host, config, provider):
HmacKeys.__init__(self, host, config, provider)
self._hmac_256 = None
- def add_auth(self, http_request):
+ def add_auth(self, http_request, **kwargs):
headers = http_request.headers
if not headers.has_key('Date'):
headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
@@ -148,13 +148,13 @@ def add_auth(self, http_request):
class HmacAuthV3Handler(AuthHandler, HmacKeys):
"""Implements the new Version 3 HMAC authorization used by Route53."""
- capability = ['hmac-v3', 'route53']
+ capability = ['hmac-v3', 'route53', 'ses']
def __init__(self, host, config, provider):
AuthHandler.__init__(self, host, config, provider)
HmacKeys.__init__(self, host, config, provider)
- def add_auth(self, http_request):
+ def add_auth(self, http_request, **kwargs):
headers = http_request.headers
if not headers.has_key('Date'):
headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
@@ -171,16 +171,15 @@ class QuerySignatureHelper(HmacKeys):
Concrete sub class need to implement _calc_sigature method.
"""
- def add_auth(self, http_request):
- server_name = self._server_name(http_request.host, http_request.port)
+ def add_auth(self, http_request, **kwargs):
headers = http_request.headers
params = http_request.params
params['AWSAccessKeyId'] = self._provider.access_key
params['SignatureVersion'] = self.SignatureVersion
- params['Timestamp'] = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
+ params['Timestamp'] = boto.utils.get_ts()
qs, signature = self._calc_signature(
http_request.params, http_request.method,
- http_request.path, server_name)
+ http_request.path, http_request.host)
boto.log.debug('query_string: %s Signature: %s' % (qs, signature))
if http_request.method == 'POST':
headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
@@ -192,23 +191,6 @@ def add_auth(self, http_request):
# in request.
http_request.params = {}
- def _server_name(self, host, port):
- if port == 80:
- signature_host = host
- else:
- # This unfortunate little hack can be attributed to
- # a difference in the 2.6 version of httplib. In old
- # versions, it would append ":443" to the hostname sent
- # in the Host header and so we needed to make sure we
- # did the same when calculating the V2 signature. In 2.6
- # (and higher!)
- # it no longer does that. Hence, this kludge.
- if sys.version[:3] in ('2.6', '2.7') and port == 443:
- signature_host = host
- else:
- signature_host = '%s:%d' % (host, port)
- return signature_host
-
class QuerySignatureV0AuthHandler(QuerySignatureHelper, AuthHandler):
"""Class SQS query signature based Auth handler."""
@@ -160,7 +160,7 @@ def endElement(self, name, value, connection):
if value.lower() == 'true':
self.enabled = True
else:
- self.enabledFalse
+ self.enabled = False
elif name == 'CallerReference':
self.caller_reference = value
elif name == 'DefaultRootObject':
View
@@ -342,7 +342,7 @@ def new_http_connection(self, host, is_secure):
else:
connection = httplib.HTTPSConnection(host)
else:
- boto.log.debug('establishing HTTPS connection')
+ boto.log.debug('establishing HTTP connection')
connection = httplib.HTTPConnection(host)
if self.debug > 1:
connection.set_debuglevel(self.debug)
@@ -484,30 +484,36 @@ def _mexe(self, method, path, data, headers, host=None, sender=None,
raise BotoClientError('Please report this exception as a Boto Issue!')
def build_base_http_request(self, method, path, auth_path,
- headers=None, data='', host=None):
+ params=None, headers=None, data='', host=None):
path = self.get_path(path)
+ if auth_path is not None:
+ auth_path = self.get_path(auth_path)
+ if params == None:
+ params = {}
+ else:
+ params = params.copy()
if headers == None:
headers = {}
else:
headers = headers.copy()
host = host or self.host
- return HTTPRequest(method, self.protocol, host, self.port, path, auth_path,
- {}, headers, data)
-
- def fill_in_auth(self, http_request):
- headers = http_request.headers
if self.use_proxy:
path = self.prefix_proxy_to_path(path, host)
if self.proxy_user and self.proxy_pass and not self.is_secure:
# If is_secure, we don't have to set the proxy authentication
# header here, we did that in the CONNECT to the proxy.
headers.update(self.get_proxy_auth_header())
+ return HTTPRequest(method, self.protocol, host, self.port,
+ path, auth_path, params, headers, data)
+
+ def fill_in_auth(self, http_request, **kwargs):
+ headers = http_request.headers
for key in headers:
val = headers[key]
if isinstance(val, unicode):
headers[key] = urllib.quote_plus(val.encode('utf-8'))
- self._auth_handler.add_auth(http_request)
+ self._auth_handler.add_auth(http_request, **kwargs)
headers['User-Agent'] = UserAgent
if not headers.has_key('Content-Length'):
@@ -524,7 +530,7 @@ def make_request(self, method, path, headers=None, data='', host=None,
auth_path=None, sender=None, override_num_retries=None):
"""Makes a request to the server, with stock multiple-retry logic."""
http_request = self.build_base_http_request(method, path, auth_path,
- headers, data, host)
+ {}, headers, data, host)
http_request = self.fill_in_auth(http_request)
return self._send_http_request(http_request, sender,
override_num_retries)
@@ -556,8 +562,9 @@ def get_utf8_value(self, value):
return boto.utils.get_utf8_value(value)
def make_request(self, action, params=None, path='/', verb='GET'):
- http_request = HTTPRequest(verb, self.protocol, self.host, self.port,
- self.get_path(path), None, params, {}, '')
+ http_request = self.build_base_http_request(verb, path, None,
+ params, {}, '',
+ self.server_name())
http_request.params['Action'] = action
http_request.params['Version'] = self.APIVersion
http_request = self.fill_in_auth(http_request)
@@ -213,3 +213,32 @@ def terminate_instance(self, instance_id, decrement_capacity=True):
return self.get_object('TerminateInstanceInAutoScalingGroup', params,
Activity)
+ def set_instance_health(self, instance_id, health_status,
+ should_respect_grace_period=True):
+ """
+ Explicitly set the health status of an instance.
+
+ :type instance_id: str
+ :param instance_id: The identifier of the EC2 instance.
+
+ :type health_status: str
+ :param health_status: The health status of the instance.
+ "Healthy" means that the instance is
+ healthy and should remain in service.
+ "Unhealthy" means that the instance is
+ unhealthy. Auto Scaling should terminate
+ and replace it.
+
+ :type should_respect_grace_period: bool
+ :param should_respect_grace_period: If True, this call should
+ respect the grace period
+ associated with the group.
+ """
+ params = {'InstanceId' : instance_id,
+ 'HealthStatus' : health_status}
+ if should_respect_grace_period:
+ params['ShouldRespectGracePeriod'] = 'true'
+ else:
+ params['ShouldRespectGracePeriod'] = 'false'
+ return self.get_status('SetInstanceHealth', params)
+
Oops, something went wrong.

0 comments on commit b198033

Please sign in to comment.