blob: dc93910e30a3a718cd5a72318276b0e406b63bd2 [file] [log] [blame]
Daryl Walleck1465d612011-11-02 02:22:15 -05001import ConfigParser
Jay Pipes7f757632011-12-02 15:53:32 -05002import logging
3import os
kavan-patil4ea2efb2011-12-09 08:58:50 +00004from tempest.common.utils import data_utils
Jay Pipes7f757632011-12-02 15:53:32 -05005
6LOG = logging.getLogger(__name__)
Daryl Walleck1465d612011-11-02 02:22:15 -05007
8
Daryl Walleck587385b2012-03-03 13:00:26 -06009class IdentityConfig(object):
10 """Provides configuration information for authenticating with Keystone."""
Daryl Walleck1465d612011-11-02 02:22:15 -050011
12 def __init__(self, conf):
Daryl Walleck587385b2012-03-03 13:00:26 -060013 """Initialize an Identity-specific configuration object"""
Daryl Walleck1465d612011-11-02 02:22:15 -050014 self.conf = conf
15
donald-ngo7fb1efa2011-12-13 17:17:36 -080016 def get(self, item_name, default_value=None):
Daryl Walleck1465d612011-11-02 02:22:15 -050017 try:
Daryl Walleck587385b2012-03-03 13:00:26 -060018 return self.conf.get("identity", item_name)
Daryl Walleck1465d612011-11-02 02:22:15 -050019 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
20 return default_value
21
22 @property
Rohit Karajgie1b050d2011-12-02 16:13:18 -080023 def host(self):
Daryl Walleck587385b2012-03-03 13:00:26 -060024 """Host IP for making Identity API requests."""
donald-ngo7fb1efa2011-12-13 17:17:36 -080025 return self.get("host", "127.0.0.1")
Rohit Karajgie1b050d2011-12-02 16:13:18 -080026
27 @property
28 def port(self):
Daryl Walleck587385b2012-03-03 13:00:26 -060029 """Port for the Identity service."""
Rohit Karajgie1b050d2011-12-02 16:13:18 -080030 return self.get("port", "8773")
31
32 @property
Daryl Walleck587385b2012-03-03 13:00:26 -060033 def api_version(self):
34 """Version of the Identity API"""
35 return self.get("api_version", "v1.1")
Rohit Karajgie1b050d2011-12-02 16:13:18 -080036
37 @property
38 def path(self):
39 """Path of API request"""
40 return self.get("path", "/")
41
kavan-patil4ea2efb2011-12-09 08:58:50 +000042 @property
43 def auth_url(self):
Daryl Walleck587385b2012-03-03 13:00:26 -060044 """The Identity URL (derived)"""
kavan-patil4ea2efb2011-12-09 08:58:50 +000045 auth_url = data_utils.build_url(self.host,
46 self.port,
Daryl Walleck587385b2012-03-03 13:00:26 -060047 self.api_version,
donald-ngo7fb1efa2011-12-13 17:17:36 -080048 self.path,
49 use_ssl=self.use_ssl)
kavan-patil4ea2efb2011-12-09 08:58:50 +000050 return auth_url
51
Daryl Walleck1465d612011-11-02 02:22:15 -050052 @property
donald-ngo7fb1efa2011-12-13 17:17:36 -080053 def use_ssl(self):
54 """Specifies if we are using https."""
Dan Prince95195922012-03-12 15:14:51 -040055 return self.get("use_ssl", 'false').lower() != 'false'
donald-ngo7fb1efa2011-12-13 17:17:36 -080056
57 @property
Daryl Walleck1465d612011-11-02 02:22:15 -050058 def username(self):
Daryl Walleck587385b2012-03-03 13:00:26 -060059 """Username to use for Identity API requests."""
60 return self.get("user", None)
Daryl Walleck1465d612011-11-02 02:22:15 -050061
62 @property
63 def tenant_name(self):
Daryl Walleck587385b2012-03-03 13:00:26 -060064 """Tenant name to use for Identity API requests."""
65 return self.get("tenant_name", None)
Daryl Walleck1465d612011-11-02 02:22:15 -050066
67 @property
Daryl Walleck587385b2012-03-03 13:00:26 -060068 def password(self):
69 """Password to use when authenticating."""
70 return self.get("password", None)
71
72 @property
73 def strategy(self):
74 """Which auth method does the environment use? (basic|keystone)"""
75 return self.get("strategy", 'keystone')
76
77
78class ComputeConfig(object):
79 def __init__(self, conf):
80 """Initialize a Compute-specific configuration object."""
81 self.conf = conf
82
83 def get(self, item_name, default_value):
84 try:
85 return self.conf.get("compute", item_name)
86 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
87 return default_value
88
89 @property
90 def image_ref(self):
91 """Valid primary image to use in tests."""
92 return self.get("image_ref", 'e7ddc02e-92fa-4f82-b36f-59b39bf66a67')
93
94 @property
95 def image_ref_alt(self):
96 """Valid secondary image reference to be used in tests."""
97 return self.get("image_ref_alt", '346f4039-a81e-44e0-9223-4a3d13c907')
98
99 @property
100 def flavor_ref(self):
101 """Valid primary flavor to use in tests."""
102 return self.get("flavor_ref", 1)
103
104 @property
105 def flavor_ref_alt(self):
106 """Valid secondary flavor to be used in tests."""
107 return self.get("flavor_ref_alt", 2)
108
109 @property
110 def resize_available(self):
111 """Does the test environment support resizing?"""
Dan Prince95195922012-03-12 15:14:51 -0400112 return self.get("resize_available", 'false').lower() != 'false'
Daryl Walleck587385b2012-03-03 13:00:26 -0600113
114 @property
115 def create_image_enabled(self):
116 """Does the test environment support snapshots?"""
Dan Prince95195922012-03-12 15:14:51 -0400117 return self.get("create_image_enabled", 'false').lower() != 'false'
Daryl Walleck587385b2012-03-03 13:00:26 -0600118
119 @property
120 def release_name(self):
121 """Which release is this?"""
122 return self.get("release_name", 'essex')
Daryl Walleck1465d612011-11-02 02:22:15 -0500123
124 @property
125 def build_interval(self):
126 """Time in seconds between build status checks."""
127 return float(self.get("build_interval", 10))
128
129 @property
130 def ssh_timeout(self):
131 """Timeout in seconds to use when connecting via ssh."""
132 return float(self.get("ssh_timeout", 300))
133
134 @property
135 def build_timeout(self):
136 """Timeout in seconds to wait for an entity to build."""
137 return float(self.get("build_timeout", 300))
138
Daryl Walleck4aa82a92012-02-14 15:45:46 -0600139 @property
Daryl Walleckb90a1a62012-02-27 11:23:10 -0600140 def catalog_type(self):
Daryl Walleck587385b2012-03-03 13:00:26 -0600141 """Catalog type of the Compute service."""
Daryl Walleckb90a1a62012-02-27 11:23:10 -0600142 return self.get("catalog_type", 'compute')
Daryl Walleck4aa82a92012-02-14 15:45:46 -0600143
Daryl Walleck1465d612011-11-02 02:22:15 -0500144
Jay Pipes50677282012-01-06 15:39:20 -0500145class ImagesConfig(object):
146 """
147 Provides configuration information for connecting to an
148 OpenStack Images service.
149 """
150
151 def __init__(self, conf):
152 self.conf = conf
153
154 def get(self, item_name, default_value=None):
155 try:
156 return self.conf.get("image", item_name)
157 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
158 return default_value
159
160 @property
161 def host(self):
162 """Host IP for making Images API requests. Defaults to '127.0.0.1'."""
163 return self.get("host", "127.0.0.1")
164
165 @property
166 def port(self):
167 """Listen port of the Images service."""
168 return int(self.get("port", "9292"))
169
170 @property
171 def api_version(self):
172 """Version of the API"""
173 return self.get("api_version", "1")
174
175 @property
176 def username(self):
177 """Username to use for Images API requests. Defaults to 'admin'."""
178 return self.get("user", "admin")
179
180 @property
181 def password(self):
182 """Password for user"""
183 return self.get("password", "")
184
185 @property
186 def tenant(self):
187 """Tenant to use for Images API requests. Defaults to 'admin'."""
188 return self.get("tenant", "admin")
189
190 @property
191 def service_token(self):
192 """Token to use in querying the API. Default: None"""
193 return self.get("service_token")
194
195 @property
196 def auth_url(self):
197 """Optional URL to auth service. Will be discovered if None"""
198 return self.get("auth_url")
199
200
Daryl Wallecked8bef32011-12-05 23:02:08 -0600201class TempestConfig(object):
Daryl Walleck1465d612011-11-02 02:22:15 -0500202 """Provides OpenStack configuration information."""
203
Brian Waldon738cd632011-12-12 18:45:09 -0500204 DEFAULT_CONFIG_DIR = os.path.join(
205 os.path.abspath(
206 os.path.dirname(
207 os.path.dirname(__file__))),
208 "etc")
Daryl Walleck1465d612011-11-02 02:22:15 -0500209
Brian Waldon738cd632011-12-12 18:45:09 -0500210 DEFAULT_CONFIG_FILE = "tempest.conf"
211
212 def __init__(self):
213 """Initialize a configuration from a conf directory and conf file."""
214
215 # Environment variables override defaults...
216 conf_dir = os.environ.get('TEMPEST_CONFIG_DIR',
217 self.DEFAULT_CONFIG_DIR)
218 conf_file = os.environ.get('TEMPEST_CONFIG',
219 self.DEFAULT_CONFIG_FILE)
220
Jay Pipes7f757632011-12-02 15:53:32 -0500221 path = os.path.join(conf_dir, conf_file)
222
223 if not os.path.exists(path):
224 msg = "Config file %(path)s not found" % locals()
225 raise RuntimeError(msg)
226
227 self._conf = self.load_config(path)
Daryl Walleck587385b2012-03-03 13:00:26 -0600228 self.compute = ComputeConfig(self._conf)
229 self.identity = IdentityConfig(self._conf)
Jay Pipes50677282012-01-06 15:39:20 -0500230 self.images = ImagesConfig(self._conf)
Daryl Walleck1465d612011-11-02 02:22:15 -0500231
Jay Pipes7f757632011-12-02 15:53:32 -0500232 def load_config(self, path):
Daryl Walleck1465d612011-11-02 02:22:15 -0500233 """Read configuration from given path and return a config object."""
234 config = ConfigParser.SafeConfigParser()
235 config.read(path)
236 return config