Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / astakos / __init__.py @ 493f5877

History | View | Annotate | Download (11.5 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2 43ca98ee Giorgos Verigakis
#
3 43ca98ee Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 43ca98ee Giorgos Verigakis
# without modification, are permitted provided that the following
5 43ca98ee Giorgos Verigakis
# conditions are met:
6 43ca98ee Giorgos Verigakis
#
7 43ca98ee Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 43ca98ee Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 43ca98ee Giorgos Verigakis
#      disclaimer.
10 43ca98ee Giorgos Verigakis
#
11 43ca98ee Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 43ca98ee Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 43ca98ee Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 43ca98ee Giorgos Verigakis
#      provided with the distribution.
15 43ca98ee Giorgos Verigakis
#
16 43ca98ee Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 43ca98ee Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 43ca98ee Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 43ca98ee Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 43ca98ee Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 43ca98ee Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 43ca98ee Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 43ca98ee Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 43ca98ee Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 43ca98ee Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 43ca98ee Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 43ca98ee Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 43ca98ee Giorgos Verigakis
#
29 43ca98ee Giorgos Verigakis
# The views and conclusions contained in the software and
30 43ca98ee Giorgos Verigakis
# documentation are those of the authors and should not be
31 43ca98ee Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 43ca98ee Giorgos Verigakis
# or implied, of GRNET S.A.
33 43ca98ee Giorgos Verigakis
34 528550d9 Stavros Sachtouris
from logging import getLogger
35 cd42f8d8 Stavros Sachtouris
from astakosclient import AstakosClient as OriginalAstakosClient
36 cd42f8d8 Stavros Sachtouris
from astakosclient import AstakosClientException, parse_endpoints
37 9d3cd179 Stavros Sachtouris
38 20211cbb Stavros Sachtouris
from kamaki.clients import Client, ClientError, RequestManager, recvlog
39 528550d9 Stavros Sachtouris
40 528550d9 Stavros Sachtouris
41 8b4ba753 Stavros Sachtouris
class AstakosClientError(AstakosClientException, ClientError):
42 8b4ba753 Stavros Sachtouris
    """Join AstakosClientException as ClientError in one class"""
43 8b4ba753 Stavros Sachtouris
44 8b4ba753 Stavros Sachtouris
45 8b4ba753 Stavros Sachtouris
def _astakos_error(foo):
46 8b4ba753 Stavros Sachtouris
    def wrap(self, *args, **kwargs):
47 8b4ba753 Stavros Sachtouris
        try:
48 8b4ba753 Stavros Sachtouris
            return foo(self, *args, **kwargs)
49 8b4ba753 Stavros Sachtouris
        except AstakosClientException as sace:
50 8b4ba753 Stavros Sachtouris
            raise AstakosClientError('%s' % sace, sace.status, sace.details)
51 8b4ba753 Stavros Sachtouris
    return wrap
52 8b4ba753 Stavros Sachtouris
53 8b4ba753 Stavros Sachtouris
54 cd42f8d8 Stavros Sachtouris
class AstakosClient(OriginalAstakosClient):
55 cd42f8d8 Stavros Sachtouris
    """Wrap Original AstakosClient to ensure compatibility in kamaki clients"""
56 cd42f8d8 Stavros Sachtouris
57 8b4ba753 Stavros Sachtouris
    @_astakos_error
58 cd42f8d8 Stavros Sachtouris
    def __init__(self, *args, **kwargs):
59 cd42f8d8 Stavros Sachtouris
        if args:
60 cd42f8d8 Stavros Sachtouris
            args = list(args)
61 cd42f8d8 Stavros Sachtouris
            url = args.pop(0)
62 cd42f8d8 Stavros Sachtouris
            token = args.pop(0) if args else kwargs.pop('token', None)
63 cd42f8d8 Stavros Sachtouris
            args = tuple([token, url] + args)
64 cd42f8d8 Stavros Sachtouris
        elif 'base_url' in kwargs:
65 cd42f8d8 Stavros Sachtouris
            kwargs['auth_url'] = kwargs.get('auth_url', kwargs['base_url'])
66 cd42f8d8 Stavros Sachtouris
        super(AstakosClient, self).__init__(*args, **kwargs)
67 cd42f8d8 Stavros Sachtouris
68 0897ff84 Stavros Sachtouris
    def get_service_endpoints(self, service_type, version=None):
69 0897ff84 Stavros Sachtouris
        services = parse_endpoints(
70 0897ff84 Stavros Sachtouris
            self.get_endpoints(), ep_type=service_type, ep_version_id=version)
71 0897ff84 Stavros Sachtouris
        return services[0]['endpoints'][0] if services else []
72 0897ff84 Stavros Sachtouris
73 736072e2 Stavros Sachtouris
    @property
74 736072e2 Stavros Sachtouris
    def user_info(self):
75 736072e2 Stavros Sachtouris
        return self.authenticate()['access']['user']
76 736072e2 Stavros Sachtouris
77 736072e2 Stavros Sachtouris
    def user_term(self, term):
78 736072e2 Stavros Sachtouris
        return self.user_info[term]
79 736072e2 Stavros Sachtouris
80 a22d311c Stavros Sachtouris
81 8b4ba753 Stavros Sachtouris
#  Wrap AstakosClient public methods to raise AstakosClientError
82 8b4ba753 Stavros Sachtouris
from inspect import getmembers
83 8b4ba753 Stavros Sachtouris
for m in getmembers(AstakosClient):
84 8b4ba753 Stavros Sachtouris
    if hasattr(m[1], '__call__') and not ('%s' % m[0]).startswith('_'):
85 8b4ba753 Stavros Sachtouris
        setattr(AstakosClient, m[0], _astakos_error(m[1]))
86 fa7d08b6 Stavros Sachtouris
87 fa7d08b6 Stavros Sachtouris
88 cd42f8d8 Stavros Sachtouris
class LoggedAstakosClient(AstakosClient):
89 cd42f8d8 Stavros Sachtouris
    """An AstakosClient wrapper with modified logging
90 cd42f8d8 Stavros Sachtouris

91 cd42f8d8 Stavros Sachtouris
    Logs are adjusted to appear similar to the ones of kamaki clients.
92 cd42f8d8 Stavros Sachtouris
    No other changes are made to the parent class.
93 cd42f8d8 Stavros Sachtouris
    """
94 36cb577e Stavros Sachtouris
95 36cb577e Stavros Sachtouris
    LOG_TOKEN = False
96 36cb577e Stavros Sachtouris
    LOG_DATA = False
97 85115c12 Stavros Sachtouris
98 85115c12 Stavros Sachtouris
    def _dump_response(self, request, status, message, data):
99 20211cbb Stavros Sachtouris
        recvlog.info('\n%d %s' % (status, message))
100 20211cbb Stavros Sachtouris
        recvlog.info('data size: %s' % len(data))
101 36cb577e Stavros Sachtouris
        if not self.LOG_TOKEN:
102 36cb577e Stavros Sachtouris
            token = request.headers.get('X-Auth-Token', '')
103 36cb577e Stavros Sachtouris
            if self.LOG_DATA:
104 36cb577e Stavros Sachtouris
                data = data.replace(token, '...') if token else data
105 36cb577e Stavros Sachtouris
        if self.LOG_DATA:
106 36cb577e Stavros Sachtouris
            recvlog.info(data)
107 2d1f5058 Stavros Sachtouris
        recvlog.info('-             -        -     -   -  - -')
108 85115c12 Stavros Sachtouris
109 85115c12 Stavros Sachtouris
    def _call_astakos(self, *args, **kwargs):
110 cd42f8d8 Stavros Sachtouris
        r = super(LoggedAstakosClient, self)._call_astakos(*args, **kwargs)
111 85115c12 Stavros Sachtouris
        try:
112 85115c12 Stavros Sachtouris
            log_request = getattr(self, 'log_request', None)
113 85115c12 Stavros Sachtouris
            if log_request:
114 85115c12 Stavros Sachtouris
                req = RequestManager(
115 85115c12 Stavros Sachtouris
                    method=log_request['method'],
116 85115c12 Stavros Sachtouris
                    url='%s://%s' % (self.scheme, self.astakos_base_url),
117 85115c12 Stavros Sachtouris
                    path=log_request['path'],
118 85115c12 Stavros Sachtouris
                    data=log_request.get('body', None),
119 85115c12 Stavros Sachtouris
                    headers=log_request.get('headers', dict()))
120 36cb577e Stavros Sachtouris
                req.LOG_TOKEN, req.LOG_DATA = self.LOG_TOKEN, self.LOG_DATA
121 85115c12 Stavros Sachtouris
                req.dump_log()
122 85115c12 Stavros Sachtouris
                log_response = getattr(self, 'log_response', None)
123 85115c12 Stavros Sachtouris
                if log_response:
124 85115c12 Stavros Sachtouris
                    self._dump_response(
125 85115c12 Stavros Sachtouris
                        req,
126 85115c12 Stavros Sachtouris
                        status=log_response['status'],
127 85115c12 Stavros Sachtouris
                        message=log_response['message'],
128 85115c12 Stavros Sachtouris
                        data=log_response.get('data', ''))
129 20211cbb Stavros Sachtouris
        except Exception:
130 20211cbb Stavros Sachtouris
            pass
131 85115c12 Stavros Sachtouris
        finally:
132 85115c12 Stavros Sachtouris
            return r
133 85115c12 Stavros Sachtouris
134 85115c12 Stavros Sachtouris
135 36cb577e Stavros Sachtouris
class CachedAstakosClient(Client):
136 cabc72ae Stavros Sachtouris
    """Synnefo Astakos cached client wraper"""
137 44b8928d Giorgos Verigakis
138 fa7d08b6 Stavros Sachtouris
    @_astakos_error
139 528550d9 Stavros Sachtouris
    def __init__(self, base_url, token=None):
140 36cb577e Stavros Sachtouris
        super(CachedAstakosClient, self).__init__(base_url, token)
141 cabc72ae Stavros Sachtouris
        self._astakos = dict()
142 cabc72ae Stavros Sachtouris
        self._uuids = dict()
143 cabc72ae Stavros Sachtouris
        self._cache = dict()
144 cabc72ae Stavros Sachtouris
        self._uuids2usernames = dict()
145 cabc72ae Stavros Sachtouris
        self._usernames2uuids = dict()
146 cabc72ae Stavros Sachtouris
147 cabc72ae Stavros Sachtouris
    def _resolve_token(self, token):
148 cabc72ae Stavros Sachtouris
        """
149 cabc72ae Stavros Sachtouris
        :returns: (str) a single token
150 cabc72ae Stavros Sachtouris

151 cabc72ae Stavros Sachtouris
        :raises AssertionError: if no token exists (either param or member)
152 cabc72ae Stavros Sachtouris
        """
153 91478081 Stavros Sachtouris
        token = token or self.token
154 cabc72ae Stavros Sachtouris
        assert token, 'No token provided'
155 cabc72ae Stavros Sachtouris
        return token[0] if (
156 cabc72ae Stavros Sachtouris
            isinstance(token, list) or isinstance(token, tuple)) else token
157 cabc72ae Stavros Sachtouris
158 172ee8f9 Stavros Sachtouris
    def get_client(self, token=None):
159 172ee8f9 Stavros Sachtouris
        """Get the Synnefo AstakosClient instance used by client"""
160 172ee8f9 Stavros Sachtouris
        token = self._resolve_token(token)
161 172ee8f9 Stavros Sachtouris
        self._validate_token(token)
162 172ee8f9 Stavros Sachtouris
        return self._astakos[self._uuids[token]]
163 172ee8f9 Stavros Sachtouris
164 fa7d08b6 Stavros Sachtouris
    @_astakos_error
165 0238c167 Stavros Sachtouris
    def authenticate(self, token=None):
166 409371de Stavros Sachtouris
        """Get authentication information and store it in this client
167 36cb577e Stavros Sachtouris
        As long as the CachedAstakosClient instance is alive, the latest
168 409371de Stavros Sachtouris
        authentication information for this token will be available
169 409371de Stavros Sachtouris

170 0d79eb23 Stavros Sachtouris
        :param token: (str) custom token to authenticate
171 0d79eb23 Stavros Sachtouris
        """
172 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
173 cd42f8d8 Stavros Sachtouris
        astakos = LoggedAstakosClient(
174 cd42f8d8 Stavros Sachtouris
            self.base_url, token, logger=getLogger('astakosclient'))
175 36cb577e Stavros Sachtouris
        astakos.LOG_TOKEN = getattr(self, 'LOG_TOKEN', False)
176 36cb577e Stavros Sachtouris
        astakos.LOG_DATA = getattr(self, 'LOG_DATA', False)
177 fa7d08b6 Stavros Sachtouris
        r = astakos.authenticate()
178 b44a5a37 Stavros Sachtouris
        uuid = r['access']['user']['id']
179 db93db3e Stavros Sachtouris
        self._uuids[token] = uuid
180 b44a5a37 Stavros Sachtouris
        self._cache[uuid] = r
181 cabc72ae Stavros Sachtouris
        self._astakos[uuid] = astakos
182 91478081 Stavros Sachtouris
        self._uuids2usernames[uuid] = dict()
183 91478081 Stavros Sachtouris
        self._usernames2uuids[uuid] = dict()
184 f24819ad Stavros Sachtouris
        return self._cache[uuid]
185 b44a5a37 Stavros Sachtouris
186 fa7d08b6 Stavros Sachtouris
    def remove_user(self, uuid):
187 fa7d08b6 Stavros Sachtouris
        self._uuids.pop(self.get_token(uuid))
188 fa7d08b6 Stavros Sachtouris
        self._cache.pop(uuid)
189 fa7d08b6 Stavros Sachtouris
        self._astakos.pop(uuid)
190 fa7d08b6 Stavros Sachtouris
        self._uuids2usernames.pop(uuid)
191 fa7d08b6 Stavros Sachtouris
        self._usernames2uuids.pop(uuid)
192 fa7d08b6 Stavros Sachtouris
193 b44a5a37 Stavros Sachtouris
    def get_token(self, uuid):
194 b44a5a37 Stavros Sachtouris
        return self._cache[uuid]['access']['token']['id']
195 5207c784 Stavros Sachtouris
196 cabc72ae Stavros Sachtouris
    def _validate_token(self, token):
197 cabc72ae Stavros Sachtouris
        if (token not in self._uuids) or (
198 cabc72ae Stavros Sachtouris
                self.get_token(self._uuids[token]) != token):
199 cabc72ae Stavros Sachtouris
            self._uuids.pop(token, None)
200 cabc72ae Stavros Sachtouris
            self.authenticate(token)
201 cabc72ae Stavros Sachtouris
202 528550d9 Stavros Sachtouris
    def get_services(self, token=None):
203 528550d9 Stavros Sachtouris
        """
204 528550d9 Stavros Sachtouris
        :returns: (list) [{name:..., type:..., endpoints:[...]}, ...]
205 528550d9 Stavros Sachtouris
        """
206 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
207 cabc72ae Stavros Sachtouris
        self._validate_token(token)
208 cabc72ae Stavros Sachtouris
        r = self._cache[self._uuids[token]]
209 3950a864 Stavros Sachtouris
        return r['access']['serviceCatalog']
210 528550d9 Stavros Sachtouris
211 528550d9 Stavros Sachtouris
    def get_service_details(self, service_type, token=None):
212 528550d9 Stavros Sachtouris
        """
213 528550d9 Stavros Sachtouris
        :param service_type: (str) compute, object-store, image, account, etc.
214 528550d9 Stavros Sachtouris

215 528550d9 Stavros Sachtouris
        :returns: (dict) {name:..., type:..., endpoints:[...]}
216 528550d9 Stavros Sachtouris

217 493f5877 Stavros Sachtouris
        :raises AstakosClientError: if service_type not in service catalog
218 528550d9 Stavros Sachtouris
        """
219 528550d9 Stavros Sachtouris
        services = self.get_services(token)
220 528550d9 Stavros Sachtouris
        for service in services:
221 528550d9 Stavros Sachtouris
            try:
222 528550d9 Stavros Sachtouris
                if service['type'].lower() == service_type.lower():
223 528550d9 Stavros Sachtouris
                    return service
224 528550d9 Stavros Sachtouris
            except KeyError:
225 528550d9 Stavros Sachtouris
                self.log.warning('Misformated service %s' % service)
226 493f5877 Stavros Sachtouris
        raise AstakosClientError(
227 493f5877 Stavros Sachtouris
            'Service type "%s" not in service catalog' % service_type)
228 528550d9 Stavros Sachtouris
229 528550d9 Stavros Sachtouris
    def get_service_endpoints(self, service_type, version=None, token=None):
230 528550d9 Stavros Sachtouris
        """
231 528550d9 Stavros Sachtouris
        :param service_type: (str) can be compute, object-store, etc.
232 528550d9 Stavros Sachtouris

233 528550d9 Stavros Sachtouris
        :param version: (str) the version id of the service
234 528550d9 Stavros Sachtouris

235 528550d9 Stavros Sachtouris
        :returns: (dict) {SNF:uiURL, adminURL, internalURL, publicURL, ...}
236 528550d9 Stavros Sachtouris

237 493f5877 Stavros Sachtouris
        :raises AstakosClientError: if service_type not in service catalog, or
238 493f5877 Stavros Sachtouris
            if #matching endpoints != 1
239 528550d9 Stavros Sachtouris
        """
240 528550d9 Stavros Sachtouris
        service = self.get_service_details(service_type, token)
241 528550d9 Stavros Sachtouris
        matches = []
242 528550d9 Stavros Sachtouris
        for endpoint in service['endpoints']:
243 528550d9 Stavros Sachtouris
            if (not version) or (
244 e7884f25 Stavros Sachtouris
                    endpoint['versionId'].lower() == version.lower()):
245 528550d9 Stavros Sachtouris
                matches.append(endpoint)
246 528550d9 Stavros Sachtouris
        if len(matches) != 1:
247 493f5877 Stavros Sachtouris
            raise AstakosClientError(
248 528550d9 Stavros Sachtouris
                '%s endpoints match type %s %s' % (
249 528550d9 Stavros Sachtouris
                    len(matches), service_type,
250 e7884f25 Stavros Sachtouris
                    ('and versionId %s' % version) if version else ''),
251 528550d9 Stavros Sachtouris
                601)
252 528550d9 Stavros Sachtouris
        return matches[0]
253 528550d9 Stavros Sachtouris
254 528550d9 Stavros Sachtouris
    def list_users(self):
255 528550d9 Stavros Sachtouris
        """list cached users information"""
256 9a8861d1 Stavros Sachtouris
        if not self._cache:
257 9a8861d1 Stavros Sachtouris
            self.authenticate()
258 2182231b Stavros Sachtouris
        r = []
259 2182231b Stavros Sachtouris
        for k, v in self._cache.items():
260 3950a864 Stavros Sachtouris
            r.append(dict(v['access']['user']))
261 b44a5a37 Stavros Sachtouris
            r[-1].update(dict(auth_token=self.get_token(k)))
262 2182231b Stavros Sachtouris
        return r
263 76d3b2d7 Stavros Sachtouris
264 528550d9 Stavros Sachtouris
    def user_info(self, token=None):
265 2182231b Stavros Sachtouris
        """Get (cached) user information"""
266 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
267 cabc72ae Stavros Sachtouris
        self._validate_token(token)
268 cabc72ae Stavros Sachtouris
        r = self._cache[self._uuids[token]]
269 3950a864 Stavros Sachtouris
        return r['access']['user']
270 76d3b2d7 Stavros Sachtouris
271 5207c784 Stavros Sachtouris
    def term(self, key, token=None):
272 5207c784 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
273 f724cd35 Stavros Sachtouris
        return self.user_term(key, token)
274 f724cd35 Stavros Sachtouris
275 f724cd35 Stavros Sachtouris
    def user_term(self, key, token=None):
276 f724cd35 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
277 528550d9 Stavros Sachtouris
        return self.user_info(token).get(key, None)
278 9d3cd179 Stavros Sachtouris
279 cabc72ae Stavros Sachtouris
    def post_user_catalogs(self, uuids=None, displaynames=None, token=None):
280 9d3cd179 Stavros Sachtouris
        """POST base_url/user_catalogs
281 9d3cd179 Stavros Sachtouris

282 9d3cd179 Stavros Sachtouris
        :param uuids: (list or tuple) user uuids
283 9d3cd179 Stavros Sachtouris

284 95641ecc Stavros Sachtouris
        :param displaynames: (list or tuple) usernames (mut. excl. to uuids)
285 95641ecc Stavros Sachtouris

286 95641ecc Stavros Sachtouris
        :returns: (dict) {uuid1: name1, uuid2: name2, ...} or oposite
287 9d3cd179 Stavros Sachtouris
        """
288 cabc72ae Stavros Sachtouris
        return self.uuids2usernames(uuids, token) if (
289 fa7d08b6 Stavros Sachtouris
            uuids) else self.usernames2uuids(displaynames, token)
290 cabc72ae Stavros Sachtouris
291 fa7d08b6 Stavros Sachtouris
    @_astakos_error
292 cabc72ae Stavros Sachtouris
    def uuids2usernames(self, uuids, token=None):
293 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
294 cabc72ae Stavros Sachtouris
        self._validate_token(token)
295 91478081 Stavros Sachtouris
        uuid = self._uuids[token]
296 91478081 Stavros Sachtouris
        astakos = self._astakos[uuid]
297 5c5eb675 Stavros Sachtouris
        if set(uuids or []).difference(self._uuids2usernames[uuid]):
298 91478081 Stavros Sachtouris
            self._uuids2usernames[uuid].update(astakos.get_usernames(uuids))
299 91478081 Stavros Sachtouris
        return self._uuids2usernames[uuid]
300 cabc72ae Stavros Sachtouris
301 fa7d08b6 Stavros Sachtouris
    @_astakos_error
302 cabc72ae Stavros Sachtouris
    def usernames2uuids(self, usernames, token=None):
303 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
304 cabc72ae Stavros Sachtouris
        self._validate_token(token)
305 91478081 Stavros Sachtouris
        uuid = self._uuids[token]
306 91478081 Stavros Sachtouris
        astakos = self._astakos[uuid]
307 5c5eb675 Stavros Sachtouris
        if set(usernames or []).difference(self._usernames2uuids[uuid]):
308 91478081 Stavros Sachtouris
            self._usernames2uuids[uuid].update(astakos.get_uuids(usernames))
309 91478081 Stavros Sachtouris
        return self._usernames2uuids[uuid]