Statistics
| Branch: | Tag: | Revision:

root / astakosclient / astakosclient / __init__.py @ 1ecb12b5

History | View | Annotate | Download (11.4 kB)

1 99165736 Christos Stavrakakis
# Copyright (C) 2012, 2013 GRNET S.A. All rights reserved.
2 99165736 Christos Stavrakakis
#
3 99165736 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 99165736 Christos Stavrakakis
# without modification, are permitted provided that the following
5 99165736 Christos Stavrakakis
# conditions are met:
6 99165736 Christos Stavrakakis
#
7 99165736 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 99165736 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 99165736 Christos Stavrakakis
#      disclaimer.
10 99165736 Christos Stavrakakis
#
11 99165736 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 99165736 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 99165736 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 99165736 Christos Stavrakakis
#      provided with the distribution.
15 99165736 Christos Stavrakakis
#
16 99165736 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 99165736 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 99165736 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 99165736 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 99165736 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 99165736 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 99165736 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 99165736 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 99165736 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 99165736 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 99165736 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 99165736 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 99165736 Christos Stavrakakis
#
29 99165736 Christos Stavrakakis
# The views and conclusions contained in the software and
30 99165736 Christos Stavrakakis
# documentation are those of the authors and should not be
31 99165736 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 99165736 Christos Stavrakakis
# or implied, of GRNET S.A.
33 cbc0b438 Ilias Tsitsimpis
34 cbc0b438 Ilias Tsitsimpis
import logging
35 cbc0b438 Ilias Tsitsimpis
import urlparse
36 bc5032a4 Ilias Tsitsimpis
import urllib
37 6f64b6d0 Ilias Tsitsimpis
import hashlib
38 8f2d7ede Ilias Tsitsimpis
from copy import copy
39 cbc0b438 Ilias Tsitsimpis
40 cbc0b438 Ilias Tsitsimpis
import simplejson
41 f93cc364 Ilias Tsitsimpis
from astakosclient.utils import retry, scheme_to_class
42 f93cc364 Ilias Tsitsimpis
from astakosclient.errors import \
43 2377e7c2 Ilias Tsitsimpis
    AstakosClientException, Unauthorized, BadRequest, NotFound, Forbidden, \
44 794c94e6 Ilias Tsitsimpis
    NoUserName, NoUUID
45 8fe6475a Ilias Tsitsimpis
46 8fe6475a Ilias Tsitsimpis
47 cbc0b438 Ilias Tsitsimpis
# --------------------------------------------------------------------
48 4490d7b5 Ilias Tsitsimpis
# Astakos Client Class
49 bc5032a4 Ilias Tsitsimpis
50 794c94e6 Ilias Tsitsimpis
def get_token_from_cookie(request, cookie_name):
51 bc5032a4 Ilias Tsitsimpis
    """Extract token from the cookie name provided
52 bc5032a4 Ilias Tsitsimpis

53 bc5032a4 Ilias Tsitsimpis
    Cookie should be in the same form as astakos
54 bc5032a4 Ilias Tsitsimpis
    service sets its cookie contents:
55 bc5032a4 Ilias Tsitsimpis
        <user_uniq>|<user_token>
56 bc5032a4 Ilias Tsitsimpis

57 bc5032a4 Ilias Tsitsimpis
    """
58 bc5032a4 Ilias Tsitsimpis
    try:
59 bc5032a4 Ilias Tsitsimpis
        cookie_content = urllib.unquote(request.COOKIE.get(cookie_name, None))
60 bc5032a4 Ilias Tsitsimpis
        return cookie_content.split("|")[1]
61 bc5032a4 Ilias Tsitsimpis
    except:
62 bc5032a4 Ilias Tsitsimpis
        return None
63 bc5032a4 Ilias Tsitsimpis
64 bc5032a4 Ilias Tsitsimpis
65 4490d7b5 Ilias Tsitsimpis
class AstakosClient():
66 4490d7b5 Ilias Tsitsimpis
    """AstakosClient Class Implementation"""
67 4490d7b5 Ilias Tsitsimpis
68 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
69 996061fa Ilias Tsitsimpis
    def __init__(self, astakos_url, retry=0,
70 996061fa Ilias Tsitsimpis
                 use_pool=False, pool_size=8, logger=None):
