1# Copyright 2014 Rackspace 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 15import logging 16import sys 17 18from oslo_config import cfg 19from six.moves import configparser 20 21from glance_store import exceptions 22from glance_store.i18n import _, _LE 23 24swift_opts = [ 25 cfg.StrOpt('default_swift_reference', 26 default="ref1", 27 help=""" 28Reference to default Swift account/backing store parameters. 29 30Provide a string value representing a reference to the default set 31of parameters required for using swift account/backing store for 32image storage. The default reference value for this configuration 33option is 'ref1'. This configuration option dereferences the 34parameters and facilitates image storage in Swift storage backend 35every time a new image is added. 36 37Possible values: 38 * A valid string value 39 40Related options: 41 * None 42 43"""), 44 cfg.StrOpt('swift_store_auth_version', default='2', 45 help='Version of the authentication service to use. ' 46 'Valid versions are 2 and 3 for keystone and 1 ' 47 '(deprecated) for swauth and rackspace.', 48 deprecated_for_removal=True, 49 deprecated_reason=""" 50The option 'auth_version' in the Swift back-end configuration file is 51used instead. 52"""), 53 cfg.StrOpt('swift_store_auth_address', 54 help='The address where the Swift authentication ' 55 'service is listening.', 56 deprecated_for_removal=True, 57 deprecated_reason=""" 58The option 'auth_address' in the Swift back-end configuration file is 59used instead. 60"""), 61 cfg.StrOpt('swift_store_user', secret=True, 62 help='The user to authenticate against the Swift ' 63 'authentication service.', 64 deprecated_for_removal=True, 65 deprecated_reason=""" 66The option 'user' in the Swift back-end configuration file is set instead. 67"""), 68 cfg.StrOpt('swift_store_key', secret=True, 69 help='Auth key for the user authenticating against the ' 70 'Swift authentication service.', 71 deprecated_for_removal=True, 72 deprecated_reason=""" 73The option 'key' in the Swift back-end configuration file is used 74to set the authentication key instead. 75"""), 76 cfg.StrOpt('swift_store_config_file', 77 default=None, 78 help=""" 79Absolute path to the file containing the swift account(s) 80configurations. 81 82Include a string value representing the path to a configuration 83file that has references for each of the configured Swift 84account(s)/backing stores. By default, no file path is specified 85and customized Swift referencing is disabled. Configuring this 86option is highly recommended while using Swift storage backend for 87image storage as it avoids storage of credentials in the database. 88 89NOTE: Please do not configure this option if you have set 90``swift_store_multi_tenant`` to ``True``. 91 92Possible values: 93 * String value representing an absolute path on the glance-api 94 node 95 96Related options: 97 * swift_store_multi_tenant 98 99"""), 100] 101 102_config_defaults = {'user_domain_id': 'default', 103 'user_domain_name': 'default', 104 'project_domain_id': 'default', 105 'project_domain_name': 'default'} 106 107if sys.version_info >= (3, 2): 108 parser_class = configparser.ConfigParser 109else: 110 parser_class = configparser.SafeConfigParser 111 112 113class SwiftConfigParser(parser_class): 114 115 def get(self, *args, **kwargs): 116 value = super(parser_class, self).get(*args, **kwargs) 117 return self._process_quotes(value) 118 119 @staticmethod 120 def _process_quotes(value): 121 if value: 122 if value[0] in "\"'": 123 if len(value) == 1 or value[-1] != value[0]: 124 raise ValueError('Non-closed quote: %s' % 125 value) 126 value = value[1:-1] 127 return value 128 129 130if sys.version_info >= (3,): 131 CONFIG = SwiftConfigParser(defaults=_config_defaults) 132else: 133 CONFIG = parser_class(defaults=_config_defaults) 134 135LOG = logging.getLogger(__name__) 136 137 138def is_multiple_swift_store_accounts_enabled(conf, backend=None): 139 if backend: 140 cfg_file = getattr(conf, backend).swift_store_config_file 141 else: 142 cfg_file = conf.glance_store.swift_store_config_file 143 144 if cfg_file is None: 145 return False 146 return True 147 148 149class SwiftParams(object): 150 def __init__(self, conf, backend=None): 151 self.conf = conf 152 self.backend_group = backend 153 if is_multiple_swift_store_accounts_enabled( 154 self.conf, backend=backend): 155 self.params = self._load_config() 156 else: 157 self.params = self._form_default_params() 158 159 def _form_default_params(self): 160 default = {} 161 if self.backend_group: 162 glance_store = getattr(self.conf, self.backend_group) 163 else: 164 glance_store = self.conf.glance_store 165 if ( 166 glance_store.swift_store_user and 167 glance_store.swift_store_key and 168 glance_store.swift_store_auth_address 169 ): 170 171 default['user'] = glance_store.swift_store_user 172 default['key'] = glance_store.swift_store_key 173 default['auth_address'] = glance_store.swift_store_auth_address 174 default['project_domain_id'] = 'default' 175 default['project_domain_name'] = None 176 default['user_domain_id'] = 'default' 177 default['user_domain_name'] = None 178 default['auth_version'] = glance_store.swift_store_auth_version 179 return {glance_store.default_swift_reference: default} 180 return {} 181 182 def _load_config(self): 183 if self.backend_group: 184 scf = getattr(self.conf, 185 self.backend_group).swift_store_config_file 186 else: 187 scf = self.conf.glance_store.swift_store_config_file 188 try: 189 conf_file = self.conf.find_file(scf) 190 CONFIG.read(conf_file) 191 except Exception as e: 192 msg = (_("swift config file " 193 "%(conf)s:%(exc)s not found"), 194 {'conf': scf, 195 'exc': e}) 196 LOG.error(msg) 197 raise exceptions.BadStoreConfiguration(store_name='swift', 198 reason=msg) 199 account_params = {} 200 account_references = CONFIG.sections() 201 202 for ref in account_references: 203 reference = {} 204 try: 205 for param in ('auth_address', 206 'user', 207 'key', 208 'project_domain_id', 209 'project_domain_name', 210 'user_domain_id', 211 'user_domain_name'): 212 reference[param] = CONFIG.get(ref, param) 213 214 try: 215 reference['auth_version'] = CONFIG.get(ref, 'auth_version') 216 except configparser.NoOptionError: 217 if self.backend_group: 218 av = getattr( 219 self.conf, 220 self.backend_group).swift_store_auth_version 221 else: 222 av = self.conf.glance_store.swift_store_auth_version 223 reference['auth_version'] = av 224 225 account_params[ref] = reference 226 except (ValueError, SyntaxError, configparser.NoOptionError): 227 LOG.exception(_LE("Invalid format of swift store config cfg")) 228 return account_params 229