blob: 8b084ffb3e57b09c9dc4511a8c02d2c8ea2cac42 [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
Jay Pipesf38eaac2012-06-21 13:37:35 -040020
Jay Pipes13b479b2012-06-11 14:52:27 -040021import unittest2 as unittest
22
Jay Pipesf38eaac2012-06-21 13:37:35 -040023from tempest import config
Daryl Walleckc7251962012-03-12 17:26:54 -050024from tempest import exceptions
25from tempest import openstack
Rohit Karajgidc300b22012-05-04 08:11:00 -070026from tempest.common.utils.data_utils import rand_name
Jay Pipesf38eaac2012-06-21 13:37:35 -040027from tempest.services.identity.json.admin_client import AdminClient
28
29LOG = logging.getLogger(__name__)
Daryl Walleckc7251962012-03-12 17:26:54 -050030
31
Dan Smithcf8fab62012-08-14 08:03:48 -070032class _BaseComputeTest(unittest.TestCase):
Daryl Walleckc7251962012-03-12 17:26:54 -050033
Jay Pipesf38eaac2012-06-21 13:37:35 -040034 """Base test case class for all Compute API tests"""
Daryl Walleckc7251962012-03-12 17:26:54 -050035
Jay Pipesf38eaac2012-06-21 13:37:35 -040036 @classmethod
37 def setUpClass(cls):
38 cls.config = config.TempestConfig()
39 cls.isolated_creds = []
40
41 if cls.config.compute.allow_tenant_isolation:
42 creds = cls._get_isolated_creds()
43 username, tenant_name, password = creds
44 os = openstack.Manager(username=username,
45 password=password,
Dan Smithcf8fab62012-08-14 08:03:48 -070046 tenant_name=tenant_name,
47 interface=cls._interface)
Daryl Walleckc7251962012-03-12 17:26:54 -050048 else:
Dan Smithcf8fab62012-08-14 08:03:48 -070049 os = openstack.Manager(interface=cls._interface)
Daryl Walleckc7251962012-03-12 17:26:54 -050050
Jay Pipesf38eaac2012-06-21 13:37:35 -040051 cls.os = os
52 cls.servers_client = os.servers_client
53 cls.flavors_client = os.flavors_client
54 cls.images_client = os.images_client
55 cls.extensions_client = os.extensions_client
56 cls.floating_ips_client = os.floating_ips_client
57 cls.keypairs_client = os.keypairs_client
Jay Pipesf38eaac2012-06-21 13:37:35 -040058 cls.security_groups_client = os.security_groups_client
59 cls.console_outputs_client = os.console_outputs_client
60 cls.limits_client = os.limits_client
61 cls.volumes_client = os.volumes_client
62 cls.build_interval = cls.config.compute.build_interval
63 cls.build_timeout = cls.config.compute.build_timeout
64 cls.ssh_user = cls.config.compute.ssh_user
65 cls.image_ref = cls.config.compute.image_ref
66 cls.image_ref_alt = cls.config.compute.image_ref_alt
67 cls.flavor_ref = cls.config.compute.flavor_ref
68 cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
69 cls.servers = []
Daryl Walleckc7251962012-03-12 17:26:54 -050070
Jay Pipesf38eaac2012-06-21 13:37:35 -040071 @classmethod
72 def _get_identity_admin_client(cls):
73 """
74 Returns an instance of the Identity Admin API client
75 """
76 client_args = (cls.config,
77 cls.config.identity_admin.username,
78 cls.config.identity_admin.password,
79 cls.config.identity.auth_url)
80 tenant_name = cls.config.identity_admin.tenant_name
81 admin_client = AdminClient(*client_args, tenant_name=tenant_name)
82 return admin_client
Daryl Walleckc7251962012-03-12 17:26:54 -050083
Jay Pipesf38eaac2012-06-21 13:37:35 -040084 @classmethod
85 def _get_isolated_creds(cls):
86 """
87 Creates a new set of user/tenant/password credentials for a
88 **regular** user of the Compute API so that a test case can
89 operate in an isolated tenant container.
90 """
91 admin_client = cls._get_identity_admin_client()
92 rand_name_root = cls.__name__
93 if cls.isolated_creds:
94 # Main user already created. Create the alt one...
95 rand_name_root += '-alt'
96 username = rand_name_root + "-user"
97 email = rand_name_root + "@example.com"
98 tenant_name = rand_name_root + "-tenant"
99 tenant_desc = tenant_name + "-desc"
100 password = "pass"
101
Dan Smithd6ff6b72012-08-23 10:29:41 -0700102 try:
103 resp, tenant = admin_client.create_tenant(name=tenant_name,
104 description=tenant_desc)
105 except exceptions.Duplicate:
106 if cls.config.compute.allow_tenant_reuse:
107 tenant = admin_client.get_tenant_by_name(tenant_name)
108 LOG.info('Re-using existing tenant %s' % tenant)
109 else:
110 msg = ('Unable to create isolated tenant %s because ' +
111 'it already exists. If this is related to a ' +
112 'previous test failure, try using ' +
113 'allow_tentant_reuse in tempest.conf') % tenant_name
114 raise exceptions.Duplicate(msg)
115
116 try:
117 resp, user = admin_client.create_user(username,
118 password,
119 tenant['id'],
120 email)
121 except exceptions.Duplicate:
122 if cls.config.compute.allow_tenant_reuse:
123 user = admin_client.get_user_by_username(tenant['id'],
124 username)
125 LOG.info('Re-using existing user %s' % user)
126 else:
127 msg = ('Unable to create isolated tenant %s because ' +
128 'it already exists. If this is related to a ' +
129 'previous test failure, try using ' +
130 'allow_tentant_reuse in tempest.conf') % tenant_name
131 raise exceptions.Duplicate(msg)
132
Jay Pipesf38eaac2012-06-21 13:37:35 -0400133 # Store the complete creds (including UUID ids...) for later
134 # but return just the username, tenant_name, password tuple
135 # that the various clients will use.
136 cls.isolated_creds.append((user, tenant))
137
138 return username, tenant_name, password
139
140 @classmethod
141 def clear_isolated_creds(cls):
142 if not cls.isolated_creds:
143 pass
144 admin_client = cls._get_identity_admin_client()
145
146 for user, tenant in cls.isolated_creds:
147 admin_client.delete_user(user['id'])
148 admin_client.delete_tenant(tenant['id'])
149
150 @classmethod
Dan Smith74e7bcb2012-08-21 09:18:26 -0700151 def clear_remaining_servers(cls):
152 # NOTE(danms): Only nuke all left-over servers if we're in our
153 # own isolated tenant
154 if not cls.isolated_creds:
155 return
156 resp, servers = cls.servers_client.list_servers()
157 for server in servers['servers']:
158 try:
159 cls.servers_client.delete_server(server['id'])
160 except Exception:
161 pass
162
163 for server in servers['servers']:
164 try:
165 cls.servers_client.wait_for_server_termination(server['id'])
166 except Exception:
167 pass
168
169 @classmethod
Jay Pipesf38eaac2012-06-21 13:37:35 -0400170 def tearDownClass(cls):
Dan Smith74e7bcb2012-08-21 09:18:26 -0700171 cls.clear_remaining_servers()
Jay Pipesf38eaac2012-06-21 13:37:35 -0400172 cls.clear_isolated_creds()
Rohit Karajgidc300b22012-05-04 08:11:00 -0700173
174 def create_server(self, image_id=None):
175 """Wrapper utility that returns a test server"""
Jay Pipesf38eaac2012-06-21 13:37:35 -0400176 server_name = rand_name(self.__class__.__name__ + "-instance")
Rohit Karajgidc300b22012-05-04 08:11:00 -0700177 flavor = self.flavor_ref
178 if not image_id:
179 image_id = self.image_ref
180
181 resp, server = self.servers_client.create_server(
182 server_name, image_id, flavor)
183 self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
184 self.servers.append(server)
185 return server
David Kranzcf0040c2012-06-26 09:46:56 -0400186
187 def wait_for(self, condition):
188 """Repeatedly calls condition() until a timeout"""
189 start_time = int(time.time())
190 while True:
191 try:
192 condition()
193 except:
194 pass
195 else:
196 return
197 if int(time.time()) - start_time >= self.build_timeout:
198 condition()
199 return
200 time.sleep(self.build_interval)
Jay Pipesf38eaac2012-06-21 13:37:35 -0400201
202
Dan Smithcf8fab62012-08-14 08:03:48 -0700203class BaseComputeTestJSON(_BaseComputeTest):
204 @classmethod
205 def setUpClass(cls):
206 cls._interface = "json"
207 super(BaseComputeTestJSON, cls).setUpClass()
208
209# NOTE(danms): For transition, keep the old name active as JSON
210BaseComputeTest = BaseComputeTestJSON
211
212
213class BaseComputeTestXML(_BaseComputeTest):
214 @classmethod
215 def setUpClass(cls):
216 cls._interface = "xml"
217 super(BaseComputeTestXML, cls).setUpClass()
218
219
Jay Pipesf38eaac2012-06-21 13:37:35 -0400220class BaseComputeAdminTest(unittest.TestCase):
221
222 """Base test case class for all Compute Admin API tests"""
223
224 @classmethod
225 def setUpClass(cls):
226 cls.config = config.TempestConfig()
227 cls.admin_username = cls.config.compute_admin.username
228 cls.admin_password = cls.config.compute_admin.password
229 cls.admin_tenant = cls.config.compute_admin.tenant_name
230
231 if not cls.admin_username and cls.admin_password and cls.admin_tenant:
232 msg = ("Missing Compute Admin API credentials "
233 "in configuration.")
234 raise nose.SkipTest(msg)
235
236 cls.os = openstack.AdminManager()