Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-client / astakosclient / __init__.py @ 2377e7c2

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 2377e7c2 Ilias Tsitsimpis
    NoDisplayName, 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 bc5032a4 Ilias Tsitsimpis
def getTokenFromCookie(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 98752f06 Ilias Tsitsimpis
    def _callAstakos(self, token, request_path,
112 8f2d7ede 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
        # Get the connection object
145 e169a337 Ilias Tsitsimpis
        conn = self.conn_class(self.netloc)
146 4490d7b5 Ilias Tsitsimpis
147 4490d7b5 Ilias Tsitsimpis
        # Send request
148 4490d7b5 Ilias Tsitsimpis
        try:
149 4490d7b5 Ilias Tsitsimpis
            (data, status) = _doRequest(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
        finally:
154 4490d7b5 Ilias Tsitsimpis
            conn.close()
155 4490d7b5 Ilias Tsitsimpis
156 4490d7b5 Ilias Tsitsimpis
        # Return
157 4490d7b5 Ilias Tsitsimpis
        self.logger.debug("Request returned with status %s" % status)
158 8fe6475a Ilias Tsitsimpis
        if status == 400:
159 f93cc364 Ilias Tsitsimpis
            raise BadRequest(data)
160 be284f6a Christos Stavrakakis
        elif status == 401:
161 f93cc364 Ilias Tsitsimpis
            raise Unauthorized(data)
162 be284f6a Christos Stavrakakis
        elif status == 403:
163 f93cc364 Ilias Tsitsimpis
            raise Forbidden(data)
164 be284f6a Christos Stavrakakis
        elif status == 404:
165 f93cc364 Ilias Tsitsimpis
            raise NotFound(data)
166 be284f6a Christos Stavrakakis
        elif status < 200 or status >= 300:
167 4490d7b5 Ilias Tsitsimpis
            raise AstakosClientException(data, status)
168 4490d7b5 Ilias Tsitsimpis
        return simplejson.loads(unicode(data))
169 4490d7b5 Ilias Tsitsimpis
170 4490d7b5 Ilias Tsitsimpis
    # ------------------------
171 98752f06 Ilias Tsitsimpis
    def authenticate(self, token, usage=False):
172 4490d7b5 Ilias Tsitsimpis
        """Check if user is authenticated Astakos user
173 4490d7b5 Ilias Tsitsimpis

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

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

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

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

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

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

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

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

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