Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 1 | # Copyright 2014 Rackspace Australia |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 4 | # not use this file except in compliance with the License. You may obtain |
| 5 | # a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations |
| 13 | # under the License. |
| 14 | |
| 15 | import hmac |
| 16 | from hashlib import sha1 |
| 17 | from time import time |
| 18 | import os |
| 19 | import random |
Christian Berendt | e35b99c | 2014-06-06 16:57:47 +0200 | [diff] [blame] | 20 | import six |
Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 21 | import string |
| 22 | import swiftclient |
| 23 | import urlparse |
| 24 | |
| 25 | |
| 26 | class Swift(object): |
| 27 | def __init__(self, config): |
| 28 | self.config = config |
| 29 | self.connection = False |
| 30 | if self.config.has_option('swift', 'X-Account-Meta-Temp-Url-Key'): |
| 31 | self.secure_key = self.config.get('swift', |
| 32 | 'X-Account-Meta-Temp-Url-Key') |
| 33 | else: |
| 34 | self.secure_key = ''.join( |
| 35 | random.choice(string.ascii_uppercase + string.digits) |
| 36 | for x in range(20) |
| 37 | ) |
| 38 | |
| 39 | self.connect() |
| 40 | |
| 41 | def connect(self): |
| 42 | if self.config.has_section('swift'): |
| 43 | # required |
| 44 | authurl = self.config.get('swift', 'authurl') |
| 45 | |
| 46 | user = (self.config.get('swift', 'user') |
| 47 | if self.config.has_option('swift', 'user') else None) |
| 48 | key = (self.config.get('swift', 'key') |
| 49 | if self.config.has_option('swift', 'key') else None) |
| 50 | retries = (self.config.get('swift', 'retries') |
| 51 | if self.config.has_option('swift', 'retries') else 5) |
| 52 | preauthurl = (self.config.get('swift', 'preauthurl') |
| 53 | if self.config.has_option('swift', 'preauthurl') |
| 54 | else None) |
| 55 | preauthtoken = (self.config.get('swift', 'preauthtoken') |
| 56 | if self.config.has_option('swift', 'preauthtoken') |
| 57 | else None) |
| 58 | snet = (self.config.get('swift', 'snet') |
| 59 | if self.config.has_option('swift', 'snet') else False) |
| 60 | starting_backoff = (self.config.get('swift', 'starting_backoff') |
| 61 | if self.config.has_option('swift', |
| 62 | 'starting_backoff') |
| 63 | else 1) |
| 64 | max_backoff = (self.config.get('swift', 'max_backoff') |
| 65 | if self.config.has_option('swift', 'max_backoff') |
| 66 | else 64) |
| 67 | tenant_name = (self.config.get('swift', 'tenant_name') |
| 68 | if self.config.has_option('swift', 'tenant_name') |
| 69 | else None) |
| 70 | auth_version = (self.config.get('swift', 'auth_version') |
| 71 | if self.config.has_option('swift', 'auth_version') |
| 72 | else 2.0) |
| 73 | cacert = (self.config.get('swift', 'cacert') |
| 74 | if self.config.has_option('swift', 'cacert') else None) |
| 75 | insecure = (self.config.get('swift', 'insecure') |
| 76 | if self.config.has_option('swift', 'insecure') |
| 77 | else False) |
| 78 | ssl_compression = (self.config.get('swift', 'ssl_compression') |
| 79 | if self.config.has_option('swift', |
| 80 | 'ssl_compression') |
| 81 | else True) |
| 82 | |
| 83 | available_os_options = ['tenant_id', 'auth_token', 'service_type', |
| 84 | 'endpoint_type', 'tenant_name', |
| 85 | 'object_storage_url', 'region_name'] |
| 86 | |
| 87 | os_options = {} |
| 88 | for os_option in available_os_options: |
| 89 | if self.config.has_option('swift', os_option): |
| 90 | os_options[os_option] = self.config.get('swift', os_option) |
| 91 | |
| 92 | self.connection = swiftclient.client.Connection( |
| 93 | authurl=authurl, user=user, key=key, retries=retries, |
| 94 | preauthurl=preauthurl, preauthtoken=preauthtoken, snet=snet, |
| 95 | starting_backoff=starting_backoff, max_backoff=max_backoff, |
| 96 | tenant_name=tenant_name, os_options=os_options, |
| 97 | auth_version=auth_version, cacert=cacert, insecure=insecure, |
| 98 | ssl_compression=ssl_compression) |
| 99 | |
| 100 | # Tell swift of our key |
| 101 | headers = {} |
| 102 | headers['X-Account-Meta-Temp-Url-Key'] = self.secure_key |
| 103 | self.connection.post_account(headers) |
| 104 | |
| 105 | self.storage_url, self.auth_token = self.connection.get_auth() |
| 106 | |
| 107 | def generate_form_post_middleware_params(self, destination_prefix='', |
| 108 | **kwargs): |
| 109 | """Generate the FormPost middleware params for the given settings""" |
| 110 | |
| 111 | # Define the available settings and their defaults |
| 112 | settings = { |
| 113 | 'container': '', |
| 114 | 'expiry': 7200, |
| 115 | 'max_file_size': 104857600, |
| 116 | 'max_file_count': 10, |
| 117 | 'file_path_prefix': '' |
| 118 | } |
| 119 | |
Christian Berendt | e35b99c | 2014-06-06 16:57:47 +0200 | [diff] [blame] | 120 | for key, default in six.iteritems(settings): |
James E. Blair | d650023 | 2014-06-23 15:05:48 -0700 | [diff] [blame^] | 121 | # TODO(jeblair): Remove the following two lines after a |
| 122 | # deprecation period for the underscore variants of the |
| 123 | # settings in YAML. |
Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 124 | if key in kwargs: |
| 125 | settings[key] = kwargs[key] |
James E. Blair | d650023 | 2014-06-23 15:05:48 -0700 | [diff] [blame^] | 126 | # Since we prefer '-' rather than '_' in YAML, look up |
| 127 | # keys there using hyphens. Continue to use underscores |
| 128 | # everywhere else. |
| 129 | altkey = key.replace('_', '-') |
| 130 | if altkey in kwargs: |
| 131 | settings[key] = kwargs[altkey] |
Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 132 | elif self.config.has_option('swift', 'default_' + key): |
| 133 | settings[key] = self.config.get('swift', 'default_' + key) |
| 134 | |
| 135 | expires = int(time() + settings['expiry']) |
| 136 | redirect = '' |
| 137 | |
| 138 | url = os.path.join(self.storage_url, settings['container'], |
| 139 | settings['file_path_prefix'], |
| 140 | destination_prefix) |
| 141 | u = urlparse.urlparse(url) |
| 142 | |
| 143 | hmac_body = '%s\n%s\n%s\n%s\n%s' % (u.path, redirect, |
| 144 | settings['max_file_size'], |
| 145 | settings['max_file_count'], |
| 146 | expires) |
| 147 | |
| 148 | signature = hmac.new(self.secure_key, hmac_body, sha1).hexdigest() |
| 149 | |
| 150 | return url, hmac_body, signature |