blob: 7423c17e7eb2a2763c9f3857cd044307235285a9 [file] [log] [blame]
Matthew Treinishc791ac42014-07-16 09:15:23 -04001# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
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 hashlib
16import os
Matthew Treinish96e9e882014-06-09 18:37:19 -040017
Matthew Treinishc791ac42014-07-16 09:15:23 -040018import yaml
19
20from tempest import auth
21from tempest.common import cred_provider
22from tempest import config
23from tempest import exceptions
24from tempest.openstack.common import lockutils
25from tempest.openstack.common import log as logging
26
27CONF = config.CONF
28LOG = logging.getLogger(__name__)
29
30
31def read_accounts_yaml(path):
32 yaml_file = open(path, 'r')
33 accounts = yaml.load(yaml_file)
34 return accounts
35
36
37class Accounts(cred_provider.CredentialProvider):
38
39 def __init__(self, name):
40 super(Accounts, self).__init__(name)
Matthew Treinishb19eeb82014-09-04 09:57:46 -040041 if os.path.isfile(CONF.auth.test_accounts_file):
42 accounts = read_accounts_yaml(CONF.auth.test_accounts_file)
43 self.use_default_creds = False
44 else:
45 accounts = {}
46 self.use_default_creds = True
Matthew Treinishc791ac42014-07-16 09:15:23 -040047 self.hash_dict = self.get_hash_dict(accounts)
48 self.accounts_dir = os.path.join(CONF.lock_path, 'test_accounts')
49 self.isolated_creds = {}
50
51 @classmethod
52 def get_hash_dict(cls, accounts):
53 hash_dict = {}
54 for account in accounts:
55 temp_hash = hashlib.md5()
56 temp_hash.update(str(account))
57 hash_dict[temp_hash.hexdigest()] = account
58 return hash_dict
59
Matthew Treinish09f17832014-08-15 15:22:50 -040060 def is_multi_user(self):
61 return len(self.hash_dict) > 1
62
63 def _create_hash_file(self, hash_string):
64 path = os.path.join(os.path.join(self.accounts_dir, hash_string))
Matthew Treinishc791ac42014-07-16 09:15:23 -040065 if not os.path.isfile(path):
66 open(path, 'w').close()
67 return True
68 return False
69
70 @lockutils.synchronized('test_accounts_io', external=True)
71 def _get_free_hash(self, hashes):
72 if not os.path.isdir(self.accounts_dir):
73 os.mkdir(self.accounts_dir)
74 # Create File from first hash (since none are in use)
75 self._create_hash_file(hashes[0])
76 return hashes[0]
Matthew Treinish09f17832014-08-15 15:22:50 -040077 for _hash in hashes:
78 res = self._create_hash_file(_hash)
Matthew Treinishc791ac42014-07-16 09:15:23 -040079 if res:
Matthew Treinish09f17832014-08-15 15:22:50 -040080 return _hash
Matthew Treinishc791ac42014-07-16 09:15:23 -040081 msg = 'Insufficient number of users provided'
82 raise exceptions.InvalidConfiguration(msg)
83
84 def _get_creds(self):
Matthew Treinishb19eeb82014-09-04 09:57:46 -040085 if self.use_default_creds:
86 raise exceptions.InvalidConfiguration(
87 "Account file %s doesn't exist" % CONF.auth.test_accounts_file)
Matthew Treinish09f17832014-08-15 15:22:50 -040088 free_hash = self._get_free_hash(self.hash_dict.keys())
Matthew Treinishc791ac42014-07-16 09:15:23 -040089 return self.hash_dict[free_hash]
90
91 @lockutils.synchronized('test_accounts_io', external=True)
Matthew Treinish09f17832014-08-15 15:22:50 -040092 def remove_hash(self, hash_string):
93 hash_path = os.path.join(self.accounts_dir, hash_string)
Matthew Treinishc791ac42014-07-16 09:15:23 -040094 if not os.path.isfile(hash_path):
95 LOG.warning('Expected an account lock file %s to remove, but '
96 'one did not exist')
97 else:
98 os.remove(hash_path)
99 if not os.listdir(self.accounts_dir):
100 os.rmdir(self.accounts_dir)
101
102 def get_hash(self, creds):
Matthew Treinish09f17832014-08-15 15:22:50 -0400103 for _hash in self.hash_dict:
104 # Comparing on the attributes that are expected in the YAML
105 if all([getattr(creds, k) == self.hash_dict[_hash][k] for k in
106 creds.CONF_ATTRIBUTES]):
107 return _hash
Matthew Treinishc791ac42014-07-16 09:15:23 -0400108 raise AttributeError('Invalid credentials %s' % creds)
109
110 def remove_credentials(self, creds):
Matthew Treinish09f17832014-08-15 15:22:50 -0400111 _hash = self.get_hash(creds)
112 self.remove_hash(_hash)
Matthew Treinishc791ac42014-07-16 09:15:23 -0400113
114 def get_primary_creds(self):
Matthew Treinish09f17832014-08-15 15:22:50 -0400115 if self.isolated_creds.get('primary'):
116 return self.isolated_creds.get('primary')
Matthew Treinishc791ac42014-07-16 09:15:23 -0400117 creds = self._get_creds()
118 primary_credential = auth.get_credentials(**creds)
Matthew Treinish09f17832014-08-15 15:22:50 -0400119 self.isolated_creds['primary'] = primary_credential
Matthew Treinishc791ac42014-07-16 09:15:23 -0400120 return primary_credential
121
122 def get_alt_creds(self):
Matthew Treinish09f17832014-08-15 15:22:50 -0400123 if self.isolated_creds.get('alt'):
124 return self.isolated_creds.get('alt')
Matthew Treinishc791ac42014-07-16 09:15:23 -0400125 creds = self._get_creds()
126 alt_credential = auth.get_credentials(**creds)
Matthew Treinish09f17832014-08-15 15:22:50 -0400127 self.isolated_creds['alt'] = alt_credential
Matthew Treinishc791ac42014-07-16 09:15:23 -0400128 return alt_credential
129
130 def clear_isolated_creds(self):
Matthew Treinish09f17832014-08-15 15:22:50 -0400131 for creds in self.isolated_creds.values():
Matthew Treinishc791ac42014-07-16 09:15:23 -0400132 self.remove_credentials(creds)
133
134 def get_admin_creds(self):
135 msg = ('If admin credentials are available tenant_isolation should be'
136 ' used instead')
137 raise NotImplementedError(msg)
Andrea Frittolib1c23fc2014-09-03 13:40:08 +0100138
139
140class NotLockingAccounts(Accounts):
141 """Credentials provider which always returns the first and second
142 configured accounts as primary and alt users.
143 This credential provider can be used in case of serial test execution
144 to preserve the current behaviour of the serial tempest run.
145 """
146
147 def get_creds(self, id):
148 try:
149 # No need to sort the dict as within the same python process
150 # the HASH seed won't change, so subsequent calls to keys()
151 # will return the same result
152 _hash = self.hash_dict.keys()[id]
153 except IndexError:
154 msg = 'Insufficient number of users provided'
155 raise exceptions.InvalidConfiguration(msg)
156 return self.hash_dict[_hash]
157
158 def get_primary_creds(self):
159 if self.isolated_creds.get('primary'):
160 return self.isolated_creds.get('primary')
Matthew Treinishb19eeb82014-09-04 09:57:46 -0400161 if not self.use_default_creds:
162 creds = self.get_creds(0)
163 primary_credential = auth.get_credentials(**creds)
164 else:
165 primary_credential = auth.get_default_credentials('user')
Andrea Frittolib1c23fc2014-09-03 13:40:08 +0100166 self.isolated_creds['primary'] = primary_credential
167 return primary_credential
168
169 def get_alt_creds(self):
170 if self.isolated_creds.get('alt'):
171 return self.isolated_creds.get('alt')
Matthew Treinishb19eeb82014-09-04 09:57:46 -0400172 if not self.use_default_creds:
173 creds = self.get_creds(1)
174 alt_credential = auth.get_credentials(**creds)
175 else:
176 alt_credential = auth.get_default_credentials('alt_user')
Andrea Frittolib1c23fc2014-09-03 13:40:08 +0100177 self.isolated_creds['alt'] = alt_credential
178 return alt_credential
179
180 def clear_isolated_creds(self):
181 self.isolated_creds = {}
182
183 def get_admin_creds(self):
184 return auth.get_default_credentials("identity_admin", fill_in=False)