71 4490d7b5 Ilias Tsitsimpis
        """Intialize AstakosClient Class
72 4490d7b5 Ilias Tsitsimpis

73 4490d7b5 Ilias Tsitsimpis
        Keyword arguments:
74 4490d7b5 Ilias Tsitsimpis
        astakos_url -- i.e https://accounts.example.com (string)
75 4490d7b5 Ilias Tsitsimpis
        use_pool    -- use objpool for http requests (boolean)
76 949baf4d Ilias Tsitsimpis
        retry       -- how many time to retry (integer)
77 4490d7b5 Ilias Tsitsimpis
        logger      -- pass a different logger
78 4490d7b5 Ilias Tsitsimpis

79 4490d7b5 Ilias Tsitsimpis
        """
80 4490d7b5 Ilias Tsitsimpis
        if logger is None:
81 7eb32034 Ilias Tsitsimpis
            logging.basicConfig(
82 7eb32034 Ilias Tsitsimpis
                format='%(asctime)s [%(levelname)s] %(name)s %(message)s',
83 7eb32034 Ilias Tsitsimpis
                datefmt='%Y-%m-%d %H:%M:%S',
84 7eb32034 Ilias Tsitsimpis
                level=logging.INFO)
85 4490d7b5 Ilias Tsitsimpis
            logger = logging.getLogger("astakosclient")
86 8f2d7ede Ilias Tsitsimpis
        logger.debug("Intialize AstakosClient: astakos_url = %s, "
87 4490d7b5 Ilias Tsitsimpis
                     "use_pool = %s" % (astakos_url, use_pool))
88 4490d7b5 Ilias Tsitsimpis
89 4490d7b5 Ilias Tsitsimpis
        if not astakos_url:
90 4490d7b5 Ilias Tsitsimpis
            m = "Astakos url not given"
91 4490d7b5 Ilias Tsitsimpis
            logger.error(m)
92 4490d7b5 Ilias Tsitsimpis
            raise ValueError(m)
93 4490d7b5 Ilias Tsitsimpis
94 4490d7b5 Ilias Tsitsimpis
        # Check for supported scheme
95 4490d7b5 Ilias Tsitsimpis
        p = urlparse.urlparse(astakos_url)
96 f93cc364 Ilias Tsitsimpis
        conn_class = scheme_to_class(p.scheme, use_pool, pool_size)
97 e169a337 Ilias Tsitsimpis
        if conn_class is None:
98 4490d7b5 Ilias Tsitsimpis
            m = "Unsupported scheme: %s" % p.scheme
99 4490d7b5 Ilias Tsitsimpis
            logger.error(m)
100 4490d7b5 Ilias Tsitsimpis
            raise ValueError(m)
101 4490d7b5 Ilias Tsitsimpis
102 98752f06 Ilias Tsitsimpis
        # Save astakos_url etc. in our class
103 949baf4d Ilias Tsitsimpis
        self.retry = retry
104 4490d7b5 Ilias Tsitsimpis
        self.logger = logger
105 4490d7b5 Ilias Tsitsimpis
        self.netloc = p.netloc
106 4490d7b5 Ilias Tsitsimpis
        self.scheme = p.scheme
107 e169a337 Ilias Tsitsimpis
        self.conn_class = conn_class
108 4490d7b5 Ilias Tsitsimpis
109 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
110 949baf4d Ilias Tsitsimpis
    @retry
111 794c94e6 Ilias Tsitsimpis
    def _call_astakos(self, token, request_path,
112 794c94e6 Ilias Tsitsimpis
                      headers=None, body=None, method="GET"):
113 4490d7b5 Ilias Tsitsimpis
        """Make the actual call to Astakos Service"""
114 6f64b6d0 Ilias Tsitsimpis
        hashed_token = hashlib.sha1()
115 6f64b6d0 Ilias Tsitsimpis
        hashed_token.update(token)
116 4490d7b5 Ilias Tsitsimpis
        self.logger.debug(
117 6f64b6d0 Ilias Tsitsimpis
            "Make a %s request to %s using token %s "
118 6f64b6d0 Ilias Tsitsimpis
            "with headers %s and body %s"
119 6f64b6d0 Ilias Tsitsimpis
            % (method, request_path, hashed_token.hexdigest(), headers, body))
