~ubuntu-branches/ubuntu/vivid/openstack-trove/vivid

« back to all changes in this revision

Viewing changes to trove/guestagent/datastore/postgresql/service/users.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, James Page
  • Date: 2015-03-30 11:22:26 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20150330112226-op8vdoaqypjn9ghs
Tags: 2015.1~b3-0ubuntu1
[ Chuck Short ]
* New upstream release.
  - d/control: Align with upstream dependencies.
  - d/p/fix-requirements.patch: Rebased
  - d/p/patch-default-config-file.patch: Rebased

[ James Page ]
* d/rules,control: Tweak unit test execution, add subunit to BD's.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2013 OpenStack Foundation
2
 
# All Rights Reserved.
3
 
#
4
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
 
#    not use this file except in compliance with the License. You may obtain
6
 
#    a copy of the License at
7
 
#
8
 
#         http://www.apache.org/licenses/LICENSE-2.0
9
 
#
10
 
#    Unless required by applicable law or agreed to in writing, software
11
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
 
#    License for the specific language governing permissions and limitations
14
 
#    under the License.
15
 
 
16
 
import itertools
17
 
from trove.common import cfg
18
 
from trove.guestagent.datastore.postgresql import pgutil
19
 
from trove.guestagent.datastore.postgresql.service.access import PgSqlAccess
20
 
from trove.openstack.common import log as logging
21
 
from trove.common.i18n import _
22
 
 
23
 
LOG = logging.getLogger(__name__)
24
 
CONF = cfg.CONF
25
 
IGNORE_USERS_LIST = CONF.get(CONF.datastore_manager).ignore_users
26
 
 
27
 
 
28
 
class PgSqlUsers(PgSqlAccess):
29
 
    """Mixin implementing the user CRUD API.
30
 
 
31
 
    This mixin has a dependency on the PgSqlAccess mixin.
32
 
    """
33
 
 
34
 
    def create_user(self, context, users):
35
 
        """Create users and grant privileges for the specified databases.
36
 
 
37
 
        The users parameter is a list of dictionaries in the following form:
38
 
 
39
 
            {"_name": "", "_password": "", "_databases": [{"_name": ""}, ...]}
40
 
        """
41
 
        for user in users:
42
 
            LOG.debug(
43
 
                "{guest_id}: Creating user {name} with password {password}."
44
 
                .format(
45
 
                    guest_id=CONF.guest_id,
46
 
                    name=user['_name'],
47
 
                    password=user['_password'],
48
 
                )
49
 
            )
50
 
            LOG.info(
51
 
                _("{guest_id}: Creating user {name} with password {password}.")
52
 
                .format(
53
 
                    guest_id=CONF.guest_id,
54
 
                    name=user['_name'],
55
 
                    password="<SANITIZED>",
56
 
                )
57
 
            )
58
 
            pgutil.psql(
59
 
                pgutil.UserQuery.create(
60
 
                    name=user['_name'],
61
 
                    password=user['_password'],
62
 
                ),
63
 
                timeout=30,
64
 
            )
65
 
            self.grant_access(
66
 
                context,
67
 
                user['_name'],
68
 
                None,
69
 
                [d['_name'] for d in user['_databases']],
70
 
            )
71
 
 
72
 
    def list_users(
73
 
            self,
74
 
            context,
75
 
            limit=None,
76
 
            marker=None,
77
 
            include_marker=False,
78
 
    ):
79
 
        """List all users on the instance along with their access permissions.
80
 
 
81
 
        Return value is a list of dictionaries in the following form:
82
 
 
83
 
            [{"_name": "", "_password": None, "_host": None,
84
 
              "_databases": [{"_name": ""}, ...]}, ...]
85
 
        """
86
 
        results = pgutil.query(
87
 
            pgutil.UserQuery.list(ignore=IGNORE_USERS_LIST),
88
 
            timeout=30,
89
 
        )
90
 
        # Convert results into dictionaries.
91
 
        results = (
92
 
            {
93
 
                '_name': r[0].strip(),
94
 
                '_password': None,
95
 
                '_host': None,
96
 
                '_databases': self.list_access(context, r[0], None),
97
 
            }
98
 
            for r in results
99
 
        )
100
 
 
101
 
        # Force __iter__ of generator until marker found.
102
 
        if marker is not None:
103
 
            try:
104
 
                item = results.next()
105
 
                while item['_name'] != marker:
106
 
                    item = results.next()
107
 
            except StopIteration:
108
 
                pass
109
 
 
110
 
        remainder = None
111
 
        if limit is not None:
112
 
            remainder = results
113
 
            results = itertools.islice(results, limit)
114
 
 
115
 
        results = tuple(results)
116
 
 
117
 
        next_marker = None
