~soren/nova/lp658257

« back to all changes in this revision

Viewing changes to nova/auth/dbdriver.py

  • Committer: Tarmac
  • Author(s): Soren Hansen
  • Date: 2010-10-04 19:23:38 UTC
  • mfrom: (306.3.5 redisectomy)
  • Revision ID: hudson@openstack.org-20101004192338-ga19zarvlnbmvk2g
A shiny, new Auth driver backed by SQLAlchemy. Read it and weep. I did.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2010 United States Government as represented by the
 
4
# Administrator of the National Aeronautics and Space Administration.
 
5
# All Rights Reserved.
 
6
#
 
7
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
8
#    not use this file except in compliance with the License. You may obtain
 
9
#    a copy of the License at
 
10
#
 
11
#         http://www.apache.org/licenses/LICENSE-2.0
 
12
#
 
13
#    Unless required by applicable law or agreed to in writing, software
 
14
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
15
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
16
#    License for the specific language governing permissions and limitations
 
17
#    under the License.
 
18
 
 
19
"""
 
20
Auth driver using the DB as its backend.
 
21
"""
 
22
 
 
23
import logging
 
24
import sys
 
25
 
 
26
from nova import exception
 
27
from nova import db
 
28
 
 
29
 
 
30
class DbDriver(object):
 
31
    """DB Auth driver
 
32
 
 
33
    Defines enter and exit and therefore supports the with/as syntax.
 
34
    """
 
35
 
 
36
    def __init__(self):
 
37
        """Imports the LDAP module"""
 
38
        pass
 
39
        db
 
40
 
 
41
    def __enter__(self):
 
42
        return self
 
43
 
 
44
    def __exit__(self, exc_type, exc_value, traceback):
 
45
        pass
 
46
 
 
47
    def get_user(self, uid):
 
48
        """Retrieve user by id"""
 
49
        return self._db_user_to_auth_user(db.user_get({}, uid))
 
50
 
 
51
    def get_user_from_access_key(self, access):
 
52
        """Retrieve user by access key"""
 
53
        return self._db_user_to_auth_user(db.user_get_by_access_key({}, access))
 
54
 
 
55
    def get_project(self, pid):
 
56
        """Retrieve project by id"""
 
57
        return self._db_project_to_auth_projectuser(db.project_get({}, pid))
 
58
 
 
59
    def get_users(self):
 
60
        """Retrieve list of users"""
 
61
        return [self._db_user_to_auth_user(user) for user in db.user_get_all({})]
 
62
 
 
63
    def get_projects(self, uid=None):
 
64
        """Retrieve list of projects"""
 
65
        if uid:
 
66
            result = db.project_get_by_user({}, uid)
 
67
        else:
 
68
            result = db.project_get_all({})
 
69
        return [self._db_project_to_auth_projectuser(proj) for proj in result]
 
70
 
 
71
    def create_user(self, name, access_key, secret_key, is_admin):
 
72
        """Create a user"""
 
73
        values = { 'id'         : name,
 
74
                   'access_key' : access_key,
 
75
                   'secret_key' : secret_key,
 
76
                   'is_admin'   : is_admin
 
77
                 }
 
78
        try:
 
79
            user_ref = db.user_create({}, values)
 
80
            return self._db_user_to_auth_user(user_ref)
 
81
        except exception.Duplicate, e:
 
82
            raise exception.Duplicate('User %s already exists' % name)
 
83
 
 
84
    def _db_user_to_auth_user(self, user_ref):
 
85
        return { 'id'     : user_ref['id'],
 
86
                 'name'   : user_ref['id'],
 
87
                 'access' : user_ref['access_key'],
 
88
                 'secret' : user_ref['secret_key'],
 
89
                 'admin'  : user_ref['is_admin'] }
 
90
 
 
91
    def _db_project_to_auth_projectuser(self, project_ref):
 
92
        return { 'id'                 : project_ref['id'],
 
93
                 'name'               : project_ref['name'],
 
94
                 'project_manager_id' : project_ref['project_manager'],
 
95
                 'description'        : project_ref['description'],
 
96
                 'member_ids'         : [member['id'] for member in project_ref['members']] }
 
97
 
 
98
    def create_project(self, name, manager_uid,
 
99
                       description=None, member_uids=None):
 
100
        """Create a project"""
 
101
        manager = db.user_get({}, manager_uid)
 
102
        if not manager:
 
103
            raise exception.NotFound("Project can't be created because "
 
104
                                     "manager %s doesn't exist" % manager_uid)
 
105
 
 
106
        # description is a required attribute
 
107
        if description is None:
 
108
            description = name
 
109
 
 
110
        # First, we ensure that all the given users exist before we go
 
111
        # on to create the project. This way we won't have to destroy
 
112
        # the project again because a user turns out to be invalid.
 
113
        members = set([manager])
 
114
        if member_uids != None:
 