120 4490d7b5 Ilias Tsitsimpis
121 98752f06 Ilias Tsitsimpis
        # Check Input
122 98752f06 Ilias Tsitsimpis
        if not token:
123 98752f06 Ilias Tsitsimpis
            m = "Token not given"
124 98752f06 Ilias Tsitsimpis
            self.logger.error(m)
125 98752f06 Ilias Tsitsimpis
            raise ValueError(m)
126 8f2d7ede Ilias Tsitsimpis
        if headers is None:
127 8f2d7ede Ilias Tsitsimpis
            headers = {}
128 8f2d7ede Ilias Tsitsimpis
        if body is None:
129 8f2d7ede Ilias Tsitsimpis
            body = {}
130 3f8d6b11 Ilias Tsitsimpis
        if request_path[0] != '/':
131 3f8d6b11 Ilias Tsitsimpis
            request_path = "/" + request_path
132 98752f06 Ilias Tsitsimpis
133 4490d7b5 Ilias Tsitsimpis
        # Build request's header and body
134 4490d7b5 Ilias Tsitsimpis
        kwargs = {}
135 8f2d7ede Ilias Tsitsimpis
        kwargs['headers'] = copy(headers)
136 98752f06 Ilias Tsitsimpis
        kwargs['headers']['X-Auth-Token'] = token
137 4490d7b5 Ilias Tsitsimpis
        if body:
138 8f2d7ede Ilias Tsitsimpis
            kwargs['body'] = copy(body)
139 4490d7b5 Ilias Tsitsimpis
            kwargs['headers'].setdefault(
140 4490d7b5 Ilias Tsitsimpis
                'content-type', 'application/octet-stream')
141 4490d7b5 Ilias Tsitsimpis
        kwargs['headers'].setdefault('content-length',
142 4490d7b5 Ilias Tsitsimpis
                                     len(body) if body else 0)
143 4490d7b5 Ilias Tsitsimpis
144 4490d7b5 Ilias Tsitsimpis
        try:
145 6837f014 Ilias Tsitsimpis
            # Get the connection object
146 6837f014 Ilias Tsitsimpis
            with self.conn_class(self.netloc) as conn:
147 6837f014 Ilias Tsitsimpis
                # Send request
148 6837f014 Ilias Tsitsimpis
                (data, status) = \
149 6837f014 Ilias Tsitsimpis
                    _do_request(conn, method, request_path, **kwargs)
150 4490d7b5 Ilias Tsitsimpis
        except Exception as err:
151 996061fa Ilias Tsitsimpis
            self.logger.error("Failed to send request: %s" % repr(err))
152 4490d7b5 Ilias Tsitsimpis
            raise AstakosClientException(str(err))
153 4490d7b5 Ilias Tsitsimpis
154 4490d7b5 Ilias Tsitsimpis
        # Return
155 4490d7b5 Ilias Tsitsimpis
        self.logger.debug("Request returned with status %s" % status)
156 8fe6475a Ilias Tsitsimpis
        if status == 400:
157 f93cc364 Ilias Tsitsimpis
            raise BadRequest(data)
158 be284f6a Christos Stavrakakis
        elif status == 401:
159 f93cc364 Ilias Tsitsimpis
            raise Unauthorized(data)
160 be284f6a Christos Stavrakakis
        elif status == 403:
161 f93cc364 Ilias Tsitsimpis
            raise Forbidden(data)
162 be284f6a Christos Stavrakakis
        elif status == 404:
163 f93cc364 Ilias Tsitsimpis
            raise NotFound(data)
164 be284f6a Christos Stavrakakis
        elif status < 200 or status >= 300:
165 4490d7b5 Ilias Tsitsimpis
            raise AstakosClientException(data, status)
166 4490d7b5 Ilias Tsitsimpis
        return simplejson.loads(unicode(data))
167 4490d7b5 Ilias Tsitsimpis
168 4490d7b5 Ilias Tsitsimpis
    # ------------------------
169 794c94e6 Ilias Tsitsimpis
    def get_user_info(self, token, usage=False):
170 f74d2b69 Ilias Tsitsimpis
        """Authenticate user and get user's info as a dictionary
171 4490d7b5 Ilias Tsitsimpis

172 4490d7b5 Ilias Tsitsimpis
        Keyword arguments:
173 98752f06 Ilias Tsitsimpis
        token   -- user's token (string)
174 4490d7b5 Ilias Tsitsimpis
        usage   -- return usage information for user (boolean)
175 4490d7b5 Ilias Tsitsimpis

176 4490d7b5 Ilias Tsitsimpis
        In case of success return user information (json parsed format).
177 4490d7b5 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException.
178 4490d7b5 Ilias Tsitsimpis

179 4490d7b5 Ilias Tsitsimpis
        """
180 98752f06 Ilias Tsitsimpis
        # Send request
181 4490d7b5 Ilias Tsitsimpis
        auth_path = "/im/authenticate"
182 4490d7b5 Ilias Tsitsimpis
        if usage:
183 4490d7b5 Ilias Tsitsimpis
            auth_path += "?usage=1"
184 794c94e6 Ilias Tsitsimpis
        return self._call_astakos(token, auth_path)
185 4490d7b5 Ilias Tsitsimpis
186 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
187 794c94e6 Ilias Tsitsimpis
    def _uuid_catalog(self, token, uuids, req_path):
188 1c26b500 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
189 1c26b500 Ilias Tsitsimpis
        req_body = simplejson.dumps({'uuids': uuids})
190 794c94e6 Ilias Tsitsimpis
        data = self._call_astakos(
191 1c26b500 Ilias Tsitsimpis
            token, req_path, req_headers, req_body, "POST")
192 2377e7c2 Ilias Tsitsimpis
        if "uuid_catalog" in data:
193 2377e7c2 Ilias Tsitsimpis
            return data.get("uuid_catalog")
194 2377e7c2 Ilias Tsitsimpis
        else:
195 794c94e6 Ilias Tsitsimpis
            m = "_uuid_catalog request returned %s. No uuid_catalog found" \
196 2377e7c2 Ilias Tsitsimpis
                % data
197 2377e7c2 Ilias Tsitsimpis
            self.logger.error(m)
198 2377e7c2 Ilias Tsitsimpis
            raise AstakosClientException(m)
199 1c26b500 Ilias Tsitsimpis
200 794c94e6 Ilias Tsitsimpis
    def get_usernames(self, token, uuids):
201 4490d7b5 Ilias Tsitsimpis
        """Return a uuid_catalog dictionary for the given uuids
202 4490d7b5 Ilias Tsitsimpis

203 4490d7b5 Ilias Tsitsimpis
        Keyword arguments:
204 98752f06 Ilias Tsitsimpis
        token   -- user's token (string)
205 4490d7b5 Ilias Tsitsimpis
        uuids   -- list of user ids (list of strings)
206 4490d7b5 Ilias Tsitsimpis

207 4490d7b5 Ilias Tsitsimpis
        The returned uuid_catalog is a dictionary with uuids as
208 4490d7b5 Ilias Tsitsimpis
        keys and the corresponding user names as values
209 4490d7b5 Ilias Tsitsimpis

210 4490d7b5 Ilias Tsitsimpis
        """
211 4490d7b5 Ilias Tsitsimpis
        req_path = "/user_catalogs"
212 794c94e6 Ilias Tsitsimpis
        return self._uuid_catalog(token, uuids, req_path)
213 4490d7b5 Ilias Tsitsimpis
214 794c94e6 Ilias Tsitsimpis
    def get_username(self, token, uuid):
215 794c94e6 Ilias Tsitsimpis
        """Return the user name of a uuid (see get_usernames)"""
216 4490d7b5 Ilias Tsitsimpis
        if not uuid:
217 4490d7b5 Ilias Tsitsimpis
            m = "No uuid was given"
218 4490d7b5 Ilias Tsitsimpis
            self.logger.error(m)
219 4490d7b5 Ilias Tsitsimpis
            raise ValueError(m)
220 794c94e6 Ilias Tsitsimpis
        uuid_dict = self.get_usernames(token, [uuid])
