blob: ee3bf9e2605eaa6a03f98d6c4e0e44165f617bf2 [file] [log] [blame]
Jay Pipes13b479b2012-06-11 14:52:27 -04001# 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
Jay Pipesf38eaac2012-06-21 13:37:35 -040018import logging
David Kranzcf0040c2012-06-26 09:46:56 -040019import time
Rohit Karajgidd47d7e2012-07-31 04:11:01 -070020import nose
Jay Pipesf38eaac2012-06-21 13:37:35 -040021
Jay Pipes13b479b2012-06-11 14:52:27 -040022import unittest2 as unittest
Wayne Vestal Weeks383c71d2012-09-12 16:21:17 -040023import nose
Jay Pipes13b479b2012-06-11 14:52:27 -040024
Jay Pipesf38eaac2012-06-21 13:37:35 -040025from tempest import config
Daryl Walleckc7251962012-03-12 17:26:54 -050026from tempest import openstack
Wayne Vestal Weeks383c71d2012-09-12 16:21:17 -040027from tempest import exceptions
Rohit Karajgidc300b22012-05-04 08:11:00 -070028from tempest.common.utils.data_utils import rand_name
Jay Pipesf38eaac2012-06-21 13:37:35 -040029from tempest.services.identity.json.admin_client import AdminClient
30
Tiago Melloeda03b52012-08-22 23:47:29 -030031__all__ = ['BaseComputeTest', 'BaseComputeTestJSON', 'BaseComputeTestXML',
32 'BaseComputeAdminTestJSON', 'BaseComputeAdminTestXML']
33
Jay Pipesf38eaac2012-06-21 13:37:35 -040034LOG = logging.getLogger(__name__)
Daryl Walleckc7251962012-03-12 17:26:54 -050035
36
Matthew Treinish4e086902012-08-17 17:52:22 -040037class BaseCompTest(unittest.TestCase):
Daryl Walleckc7251962012-03-12 17:26:54 -050038
Jay Pipesf38eaac2012-06-21 13:37:35 -040039 """Base test case class for all Compute API tests"""
Daryl Walleckc7251962012-03-12 17:26:54 -050040
Jay Pipesf38eaac2012-06-21 13:37:35 -040041 @classmethod
42 def setUpClass(cls):
43 cls.config = config.TempestConfig()
44 cls.isolated_creds = []
45
46 if cls.config.compute.allow_tenant_isolation:
47 creds = cls._get_isolated_creds()
48 username, tenant_name, password = creds
49 os = openstack.Manager(username=username,
50 password=password,
Dan Smithcf8fab62012-08-14 08:03:48 -070051 tenant_name=tenant_name,
52 interface=cls._interface)
Daryl Walleckc7251962012-03-12 17:26:54 -050053 else:
Dan Smithcf8fab62012-08-14 08:03:48 -070054 os = openstack.Manager(interface=cls._interface)
Daryl Walleckc7251962012-03-12 17:26:54 -050055
Jay Pipesf38eaac2012-06-21 13:37:35 -040056 cls.os = os
57 cls.servers_client = os.servers_client
58 cls.flavors_client = os.flavors_client
59 cls.images_client = os.images_client
60 cls.extensions_client = os.extensions_client
61 cls.floating_ips_client = os.floating_ips_client
62 cls.keypairs_client = os.keypairs_client
Jay Pipesf38eaac2012-06-21 13:37:35 -040063 cls.security_groups_client = os.security_groups_client
64 cls.console_outputs_client = os.console_outputs_client
65 cls.limits_client = os.limits_client
Rohit Karajgidd47d7e2012-07-31 04:11:01 -070066 cls.volumes_extensions_client = os.volumes_extensions_client
Jay Pipesf38eaac2012-06-21 13:37:35 -040067 cls.volumes_client = os.volumes_client
68 cls.build_interval = cls.config.compute.build_interval
69 cls.build_timeout = cls.config.compute.build_timeout
70 cls.ssh_user = cls.config.compute.ssh_user
71 cls.image_ref = cls.config.compute.image_ref
72 cls.image_ref_alt = cls.config.compute.image_ref_alt
73 cls.flavor_ref = cls.config.compute.flavor_ref
74 cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
75 cls.servers = []
Daryl Walleckc7251962012-03-12 17:26:54 -050076
Jay Pipesf38eaac2012-06-21 13:37:35 -040077 @classmethod
78 def _get_identity_admin_client(cls):
79 """
80 Returns an instance of the Identity Admin API client
81 """
82 client_args = (cls.config,
83 cls.config.identity_admin.username,
84 cls.config.identity_admin.password,
85 cls.config.identity.auth_url)
86 tenant_name = cls.config.identity_admin.tenant_name
87 admin_client = AdminClient(*client_args, tenant_name=tenant_name)
88 return admin_client
Daryl Walleckc7251962012-03-12 17:26:54 -050089
Jay Pipesf38eaac2012-06-21 13:37:35 -040090 @classmethod
91 def _get_isolated_creds(cls):
92 """
93 Creates a new set of user/tenant/password credentials for a
94 **regular** user of the Compute API so that a test case can
95 operate in an isolated tenant container.
96 """
97 admin_client = cls._get_identity_admin_client()
98 rand_name_root = cls.__name__
99 if cls.isolated_creds:
100 # Main user already created. Create the alt one...
101 rand_name_root += '-alt'
102 username = rand_name_root + "-user"
103 email = rand_name_root + "@example.com"
104 tenant_name = rand_name_root + "-tenant"
105 tenant_desc = tenant_name + "-desc"
106 password = "pass"
107
Dan Smithd6ff6b72012-08-23 10:29:41 -0700108 try:
109 resp, tenant = admin_client.create_tenant(name=tenant_name,
110 description=tenant_desc)
111 except exceptions.Duplicate:
112 if cls.config.compute.allow_tenant_reuse:
113 tenant = admin_client.get_tenant_by_name(tenant_name)
114 LOG.info('Re-using existing tenant %s' % tenant)
115 else:
116 msg = ('Unable to create isolated tenant %s because ' +
117 'it already exists. If this is related to a ' +
118 'previous test failure, try using ' +
119 'allow_tentant_reuse in tempest.conf') % tenant_name
120 raise exceptions.Duplicate(msg)
121
122 try:
123 resp, user = admin_client.create_user(username,
124 password,
125 tenant['id'],
126 email)
127 except exceptions.Duplicate:
128 if cls.config.compute.allow_tenant_reuse:
129 user = admin_client.get_user_by_username(tenant['id'],
130 username)
131 LOG.info('Re-using existing user %s' % user)
132 else:
133 msg = ('Unable to create isolated tenant %s because ' +
134 'it already exists. If this is related to a ' +
135 'previous test failure, try using ' +
136 'allow_tentant_reuse in tempest.conf') % tenant_name
137 raise exceptions.Duplicate(msg)
138
Jay Pipesf38eaac2012-06-21 13:37:35 -0400139 # Store the complete creds (including UUID ids...) for later
140 # but return just the username, tenant_name, password tuple
141 # that the various clients will use.
142 cls.isolated_creds.append((user, tenant))
143
144 return username, tenant_name, password
145
146 @classmethod
147 def clear_isolated_creds(cls):
148 if not cls.isolated_creds:
149 pass
150 admin_client = cls._get_identity_admin_client()
151
152 for user, tenant in cls.isolated_creds:
153 admin_client.delete_user(user['id'])
154 admin_client.delete_tenant(tenant['id'])
155
156 @classmethod
Dan Smith74e7bcb2012-08-21 09:18:26 -0700157 def clear_remaining_servers(cls):
158 # NOTE(danms): Only nuke all left-over servers if we're in our
159 # own isolated tenant
160 if not cls.isolated_creds:
161 return
162 resp, servers = cls.servers_client.list_servers()
163 for server in servers['servers']:
164 try:
165 cls.servers_client.delete_server(server['id'])
166 except Exception:
167 pass
168
169 for server in servers['servers']:
170 try:
171 cls.servers_client.wait_for_server_termination(server['id'])
172 except Exception:
173 pass
174
175 @classmethod
Jay Pipesf38eaac2012-06-21 13:37:35 -0400176 def tearDownClass(cls):
Dan Smith74e7bcb2012-08-21 09:18:26 -0700177 cls.clear_remaining_servers()
Jay Pipesf38eaac2012-06-21 13:37:35 -0400178 cls.clear_isolated_creds()
Rohit Karajgidc300b22012-05-04 08:11:00 -0700179
180 def create_server(self, image_id=None):
181 """Wrapper utility that returns a test server"""
Jay Pipesf38eaac2012-06-21 13:37:35 -0400182 server_name = rand_name(self.__class__.__name__ + "-instance")
Rohit Karajgidc300b22012-05-04 08:11:00 -0700183 flavor = self.flavor_ref
184 if not image_id:
185 image_id = self.image_ref
186
187 resp, server = self.servers_client.create_server(
188 server_name, image_id, flavor)
189 self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
190 self.servers.append(server)
191 return server
David Kranzcf0040c2012-06-26 09:46:56 -0400192
193 def wait_for(self, condition):
194 """Repeatedly calls condition() until a timeout"""
195 start_time = int(time.time())
196 while True:
197 try:
198 condition()
199 except:
200 pass
201 else:
202 return
203 if int(time.time()) - start_time >= self.build_timeout:
204 condition()
205 return
206 time.sleep(self.build_interval)
Jay Pipesf38eaac2012-06-21 13:37:35 -0400207
208
Matthew Treinish4e086902012-08-17 17:52:22 -0400209class BaseComputeTestJSON(BaseCompTest):
Dan Smithcf8fab62012-08-14 08:03:48 -0700210 @classmethod
211 def setUpClass(cls):
212 cls._interface = "json"
213 super(BaseComputeTestJSON, cls).setUpClass()
214
215# NOTE(danms): For transition, keep the old name active as JSON
216BaseComputeTest = BaseComputeTestJSON
217
218
Matthew Treinish4e086902012-08-17 17:52:22 -0400219class BaseComputeTestXML(BaseCompTest):
Dan Smithcf8fab62012-08-14 08:03:48 -0700220 @classmethod
221 def setUpClass(cls):
222 cls._interface = "xml"
223 super(BaseComputeTestXML, cls).setUpClass()
224
225
Jay Pipesf38eaac2012-06-21 13:37:35 -0400226class BaseComputeAdminTest(unittest.TestCase):
227
228 """Base test case class for all Compute Admin API tests"""
229
230 @classmethod
231 def setUpClass(cls):
232 cls.config = config.TempestConfig()
233 cls.admin_username = cls.config.compute_admin.username
234 cls.admin_password = cls.config.compute_admin.password
235 cls.admin_tenant = cls.config.compute_admin.tenant_name
236
237 if not cls.admin_username and cls.admin_password and cls.admin_tenant:
238 msg = ("Missing Compute Admin API credentials "
239 "in configuration.")
240 raise nose.SkipTest(msg)
241
Tiago Melloeda03b52012-08-22 23:47:29 -0300242 cls.os = openstack.AdminManager(interface=cls._interface)
243
244
245class BaseComputeAdminTestJSON(BaseComputeAdminTest):
246 @classmethod
247 def setUpClass(cls):
248 cls._interface = "json"
249 super(BaseComputeAdminTestJSON, cls).setUpClass()
250
251
252class BaseComputeAdminTestXML(BaseComputeAdminTest):
253 @classmethod
254 def setUpClass(cls):
255 cls._interface = "xml"
256 super(BaseComputeAdminTestXML, cls).setUpClass()