118
 
        if remainder is not None:
119
 
            try:
120
 
                next_marker = remainder.next()
121
 
            except StopIteration:
122
 
                pass
123
 
 
124
 
        return results, next_marker
125
 
 
126
 
    def delete_user(self, context, user):
127
 
        """Delete the specified user.
128
 
 
129
 
        The user parameter is a dictionary in the following form:
130
 
 
131
 
            {"_name": ""}
132
 
        """
133
 
        LOG.info(
134
 
            _("{guest_id}: Dropping user {name}.").format(
135
 
                guest_id=CONF.guest_id,
136
 
                name=user['_name'],
137
 
            )
138
 
        )
139
 
        pgutil.psql(
140
 
            pgutil.UserQuery.drop(name=user['_name']),
141
 
            timeout=30,
142
 
        )
143
 
 
144
 
    def get_user(self, context, username, hostname):
145
 
        """Return a single user matching the criteria.
146
 
 
147
 
        The username and hostname parameter are strings.
148
 
 
149
 
        The return value is a dictionary in the following form:
150
 
 
151
 
            {"_name": "", "_host": None, "_password": None,
152
 
             "_databases": [{"_name": ""}, ...]}
153
 
 
154
 
        Where "_databases" is a list of databases the user has access to.
155
 
        """
156
 
        results = pgutil.query(
157
 
            pgutil.UserQuery.get(name=username),
158
 
            timeout=30,
159
 
        )
160
 
        results = tuple(results)
161
 
        if len(results) < 1:
162
 
            return None
163
 
 
164
 
        return {
165
 
            "_name": results[0][0],
166
 
            "_host": None,
167
 
            "_password": None,
168
 
            "_databases": self.list_access(context, username, None),
169
 
        }
170
 
 
171
 
    def change_passwords(self, context, users):
172
 
        """Change the passwords of one or more existing users.
173
 
 
174
 
        The users parameter is a list of dictionaries in the following form:
175
 
 
176
 
            {"name": "", "password": ""}
177
 
        """
178
 
        for user in users:
179
 
            LOG.debug(
180
 
                "{guest_id}: Changing password for {user} to {password}."
181
 
                .format(
182
 
                    guest_id=CONF.guest_id,
183
 
                    user=user['name'],
184
 
                    password=user['password'],
185
 
                )
186
 
            )
187
 
            LOG.info(
188
 
                _("{guest_id}: Changing password for {user} to {password}.")
189
 
                .format(
190
 
                    guest_id=CONF.guest_id,
191
 
                    user=user['name'],
192
 
                    password="<SANITIZED>",
193
 
                )
194
 
            )
195
 
            pgutil.psql(
196
 
                pgutil.UserQuery.update_password(
197
 
                    user=user['name'],
198
 
                    password=user['password'],
199
 
                ),
200
 
                timeout=30,
201
 
            )
202
 
 
203
 
    def update_attributes(self, context, username, hostname, user_attrs):
204
 
        """Change the attributes of one existing user.
205
 
 
206
 
        The username and hostname parameters are strings.
207
 
        The user_attrs parameter is a dictionary in the following form:
208
 
 
209
 
            {"password": "", "name": ""}
210
 
 
211
 
        Each key/value pair in user_attrs is optional.
212
 
        """
213
 
        if user_attrs.get('password') is not None:
214
 
            self.change_passwords(
215
 
                context,
216
 
                (
217
 
                    {
218
 
                        "name": username,
219
 
                        "password": user_attrs['password'],
220
 
                    },
221
 
                ),
222
 
            )
223
 
 
224
 
        if user_attrs.get('name') is not None:
225
 
            access = self.list_access(context, username, None)
226
 
            LOG.info(
227
 
                _("{guest_id}: Changing username for {old} to {new}.").format(
228
 
                    guest_id=CONF.guest_id,
229
 
                    old=username,
230
 
                    new=user_attrs['name'],
231
 
                )
232
 
            )
233
 
            pgutil.psql(
234
 
                pgutil.psql.UserQuery.update_name(
235
 
                    old=username,
236
 
                    new=user_attrs['name'],
237
 
                ),
238
 
                timeout=30,
239
 
            )
240
 
            # Regrant all previous access after the name change.
241
 
            LOG.info(
242
 
                _("{guest_id}: Regranting permissions from {old} to {new}.")
243
 
                .format(
244
 
                    guest_id=CONF.guest_id,
245
 
                    old=username,
246
 
                    new=user_attrs['name'],
247
 
                )
248
 
            )
249
 
            self.grant_access(
250
 
                context,
251
 
                username=user_attrs['name'],
252
 
                hostname=None,
253
 
                databases=(db['_name'] for db in access)
254
 
            )