221 2377e7c2 Ilias Tsitsimpis
        if uuid in uuid_dict:
222 2377e7c2 Ilias Tsitsimpis
            return uuid_dict.get(uuid)
223 2377e7c2 Ilias Tsitsimpis
        else:
224 794c94e6 Ilias Tsitsimpis
            raise NoUserName(uuid)
225 4490d7b5 Ilias Tsitsimpis
226 794c94e6 Ilias Tsitsimpis
    def service_get_usernames(self, token, uuids):
227 1c26b500 Ilias Tsitsimpis
        """Return a uuid_catalog dict using a service's token"""
228 1c26b500 Ilias Tsitsimpis
        req_path = "/service/api/user_catalogs"
229 794c94e6 Ilias Tsitsimpis
        return self._uuid_catalog(token, uuids, req_path)
230 1c26b500 Ilias Tsitsimpis
231 794c94e6 Ilias Tsitsimpis
    def service_get_username(self, token, uuid):
232 1c26b500 Ilias Tsitsimpis
        """Return the displayName of a uuid using a service's token"""
233 1c26b500 Ilias Tsitsimpis
        if not uuid:
234 1c26b500 Ilias Tsitsimpis
            m = "No uuid was given"
235 1c26b500 Ilias Tsitsimpis
            self.logger.error(m)
236 1c26b500 Ilias Tsitsimpis
            raise ValueError(m)
237 794c94e6 Ilias Tsitsimpis
        uuid_dict = self.service_get_usernames(token, [uuid])
238 2377e7c2 Ilias Tsitsimpis
        if uuid in uuid_dict:
239 2377e7c2 Ilias Tsitsimpis
            return uuid_dict.get(uuid)
240 2377e7c2 Ilias Tsitsimpis
        else:
241 794c94e6 Ilias Tsitsimpis
            raise NoUserName(uuid)
242 1c26b500 Ilias Tsitsimpis
243 aaf0a42c Ilias Tsitsimpis
    # ----------------------------------
244 794c94e6 Ilias Tsitsimpis
    def _displayname_catalog(self, token, display_names, req_path):
245 1c26b500 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
246 1c26b500 Ilias Tsitsimpis
        req_body = simplejson.dumps({'displaynames': display_names})
247 794c94e6 Ilias Tsitsimpis
        data = self._call_astakos(
248 1c26b500 Ilias Tsitsimpis
            token, req_path, req_headers, req_body, "POST")
249 2377e7c2 Ilias Tsitsimpis
        if "displayname_catalog" in data:
250 2377e7c2 Ilias Tsitsimpis
            return data.get("displayname_catalog")
251 2377e7c2 Ilias Tsitsimpis
        else:
252 794c94e6 Ilias Tsitsimpis
            m = "_displayname_catalog request returned %s. " \
253 2377e7c2 Ilias Tsitsimpis
                "No displayname_catalog found" % data
254 2377e7c2 Ilias Tsitsimpis
            self.logger.error(m)
255 2377e7c2 Ilias Tsitsimpis
            raise AstakosClientException(m)
256 1c26b500 Ilias Tsitsimpis
257 794c94e6 Ilias Tsitsimpis
    def get_uuids(self, token, display_names):
258 aaf0a42c Ilias Tsitsimpis
        """Return a displayname_catalog for the given names
259 aaf0a42c Ilias Tsitsimpis

260 aaf0a42c Ilias Tsitsimpis
        Keyword arguments:
261 aaf0a42c Ilias Tsitsimpis
        token           -- user's token (string)
262 aaf0a42c Ilias Tsitsimpis
        display_names   -- list of user names (list of strings)
263 aaf0a42c Ilias Tsitsimpis

264 aaf0a42c Ilias Tsitsimpis
        The returned displayname_catalog is a dictionary with
265 aaf0a42c Ilias Tsitsimpis
        the names as keys and the corresponding uuids as values
266 aaf0a42c Ilias Tsitsimpis

267 aaf0a42c Ilias Tsitsimpis
        """
268 aaf0a42c Ilias Tsitsimpis
        req_path = "/user_catalogs"