115
            for member_uid in member_uids:
 
116
                member = db.user_get({}, member_uid)
 
117
                if not member:
 
118
                    raise exception.NotFound("Project can't be created "
 
119
                                             "because user %s doesn't exist"
 
120
                                             % member_uid)
 
121
                members.add(member)
 
122
 
 
123
        values = { 'id'         : name,
 
124
                   'name'       : name,
 
125
                   'project_manager' : manager['id'],
 
126
                   'description': description }
 
127
 
 
128
        try:
 
129
            project = db.project_create({}, values)
 
130
        except exception.Duplicate:
 
131
            raise exception.Duplicate("Project can't be created because "
 
132
                                      "project %s already exists" % name)
 
133
 
 
134
        for member in members:
 
135
            db.project_add_member({}, project['id'], member['id'])
 
136
 
 
137
        # This looks silly, but ensures that the members element has been
 
138
        # correctly populated
 
139
        project_ref = db.project_get({}, project['id'])
 
140
        return self._db_project_to_auth_projectuser(project_ref)
 
141
 
 
142
    def modify_project(self, project_id, manager_uid=None, description=None):
 
143
        """Modify an existing project"""
 
144
        if not manager_uid and not description:
 
145
            return
 
146
        values = {}
 
147
        if manager_uid:
 
148
            manager = db.user_get({}, manager_uid)
 
149
            if not manager:
 
150
                raise exception.NotFound("Project can't be modified because "
 
151
                                          "manager %s doesn't exist" %
 
152
                                          manager_uid)
 
153
            values['project_manager'] = manager['id']
 
154
        if description:
 
155
            values['description'] = description
 
156
 
 
157
        db.project_update({}, project_id, values)
 
158
 
 
159
    def add_to_project(self, uid, project_id):
 
160
        """Add user to project"""
 
161
        user, project = self._validate_user_and_project(uid, project_id)
 
162
        db.project_add_member({}, project['id'], user['id'])
 
163
 
 
164
    def remove_from_project(self, uid, project_id):
 
165
        """Remove user from project"""
 
166
        user, project = self._validate_user_and_project(uid, project_id)
 
167
        db.project_remove_member({}, project['id'], user['id'])
 
168
 
 
169
    def is_in_project(self, uid, project_id):
 
170
        """Check if user is in project"""
 
171
        user, project = self._validate_user_and_project(uid, project_id)
 
172
        return user in project.members
 
173
 
 
174
    def has_role(self, uid, role, project_id=None):
 
175
        """Check if user has role
 
176
 
 
177
        If project is specified, it checks for local role, otherwise it
 
178
        checks for global role
 
179
        """
 
180
 
 
181
        return role in self.get_user_roles(uid, project_id)
 
182
 
 
183
    def add_role(self, uid, role, project_id=None):
 
184
        """Add role for user (or user and project)"""
 
185
        if not project_id:
 
186
            db.user_add_role({}, uid, role)
 
187
            return
 
188
        db.user_add_project_role({}, uid, project_id, role)
 
189
 
 
190
    def remove_role(self, uid, role, project_id=None):
 
191
        """Remove role for user (or user and project)"""
 
192
        if not project_id:
 
193
            db.user_remove_role({}, uid, role)
 
194
            return
 
195
        db.user_remove_project_role({}, uid, project_id, role)
 
196
 
 
197
    def get_user_roles(self, uid, project_id=None):
 
198
        """Retrieve list of roles for user (or user and project)"""
 
199
        if project_id is None:
 
200
            roles = db.user_get_roles({}, uid)
 
201
            return roles
 
202
        else:
 
203
            roles = db.user_get_roles_for_project({}, uid, project_id)
 
204
            return roles
 
205
 
 
206
    def delete_user(self, id):
 
207
        """Delete a user"""
 
208
        user = db.user_get({}, id)
 
209
        db.user_delete({}, user['id'])
 
210
 
 
211
    def delete_project(self, project_id):
 
212
        """Delete a project"""
 
213
        db.project_delete({}, project_id)
 
214
 
 
215
    def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
 
216
        """Modify an existing user"""
 
217
        if not access_key and not secret_key and admin is None:
 
218
            return
 
219
        values = {}
 
220
        if access_key:
 
221
            values['access_key'] = access_key
 
222
        if secret_key:
 
223
            values['secret_key'] = secret_key
 
224
        if admin is not None:
 
225
            values['is_admin'] = admin
 
226
        db.user_update({}, uid, values)
 
227
 
 
228
    def _validate_user_and_project(self, user_id, project_id):
 
229
        user = db.user_get({}, user_id)
 
230
        if not user:
 
231
            raise exception.NotFound('User "%s" not found' % user_id)
 
232
        project = db.project_get({}, project_id)
 
233
        if not project:
 
234
            raise exception.NotFound('Project "%s" not found' % project_id)
 
235
        return user, project
 
236