~sandy-walsh/nova/zones3

« back to all changes in this revision

Viewing changes to nova/tests/integrated/integrated_helpers.py

  • Committer: Sandy Walsh
  • Date: 2011-03-23 19:31:49 UTC
  • mfrom: (635.1.218 nova)
  • Revision ID: sandy.walsh@rackspace.com-20110323193149-ru7x3l3mabrssaup
trunk merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2011 Justin Santa Barbara
 
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
 
 
18
"""
 
19
Provides common functionality for integrated unit tests
 
20
"""
 
21
 
 
22
import random
 
23
import string
 
24
 
 
25
from nova import exception
 
26
from nova import flags
 
27
from nova import service
 
28
from nova import test  # For the flags
 
29
from nova.auth import manager
 
30
from nova.exception import Error
 
31
from nova.log import logging
 
32
from nova.tests.integrated.api import client
 
33
 
 
34
 
 
35
FLAGS = flags.FLAGS
 
36
 
 
37
LOG = logging.getLogger('nova.tests.integrated')
 
38
 
 
39
 
 
40
def generate_random_alphanumeric(length):
 
41
    """Creates a random alphanumeric string of specified length"""
 
42
    return ''.join(random.choice(string.ascii_uppercase + string.digits)
 
43
                   for _x in range(length))
 
44
 
 
45
 
 
46
def generate_random_numeric(length):
 
47
    """Creates a random numeric string of specified length"""
 
48
    return ''.join(random.choice(string.digits)
 
49
                   for _x in range(length))
 
50
 
 
51
 
 
52
def generate_new_element(items, prefix, numeric=False):
 
53
    """Creates a random string with prefix, that is not in 'items' list"""
 
54
    while True:
 
55
        if numeric:
 
56
            candidate = prefix + generate_random_numeric(8)
 
57
        else:
 
58
            candidate = prefix + generate_random_alphanumeric(8)
 
59
        if not candidate in items:
 
60
            return candidate
 
61
        print "Random collision on %s" % candidate
 
62
 
 
63
 
 
64
class TestUser(object):
 
65
    def __init__(self, name, secret, auth_url):
 
66
        self.name = name
 
67
        self.secret = secret
 
68
        self.auth_url = auth_url
 
69
 
 
70
        if not auth_url:
 
71
            raise exception.Error("auth_url is required")
 
72
        self.openstack_api = client.TestOpenStackClient(self.name,
 
73
                                                        self.secret,
 
74
                                                        self.auth_url)
 
75
 
 
76
 
 
77
class IntegratedUnitTestContext(object):
 
78
    __INSTANCE = None
 
79
 
 
80
    def __init__(self):
 
81
        self.auth_manager = manager.AuthManager()
 
82
 
 
83
        self.wsgi_server = None
 
84
        self.wsgi_apps = []
 
85
        self.api_service = None
 
86
 
 
87
        self.services = []
 
88
        self.auth_url = None
 
89
        self.project_name = None
 
90
 
 
91
        self.setup()
 
92
 
 
93
    def setup(self):
 
94
        self._start_services()
 
95
 
 
96
        self._create_test_user()
 
97
 
 
98
    def _create_test_user(self):
 
99
        self.test_user = self._create_unittest_user()
 
100
 
 
101
        # No way to currently pass this through the OpenStack API
 
102
        self.project_name = 'openstack'
 
103
        self._configure_project(self.project_name, self.test_user)
 
104
 
 
105
    def _start_services(self):
 
106
        # WSGI shutdown broken :-(
 
107
        # bug731668
 
108
        if not self.api_service:
 
109
            self._start_api_service()
 
110
 
 
111
    def cleanup(self):
 
112
        for service in self.services:
 
113
            service.kill()
 
114
        self.services = []
 
115
        # TODO(justinsb): Shutdown WSGI & anything else we startup
 
116
        # bug731668
 
117
        # WSGI shutdown broken :-(
 
118
        # self.wsgi_server.terminate()
 
119
        # self.wsgi_server = None
 
120
        self.test_user = None
 
121
 
 
122
    def _create_unittest_user(self):
 
123
        users = self.auth_manager.get_users()
 
124
        user_names = [user.name for user in users]
 
125
        auth_name = generate_new_element(user_names, 'unittest_user_')
 
126
        auth_key = generate_random_alphanumeric(16)
 
127
 
 
128
        # Right now there's a bug where auth_name and auth_key are reversed
 
129
        # bug732907
 
130
        auth_key = auth_name
 
131
 
 
132
        self.auth_manager.create_user(auth_name, auth_name, auth_key, False)
 
133
        return TestUser(auth_name, auth_key, self.auth_url)
 
134
 
 
135
    def _configure_project(self, project_name, user):
 
136
        projects = self.auth_manager.get_projects()
 
137
        project_names = [project.name for project in projects]
 
138
        if not project_name in project_names:
 
139
            project = self.auth_manager.create_project(project_name,
 
140
                                                       user.name,
 
141
                                                       description=None,
 
142
                                                       member_users=None)
 
143
        else:
 
144
            self.auth_manager.add_to_project(user.name, project_name)
 
145
 
 
146
    def _start_api_service(self):
 
147
        api_service = service.ApiService.create()
 
148
        api_service.start()
 
149
 
 
150
        if not api_service:
 
151
            raise Exception("API Service was None")
 
152
 
 
153
        # WSGI shutdown broken :-(
 
154
        #self.services.append(volume_service)
 
155
        self.api_service = api_service
 
156
 
 
157
        self.auth_url = 'http://localhost:8774/v1.0'
 
158
 
 
159
        return api_service
 
160
 
 
161
    # WSGI shutdown broken :-(
 
162
    # bug731668
 
163
    #@staticmethod
 
164
    #def get():
 
165
    #    if not IntegratedUnitTestContext.__INSTANCE:
 
166
    #        IntegratedUnitTestContext.startup()
 
167
    #        #raise Error("Must call IntegratedUnitTestContext::startup")
 
168
    #    return IntegratedUnitTestContext.__INSTANCE
 
169
 
 
170
    @staticmethod
 
171
    def startup():
 
172
        # Because WSGI shutdown is broken at the moment, we have to recycle
 
173
        # bug731668
 
174
        if IntegratedUnitTestContext.__INSTANCE:
 
175
            #raise Error("Multiple calls to IntegratedUnitTestContext.startup")
 
176
            IntegratedUnitTestContext.__INSTANCE.setup()
 
177
        else:
 
178
            IntegratedUnitTestContext.__INSTANCE = IntegratedUnitTestContext()
 
179
        return IntegratedUnitTestContext.__INSTANCE
 
180
 
 
181
    @staticmethod
 
182
    def shutdown():
 
183
        if not IntegratedUnitTestContext.__INSTANCE:
 
184
            raise Error("Must call IntegratedUnitTestContext::startup")
 
185
        IntegratedUnitTestContext.__INSTANCE.cleanup()
 
186
        # WSGI shutdown broken :-(
 
187
        # bug731668
 
188
        #IntegratedUnitTestContext.__INSTANCE = None