269 794c94e6 Ilias Tsitsimpis
        return self._displayname_catalog(token, display_names, req_path)
270 aaf0a42c Ilias Tsitsimpis
271 794c94e6 Ilias Tsitsimpis
    def get_uuid(self, token, display_name):
272 aaf0a42c Ilias Tsitsimpis
        """Return the uuid of a name (see getUUIDs)"""
273 aaf0a42c Ilias Tsitsimpis
        if not display_name:
274 aaf0a42c Ilias Tsitsimpis
            m = "No display_name was given"
275 aaf0a42c Ilias Tsitsimpis
            self.logger.error(m)
276 aaf0a42c Ilias Tsitsimpis
            raise ValueError(m)
277 794c94e6 Ilias Tsitsimpis
        name_dict = self.get_uuids(token, [display_name])
278 2377e7c2 Ilias Tsitsimpis
        if display_name in name_dict:
279 2377e7c2 Ilias Tsitsimpis
            return name_dict.get(display_name)
280 2377e7c2 Ilias Tsitsimpis
        else:
281 2377e7c2 Ilias Tsitsimpis
            raise NoUUID(display_name)
282 aaf0a42c Ilias Tsitsimpis
283 794c94e6 Ilias Tsitsimpis
    def service_get_uuids(self, token, display_names):
284 1c26b500 Ilias Tsitsimpis
        """Return a display_name catalog using a service's token"""
285 1c26b500 Ilias Tsitsimpis
        req_path = "/service/api/user_catalogs"
286 794c94e6 Ilias Tsitsimpis
        return self._displayname_catalog(token, display_names, req_path)
287 1c26b500 Ilias Tsitsimpis
288 794c94e6 Ilias Tsitsimpis
    def service_get_uuid(self, token, display_name):
289 1c26b500 Ilias Tsitsimpis
        """Return the uuid of a name using a service's token"""
290 1c26b500 Ilias Tsitsimpis
        if not display_name:
291 1c26b500 Ilias Tsitsimpis
            m = "No display_name was given"
292 1c26b500 Ilias Tsitsimpis
            self.logger.error(m)
293 1c26b500 Ilias Tsitsimpis
            raise ValueError(m)
294 794c94e6 Ilias Tsitsimpis
        name_dict = self.service_get_uuids(token, [display_name])
295 2377e7c2 Ilias Tsitsimpis
        if display_name in name_dict:
296 2377e7c2 Ilias Tsitsimpis
            return name_dict.get(display_name)
297 2377e7c2 Ilias Tsitsimpis
        else:
298 2377e7c2 Ilias Tsitsimpis
            raise NoUUID(display_name)
299 1c26b500 Ilias Tsitsimpis
300 3f8d6b11 Ilias Tsitsimpis
    # ----------------------------------
301 794c94e6 Ilias Tsitsimpis
    def get_services(self):
302 3f8d6b11 Ilias Tsitsimpis
        """Return a list of dicts with the registered services"""
303 794c94e6 Ilias Tsitsimpis
        return self._call_astakos("dummy token", "/im/get_services")
304 3f8d6b11 Ilias Tsitsimpis
305 f54cf5e4 Ilias Tsitsimpis
306 f54cf5e4 Ilias Tsitsimpis
# --------------------------------------------------------------------
307 cbc0b438 Ilias Tsitsimpis
# Private functions
308 f93cc364 Ilias Tsitsimpis
# We want _doRequest to be a distinct function
309 f93cc364 Ilias Tsitsimpis
# so that we can replace it during unit tests.
310 794c94e6 Ilias Tsitsimpis
def _do_request(conn, method, url, **kwargs):
311 f8388a90 Ilias Tsitsimpis
    """The actual request. This function can easily be mocked"""
312 f8388a90 Ilias Tsitsimpis
    conn.request(method, url, **kwargs)
313 f8388a90 Ilias Tsitsimpis
    response = conn.getresponse()
314 f8388a90 Ilias Tsitsimpis
    length = response.getheader('content-length', None)
315 f8388a90 Ilias Tsitsimpis
    data = response.read(length)
316 f8388a90 Ilias Tsitsimpis
    status = int(response.status)
317 4490d7b5 Ilias Tsitsimpis
    return (data, status)