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

Side by Side Diff: boto/utils.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, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « boto/tests/test_sqsconnection.py ('k') | boto/vpc/__init__.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
2 # Copyright (c) 2010, Eucalyptus Systems, Inc. 2 # Copyright (c) 2010, Eucalyptus Systems, Inc.
3 # All rights reserved. 3 # All rights reserved.
4 # 4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a 5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the 6 # copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including 7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish, dis- 8 # without limitation the rights to use, copy, modify, merge, publish, dis-
9 # tribute, sublicense, and/or sell copies of the Software, and to permit 9 # tribute, sublicense, and/or sell copies of the Software, and to permit
10 # persons to whom the Software is furnished to do so, subject to the fol- 10 # persons to whom the Software is furnished to do so, subject to the fol-
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 import logging.handlers 47 import logging.handlers
48 import boto 48 import boto
49 import tempfile 49 import tempfile
50 import smtplib 50 import smtplib
51 import datetime 51 import datetime
52 from email.MIMEMultipart import MIMEMultipart 52 from email.MIMEMultipart import MIMEMultipart
53 from email.MIMEBase import MIMEBase 53 from email.MIMEBase import MIMEBase
54 from email.MIMEText import MIMEText 54 from email.MIMEText import MIMEText
55 from email.Utils import formatdate 55 from email.Utils import formatdate
56 from email import Encoders 56 from email import Encoders
57 import gzip
58
57 59
58 try: 60 try:
59 import hashlib 61 import hashlib
60 _hashfn = hashlib.sha512 62 _hashfn = hashlib.sha512
61 except ImportError: 63 except ImportError:
62 import md5 64 import md5
63 _hashfn = md5.md5 65 _hashfn = md5.md5
64 66
65 # List of Query String Arguments of Interest 67 # List of Query String Arguments of Interest
66 qsa_of_interest = ['acl', 'location', 'logging', 'partNumber', 'policy', 68 qsa_of_interest = ['acl', 'location', 'logging', 'partNumber', 'policy',
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return final_headers 144 return final_headers
143 145
144 def get_aws_metadata(headers, provider=None): 146 def get_aws_metadata(headers, provider=None):
145 if not provider: 147 if not provider:
146 provider = boto.provider.get_default() 148 provider = boto.provider.get_default()
147 metadata_prefix = provider.metadata_prefix 149 metadata_prefix = provider.metadata_prefix
148 metadata = {} 150 metadata = {}
149 for hkey in headers.keys(): 151 for hkey in headers.keys():
150 if hkey.lower().startswith(metadata_prefix): 152 if hkey.lower().startswith(metadata_prefix):
151 val = urllib.unquote_plus(headers[hkey]) 153 val = urllib.unquote_plus(headers[hkey])
152 metadata[hkey[len(metadata_prefix):]] = unicode(val, 'utf-8') 154 try:
155 metadata[hkey[len(metadata_prefix):]] = unicode(val, 'utf-8')
156 except UnicodeDecodeError:
157 metadata[hkey[len(metadata_prefix):]] = val
153 del headers[hkey] 158 del headers[hkey]
154 return metadata 159 return metadata
155 160
156 def retry_url(url, retry_on_404=True): 161 def retry_url(url, retry_on_404=True, num_retries=10):
157 for i in range(0, 10): 162 for i in range(0, num_retries):
158 try: 163 try:
159 req = urllib2.Request(url) 164 req = urllib2.Request(url)
160 resp = urllib2.urlopen(req) 165 resp = urllib2.urlopen(req)
161 return resp.read() 166 return resp.read()
162 except urllib2.HTTPError, e: 167 except urllib2.HTTPError, e:
163 # in 2.6 you use getcode(), in 2.5 and earlier you use code 168 # in 2.6 you use getcode(), in 2.5 and earlier you use code
164 if hasattr(e, 'getcode'): 169 if hasattr(e, 'getcode'):
165 code = e.getcode() 170 code = e.getcode()
166 else: 171 else:
167 code = e.code 172 code = e.code
(...skipping 21 matching lines...) Expand all
189 resource = field[0:p] + '/openssh-key' 194 resource = field[0:p] + '/openssh-key'
190 else: 195 else:
191 key = resource = field 196 key = resource = field
192 val = retry_url(url + resource) 197 val = retry_url(url + resource)
193 p = val.find('\n') 198 p = val.find('\n')
194 if p > 0: 199 if p > 0:
195 val = val.split('\n') 200 val = val.split('\n')
196 d[key] = val 201 d[key] = val
197 return d 202 return d
198 203
199 def get_instance_metadata(version='latest'): 204 def get_instance_metadata(version='latest', url='http://169.254.169.254'):
200 """ 205 """
201 Returns the instance metadata as a nested Python dictionary. 206 Returns the instance metadata as a nested Python dictionary.
202 Simple values (e.g. local_hostname, hostname, etc.) will be 207 Simple values (e.g. local_hostname, hostname, etc.) will be
203 stored as string values. Values such as ancestor-ami-ids will 208 stored as string values. Values such as ancestor-ami-ids will
204 be stored in the dict as a list of string values. More complex 209 be stored in the dict as a list of string values. More complex
205 fields such as public-keys and will be stored as nested dicts. 210 fields such as public-keys and will be stored as nested dicts.
206 """ 211 """
207 url = 'http://169.254.169.254/%s/meta-data/' % version 212 return _get_instance_metadata('%s/%s/meta-data/' % (url, version))
208 return _get_instance_metadata(url)
209 213
210 def get_instance_userdata(version='latest', sep=None): 214 def get_instance_userdata(version='latest', sep=None,
211 url = 'http://169.254.169.254/%s/user-data' % version 215 url='http://169.254.169.254'):
212 user_data = retry_url(url, retry_on_404=False) 216 ud_url = '%s/%s/user-data' % (url,version)
217 user_data = retry_url(ud_url, retry_on_404=False)
213 if user_data: 218 if user_data:
214 if sep: 219 if sep:
215 l = user_data.split(sep) 220 l = user_data.split(sep)
216 user_data = {} 221 user_data = {}
217 for nvpair in l: 222 for nvpair in l:
218 t = nvpair.split('=') 223 t = nvpair.split('=')
219 user_data[t[0].strip()] = t[1].strip() 224 user_data[t[0].strip()] = t[1].strip()
220 return user_data 225 return user_data
221 226
222 ISO8601 = '%Y-%m-%dT%H:%M:%SZ' 227 ISO8601 = '%Y-%m-%dT%H:%M:%SZ'
228 ISO8601_MS = '%Y-%m-%dT%H:%M:%S.%fZ'
223 229
224 def get_ts(ts=None): 230 def get_ts(ts=None):
225 if not ts: 231 if not ts:
226 ts = time.gmtime() 232 ts = time.gmtime()
227 return time.strftime(ISO8601, ts) 233 return time.strftime(ISO8601, ts)
228 234
229 def parse_ts(ts): 235 def parse_ts(ts):
230 return datetime.datetime.strptime(ts, ISO8601) 236 try:
237 dt = datetime.datetime.strptime(ts, ISO8601)
238 return dt
239 except ValueError:
240 dt = datetime.datetime.strptime(ts, ISO8601_MS)
241 return dt
231 242
232 def find_class(module_name, class_name=None): 243 def find_class(module_name, class_name=None):
233 if class_name: 244 if class_name:
234 module_name = "%s.%s" % (module_name, class_name) 245 module_name = "%s.%s" % (module_name, class_name)
235 modules = module_name.split('.') 246 modules = module_name.split('.')
236 c = None 247 c = None
237 248
238 try: 249 try:
239 for m in modules[1:]: 250 for m in modules[1:]:
240 if c: 251 if c:
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 item.next.previous = previous 506 item.next.previous = previous
496 else: 507 else:
497 self.tail = previous 508 self.tail = previous
498 509
499 item.previous = None 510 item.previous = None
500 item.next = self.head 511 item.next = self.head
501 self.head.previous = self.head = item 512 self.head.previous = self.head = item
502 513
503 class Password(object): 514 class Password(object):
504 """ 515 """
505 Password object that stores itself as SHA512 hashed. 516 Password object that stores itself as hashed.
517 Hash defaults to SHA512 if available, MD5 otherwise.
506 """ 518 """
507 def __init__(self, str=None): 519 hashfunc=_hashfn
520 def __init__(self, str=None, hashfunc=None):
508 """ 521 """
509 Load the string from an initial value, this should be the raw SHA512 has hed password 522 Load the string from an initial value, this should be the raw hashed pas sword.
510 """ 523 """
511 self.str = str 524 self.str = str
525 if hashfunc:
526 self.hashfunc = hashfunc
512 527
513 def set(self, value): 528 def set(self, value):
514 self.str = _hashfn(value).hexdigest() 529 self.str = self.hashfunc(value).hexdigest()
515 530
516 def __str__(self): 531 def __str__(self):
517 return str(self.str) 532 return str(self.str)
518 533
519 def __eq__(self, other): 534 def __eq__(self, other):
520 if other == None: 535 if other == None:
521 return False 536 return False
522 return str(_hashfn(other).hexdigest()) == str(self.str) 537 return str(self.hashfunc(other).hexdigest()) == str(self.str)
523 538
524 def __len__(self): 539 def __len__(self):
525 if self.str: 540 if self.str:
526 return len(self.str) 541 return len(self.str)
527 else: 542 else:
528 return 0 543 return 0
529 544
530 def notify(subject, body=None, html_body=None, to_string=None, attachments=[], a ppend_instance_id=True): 545 def notify(subject, body=None, html_body=None, to_string=None, attachments=None, append_instance_id=True):
546 attachments = attachments or []
531 if append_instance_id: 547 if append_instance_id:
532 subject = "[%s] %s" % (boto.config.get_value("Instance", "instance-id"), subject) 548 subject = "[%s] %s" % (boto.config.get_value("Instance", "instance-id"), subject)
533 if not to_string: 549 if not to_string:
534 to_string = boto.config.get_value('Notification', 'smtp_to', None) 550 to_string = boto.config.get_value('Notification', 'smtp_to', None)
535 if to_string: 551 if to_string:
536 try: 552 try:
537 from_string = boto.config.get_value('Notification', 'smtp_from', 'bo to') 553 from_string = boto.config.get_value('Notification', 'smtp_from', 'bo to')
538 msg = MIMEMultipart() 554 msg = MIMEMultipart()
539 msg['From'] = from_string 555 msg['From'] = from_string
540 msg['Reply-To'] = from_string 556 msg['Reply-To'] = from_string
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 s = '' 612 s = ''
597 if name[0].isupper: 613 if name[0].isupper:
598 s = name[0].lower() 614 s = name[0].lower()
599 for c in name[1:]: 615 for c in name[1:]:
600 if c.isupper(): 616 if c.isupper():
601 s += sep + c.lower() 617 s += sep + c.lower()
602 else: 618 else:
603 s += c 619 s += c
604 return s 620 return s
605 621
606 def awsify_name(name): 622 def write_mime_multipart(content, compress=False, deftype='text/plain', delimite r=':'):
607 return name[0:1].upper()+name[1:] 623 """Description:
624 :param content: A list of tuples of name-content pairs. This is used
625 instead of a dict to ensure that scripts run in order
626 :type list of tuples:
627
628 :param compress: Use gzip to compress the scripts, defaults to no compressio n
629 :type bool:
630
631 :param deftype: The type that should be assumed if nothing else can be figur ed out
632 :type str:
633
634 :param delimiter: mime delimiter
635 :type str:
636
637 :return: Final mime multipart
638 :rtype: str:
639 """
640 wrapper = MIMEMultipart()
641 for name,con in content:
642 definite_type = guess_mime_type(con, deftype)
643 maintype, subtype = definite_type.split('/', 1)
644 if maintype == 'text':
645 mime_con = MIMEText(con, _subtype=subtype)
646 else:
647 mime_con = MIMEBase(maintype, subtype)
648 mime_con.set_payload(con)
649 # Encode the payload using Base64
650 Encoders.encode_base64(mime_con)
651 mime_con.add_header('Content-Disposition', 'attachment', filename=name)
652 wrapper.attach(mime_con)
653 rcontent = wrapper.as_string()
654
655 if compress:
656 buf = StringIO.StringIO()
657 gz = gzip.GzipFile(mode='wb', fileobj=buf)
658 try:
659 gz.write(rcontent)
660 finally:
661 gz.close()
662 rcontent = buf.getvalue()
663
664 return rcontent
665
666 def guess_mime_type(content, deftype):
667 """Description: Guess the mime type of a block of text
668 :param content: content we're finding the type of
669 :type str:
670
671 :param deftype: Default mime type
672 :type str:
673
674 :rtype: <type>:
675 :return: <description>
676 """
677 #Mappings recognized by cloudinit
678 starts_with_mappings={
679 '#include' : 'text/x-include-url',
680 '#!' : 'text/x-shellscript',
681 '#cloud-config' : 'text/cloud-config',
682 '#upstart-job' : 'text/upstart-job',
683 '#part-handler' : 'text/part-handler',
684 '#cloud-boothook' : 'text/cloud-boothook'
685 }
686 rtype = deftype
687 for possible_type,mimetype in starts_with_mappings.items():
688 if content.startswith(possible_type):
689 rtype = mimetype
690 break
691 return(rtype)
OLDNEW
« no previous file with comments | « boto/tests/test_sqsconnection.py ('k') | boto/vpc/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698