-
-
Save Kami/898566 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import subprocess | |
| from urlparse import urlparse, urlunparse | |
| from httplib import HTTPException, HTTPSConnection | |
| from urllib import quote as _quote, unquote | |
| url='https://auth.api.rackspacecloud.com/v1.0' | |
| def http_connection(url): | |
| parsed = urlparse(url) | |
| if parsed.scheme == 'http': | |
| conn = HTTPConnection(parsed.netloc) | |
| elif parsed.scheme == 'https': | |
| conn = HTTPSConnection(parsed.netloc) | |
| else: | |
| raise ClientException('Cannot handle protocol scheme %s for url %s' % | |
| (parsed.scheme, repr(url))) | |
| return parsed, conn | |
| def get_auth(url, user, key, snet=False): | |
| parsed, conn = http_connection(url) | |
| conn.request('GET', parsed.path, '', | |
| {'X-Auth-User': user, 'X-Auth-Key': key}) | |
| resp = conn.getresponse() | |
| resp.read() | |
| if resp.status < 200 or resp.status >= 300: | |
| raise ClientException('Auth GET failed', http_scheme=parsed.scheme, | |
| http_host=conn.host, http_port=conn.port, | |
| http_path=parsed.path, http_status=resp.status, | |
| http_reason=resp.reason) | |
| url = resp.getheader('x-storage-url') | |
| if snet: | |
| parsed = list(urlparse(url)) | |
| # Second item in the list is the netloc | |
| parsed[1] = 'snet-' + parsed[1] | |
| url = urlunparse(parsed) | |
| return url, resp.getheader('x-storage-token', | |
| resp.getheader('x-auth-token')) | |
| def put_object(url, token, container, name, contents, content_length=None, | |
| etag=None, chunk_size=65536, content_type=None, headers=None, | |
| http_conn=None): | |
| if http_conn: | |
| parsed, conn = http_conn | |
| else: | |
| parsed, conn = http_connection(url) | |
| path = '%s/%s/%s' % (parsed.path, quote(container), quote(name)) | |
| if not headers: | |
| headers = {} | |
| headers['X-Auth-Token'] = token | |
| if etag: | |
| headers['ETag'] = etag.strip('"') | |
| if content_length is not None: | |
| headers['Content-Length'] = str(content_length) | |
| if content_type is not None: | |
| headers['Content-Type'] = content_type | |
| if not contents: | |
| headers['Content-Length'] = '0' | |
| if hasattr(contents, 'read'): | |
| conn.putrequest('PUT', path) | |
| for header, value in headers.iteritems(): | |
| conn.putheader(header, value) | |
| if content_length is None: | |
| conn.putheader('Transfer-Encoding', 'chunked') | |
| conn.endheaders() | |
| chunk = contents.read(chunk_size) | |
| while chunk: | |
| conn.send('%x\r\n%s\r\n' % (len(chunk), chunk)) | |
| chunk = contents.read(chunk_size) | |
| conn.send('0\r\n\r\n') | |
| else: | |
| conn.endheaders() | |
| left = content_length | |
| while left > 0: | |
| size = chunk_size | |
| if size > left: | |
| size = left | |
| chunk = contents.read(size) | |
| conn.send(chunk) | |
| left -= len(chunk) | |
| else: | |
| conn.request('PUT', path, contents, headers) | |
| resp = conn.getresponse() | |
| resp.read() | |
| if resp.status < 200 or resp.status >= 300: | |
| raise ClientException('Object PUT failed', http_scheme=parsed.scheme, | |
| http_host=conn.host, http_port=conn.port, http_path=path, | |
| http_status=resp.status, http_reason=resp.reason) | |
| return resp.getheader('etag').strip('"') | |
| def quote(value, safe='/'): | |
| if isinstance(value, unicode): | |
| value = value.encode('utf8') | |
| return _quote(value, safe) | |
| class ClientException(Exception): | |
| def __init__(self, msg, http_scheme='', http_host='', http_port='', | |
| http_path='', http_query='', http_status=0, http_reason='', | |
| http_device=''): | |
| Exception.__init__(self, msg) | |
| self.msg = msg | |
| self.http_scheme = http_scheme | |
| self.http_host = http_host | |
| self.http_port = http_port | |
| self.http_path = http_path | |
| self.http_query = http_query | |
| self.http_status = http_status | |
| self.http_reason = http_reason | |
| self.http_device = http_device | |
| def __str__(self): | |
| a = self.msg | |
| b = '' | |
| if self.http_scheme: | |
| b += '%s://' % self.http_scheme | |
| if self.http_host: | |
| b += self.http_host | |
| if self.http_port: | |
| b += ':%s' % self.http_port | |
| if self.http_path: | |
| b += self.http_path | |
| if self.http_query: | |
| b += '?%s' % self.http_query | |
| if self.http_status: | |
| if b: | |
| b = '%s %s' % (b, self.http_status) | |
| else: | |
| b = str(self.http_status) | |
| if self.http_reason: | |
| if b: | |
| b = '%s %s' % (b, self.http_reason) | |
| else: | |
| b = '- %s' % self.http_reason | |
| if self.http_device: | |
| if b: | |
| b = '%s: device %s' % (b, self.http_device) | |
| else: | |
| b = 'device %s' % self.http_device | |
| return b and '%s: %s' % (a, b) or a | |
| # All the defs above are for the put_object, they work. | |
| class SizeLimitedFile(object): | |
| def __init__(self, source, length): | |
| self.source = source | |
| self.length = length | |
| def read(self, size): | |
| if self.length <= 0: | |
| print 'done' | |
| return "" | |
| to_read = min(size, self.length) | |
| ret = self.source.read(to_read) | |
| if len(ret) == 0: | |
| self.length = 0 | |
| else: | |
| self.length -= len(ret) | |
| return ret | |
| storage_url, key = get_auth('https://auth.api.rackspacecloud.com/v1.0','xxxxxxxxx','xxxxxxxxx',snet=False) | |
| tarcmd = 'tar --use-compress-program=lzop -cvf - /home/crhodes/sandbox/outfile' | |
| #cmd = ['/bin/tar --use-compress-program=lzop -cvf - /home/chrodes/sandbox/outfile'] | |
| pipe = subprocess.Popen(tarcmd,bufsize=0,shell = True,stdout = subprocess.PIPE) | |
| #pipe = subprocess.Popen(tarcmd, stdout=subprocess.PIPE) | |
| part_num = 0 | |
| returncode = pipe.poll() | |
| while returncode is None: | |
| src = SizeLimitedFile(pipe.stdout, 1024) | |
| put_object(storage_url, key, 'cass_test_store', 'test_file-part-%d' % part_num, src) | |
| part_num += 1 | |
| returncode = pipe.poll() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment