blob: 1365435a110dce61a3eb1847fb9ee3615f690dff [file] [log] [blame]
Attila Fazekasa23f5002012-10-23 19:32:45 +02001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack, LLC
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Attila Fazekasa23f5002012-10-23 19:32:45 +020018from ConfigParser import DuplicateSectionError
Matthew Treinisha83a16e2012-12-07 13:44:02 -050019from contextlib import closing
20import re
21from types import MethodType
22
23import boto
Attila Fazekasa23f5002012-10-23 19:32:45 +020024
25from tempest.exceptions import InvalidConfiguration
26from tempest.exceptions import NotFound
27
Attila Fazekasa23f5002012-10-23 19:32:45 +020028
29class BotoClientBase(object):
30
31 ALLOWED_METHODS = set()
32
33 def __init__(self, config,
34 username=None, password=None,
35 auth_url=None, tenant_name=None,
36 *args, **kwargs):
37
Attila Fazekas1ab2e9e2013-01-06 20:56:22 +010038 self.connection_timeout = str(config.boto.http_socket_timeout)
39 self.num_retries = str(config.boto.num_retries)
Attila Fazekasa23f5002012-10-23 19:32:45 +020040 self.build_timeout = config.boto.build_timeout
41 # We do not need the "path": "/token" part
42 if auth_url:
43 auth_url = re.sub("(.*)" + re.escape(config.identity.path) + "$",
44 "\\1", auth_url)
45 self.ks_cred = {"username": username,
46 "password": password,
47 "auth_url": auth_url,
48 "tenant_name": tenant_name}
49
50 def _keystone_aws_get(self):
51 import keystoneclient.v2_0.client
52
53 keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
54 ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
55 ec2_cred = None
56 for cred in ec2_cred_list:
57 if cred.tenant_id == keystone.auth_tenant_id:
58 ec2_cred = cred
59 break
60 else:
61 ec2_cred = keystone.ec2.create(keystone.auth_user_id,
62 keystone.auth_tenant_id)
63 if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
64 raise NotFound("Unable to get access and secret keys")
65 return ec2_cred
66
Attila Fazekasf7f2d932012-12-13 09:14:38 +010067 def _config_boto_timeout(self, timeout, retries):
Attila Fazekasa23f5002012-10-23 19:32:45 +020068 try:
69 boto.config.add_section("Boto")
70 except DuplicateSectionError:
71 pass
72 boto.config.set("Boto", "http_socket_timeout", timeout)
Attila Fazekasf7f2d932012-12-13 09:14:38 +010073 boto.config.set("Boto", "num_retries", retries)
Attila Fazekasa23f5002012-10-23 19:32:45 +020074
75 def __getattr__(self, name):
Sean Daguef237ccb2013-01-04 15:19:14 -050076 """Automatically creates methods for the allowed methods set."""
Attila Fazekasa23f5002012-10-23 19:32:45 +020077 if name in self.ALLOWED_METHODS:
78 def func(self, *args, **kwargs):
79 with closing(self.get_connection()) as conn:
80 return getattr(conn, name)(*args, **kwargs)
81
82 func.__name__ = name
83 setattr(self, name, MethodType(func, self, self.__class__))
84 setattr(self.__class__, name,
85 MethodType(func, None, self.__class__))
86 return getattr(self, name)
87 else:
88 raise AttributeError(name)
89
90 def get_connection(self):
Attila Fazekasf7f2d932012-12-13 09:14:38 +010091 self._config_boto_timeout(self.connection_timeout, self.num_retries)
Attila Fazekasa23f5002012-10-23 19:32:45 +020092 if not all((self.connection_data["aws_access_key_id"],
93 self.connection_data["aws_secret_access_key"])):
94 if all(self.ks_cred.itervalues()):
95 ec2_cred = self._keystone_aws_get()
96 self.connection_data["aws_access_key_id"] = \
97 ec2_cred.access
98 self.connection_data["aws_secret_access_key"] = \
99 ec2_cred.secret
100 else:
101 raise InvalidConfiguration(
102 "Unable to get access and secret keys")
103 return self.connect_method(**self.connection_data)