Statistics
| Branch: | Tag: | Revision:

root / astakosclient / astakosclient / __init__.py @ d2104099

History | View | Annotate | Download (36 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 2c9c147e Ilias Tsitsimpis
"""
35 2c9c147e Ilias Tsitsimpis
Simple and minimal client for the Astakos authentication service
36 2c9c147e Ilias Tsitsimpis
"""
37 2c9c147e Ilias Tsitsimpis
38 cbc0b438 Ilias Tsitsimpis
import logging
39 cbc0b438 Ilias Tsitsimpis
import urlparse
40 bc5032a4 Ilias Tsitsimpis
import urllib
41 6f64b6d0 Ilias Tsitsimpis
import hashlib
42 d2104099 Sofia Papagiannaki
from base64 import b64encode
43 8f2d7ede Ilias Tsitsimpis
from copy import copy
44 cbc0b438 Ilias Tsitsimpis
45 cbc0b438 Ilias Tsitsimpis
import simplejson
46 10797183 Ilias Tsitsimpis
from astakosclient.utils import \
47 2c9c147e Ilias Tsitsimpis
    retry_dec, scheme_to_class, parse_request, check_input, join_urls
48 f93cc364 Ilias Tsitsimpis
from astakosclient.errors import \
49 2377e7c2 Ilias Tsitsimpis
    AstakosClientException, Unauthorized, BadRequest, NotFound, Forbidden, \
50 2c9c147e Ilias Tsitsimpis
    NoUserName, NoUUID, BadValue, QuotaLimit, InvalidResponse, NoEndpoints
51 7b5a37fd Ilias Tsitsimpis
52 7b5a37fd Ilias Tsitsimpis
53 7b5a37fd Ilias Tsitsimpis
# --------------------------------------------------------------------
54 4490d7b5 Ilias Tsitsimpis
# Astakos Client Class
55 bc5032a4 Ilias Tsitsimpis
56 794c94e6 Ilias Tsitsimpis
def get_token_from_cookie(request, cookie_name):
57 bc5032a4 Ilias Tsitsimpis
    """Extract token from the cookie name provided
58 bc5032a4 Ilias Tsitsimpis

59 bc5032a4 Ilias Tsitsimpis
    Cookie should be in the same form as astakos
60 bc5032a4 Ilias Tsitsimpis
    service sets its cookie contents:
61 bc5032a4 Ilias Tsitsimpis
        <user_uniq>|<user_token>
62 bc5032a4 Ilias Tsitsimpis

63 bc5032a4 Ilias Tsitsimpis
    """
64 bc5032a4 Ilias Tsitsimpis
    try:
65 bc5032a4 Ilias Tsitsimpis
        cookie_content = urllib.unquote(request.COOKIE.get(cookie_name, None))
66 bc5032a4 Ilias Tsitsimpis
        return cookie_content.split("|")[1]
67 2c9c147e Ilias Tsitsimpis
    except BaseException:
68 bc5032a4 Ilias Tsitsimpis
        return None
69 bc5032a4 Ilias Tsitsimpis
70 bc5032a4 Ilias Tsitsimpis
71 2c9c147e Ilias Tsitsimpis
# Too many instance attributes. pylint: disable-msg=R0902
72 2c9c147e Ilias Tsitsimpis
# Too many public methods. pylint: disable-msg=R0904
73 2c9c147e Ilias Tsitsimpis
class AstakosClient(object):
74 4490d7b5 Ilias Tsitsimpis
    """AstakosClient Class Implementation"""
75 4490d7b5 Ilias Tsitsimpis
76 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
77 2c9c147e Ilias Tsitsimpis
    # Initialize AstakosClient Class
78 2c9c147e Ilias Tsitsimpis
    # Too many arguments. pylint: disable-msg=R0913
79 2c9c147e Ilias Tsitsimpis
    # Too many local variables. pylint: disable-msg=R0914
80 2c9c147e Ilias Tsitsimpis
    # Too many statements. pylint: disable-msg=R0915
81 2c9c147e Ilias Tsitsimpis
    def __init__(self, token, auth_url,
82 2c9c147e Ilias Tsitsimpis
                 retry=0, use_pool=False, pool_size=8, logger=None):
83 c4644612 Ilias Tsitsimpis
        """Initialize AstakosClient Class
84 4490d7b5 Ilias Tsitsimpis

85 4490d7b5 Ilias Tsitsimpis
        Keyword arguments:
86 2c9c147e Ilias Tsitsimpis
        token       -- user's/service's token (string)
87 2c9c147e Ilias Tsitsimpis
        auth_url    -- i.e https://accounts.example.com/identity/v2.0
88 949baf4d Ilias Tsitsimpis
        retry       -- how many time to retry (integer)
89 2c9c147e Ilias Tsitsimpis
        use_pool    -- use objpool for http requests (boolean)
90 2c9c147e Ilias Tsitsimpis
        pool_size   -- if using pool, define the pool size
91 4490d7b5 Ilias Tsitsimpis
        logger      -- pass a different logger
92 4490d7b5 Ilias Tsitsimpis

93 4490d7b5 Ilias Tsitsimpis
        """
94 2c9c147e Ilias Tsitsimpis
95 2c9c147e Ilias Tsitsimpis
        # Get logger
96 4490d7b5 Ilias Tsitsimpis
        if logger is None:
97 7eb32034 Ilias Tsitsimpis
            logging.basicConfig(
98 7eb32034 Ilias Tsitsimpis
                format='%(asctime)s [%(levelname)s] %(name)s %(message)s',
99 7eb32034 Ilias Tsitsimpis
                datefmt='%Y-%m-%d %H:%M:%S',
100 7eb32034 Ilias Tsitsimpis
                level=logging.INFO)
101 4490d7b5 Ilias Tsitsimpis
            logger = logging.getLogger("astakosclient")
102 2c9c147e Ilias Tsitsimpis
        logger.debug("Intialize AstakosClient: auth_url = %s, "
103 2c9c147e Ilias Tsitsimpis
                     "use_pool = %s, pool_size = %s",
104 2c9c147e Ilias Tsitsimpis
                     auth_url, use_pool, pool_size)
105 4490d7b5 Ilias Tsitsimpis
106 2c9c147e Ilias Tsitsimpis
        # Check that token and auth_url (mandatory options) are given
107 2c9c147e Ilias Tsitsimpis
        check_input("__init__", logger, token=token, auth_url=auth_url)
108 4490d7b5 Ilias Tsitsimpis
109 2c9c147e Ilias Tsitsimpis
        # Initialize connection class
110 2c9c147e Ilias Tsitsimpis
        parsed_auth_url = urlparse.urlparse(auth_url)
111 2c9c147e Ilias Tsitsimpis
        conn_class = \
112 2c9c147e Ilias Tsitsimpis
            scheme_to_class(parsed_auth_url.scheme, use_pool, pool_size)
113 e169a337 Ilias Tsitsimpis
        if conn_class is None:
114 2c9c147e Ilias Tsitsimpis
            msg = "Unsupported scheme: %s" % parsed_auth_url.scheme
115 2c9c147e Ilias Tsitsimpis
            logger.error(msg)
116 2c9c147e Ilias Tsitsimpis
            raise BadValue(msg)
117 4490d7b5 Ilias Tsitsimpis
118 2c9c147e Ilias Tsitsimpis
        # Save astakos base url, logger, connection class etc in our class
119 949baf4d Ilias Tsitsimpis
        self.retry = retry
120 4490d7b5 Ilias Tsitsimpis
        self.logger = logger
121 2c9c147e Ilias Tsitsimpis
        self.token = token
122 2c9c147e Ilias Tsitsimpis
        self.astakos_base_url = parsed_auth_url.netloc
123 2c9c147e Ilias Tsitsimpis
        self.scheme = parsed_auth_url.scheme
124 e169a337 Ilias Tsitsimpis
        self.conn_class = conn_class
125 4490d7b5 Ilias Tsitsimpis
126 2c9c147e Ilias Tsitsimpis
        # Initialize astakos api prefixes
127 2c9c147e Ilias Tsitsimpis
        # API urls under auth_url
128 2c9c147e Ilias Tsitsimpis
        self.auth_prefix = parsed_auth_url.path
129 2c9c147e Ilias Tsitsimpis
        self.api_tokens = join_urls(self.auth_prefix, "tokens")
130 2c9c147e Ilias Tsitsimpis
131 45c0bcf8 Giorgos Korfiatis
    def _fill_endpoints(self, endpoints):
132 45c0bcf8 Giorgos Korfiatis
        astakos_service_catalog = parse_endpoints(
133 2c9c147e Ilias Tsitsimpis
            endpoints, ep_name="astakos_account", ep_version_id="v1.0")
134 45c0bcf8 Giorgos Korfiatis
        self._account_url = \
135 45c0bcf8 Giorgos Korfiatis
            astakos_service_catalog[0]['endpoints'][0]['publicURL']
136 45c0bcf8 Giorgos Korfiatis
        parsed_account_url = urlparse.urlparse(self._account_url)
137 45c0bcf8 Giorgos Korfiatis
138 45c0bcf8 Giorgos Korfiatis
        self._account_prefix = parsed_account_url.path
139 45c0bcf8 Giorgos Korfiatis
        self.logger.debug("Got account_prefix \"%s\"" % self._account_prefix)
140 45c0bcf8 Giorgos Korfiatis
141 45c0bcf8 Giorgos Korfiatis
        self._ui_url = \
142 45c0bcf8 Giorgos Korfiatis
            astakos_service_catalog[0]['endpoints'][0]['SNF:uiURL']
143 45c0bcf8 Giorgos Korfiatis
        parsed_ui_url = urlparse.urlparse(self._ui_url)
144 45c0bcf8 Giorgos Korfiatis
145 45c0bcf8 Giorgos Korfiatis
        self._ui_prefix = parsed_ui_url.path
146 45c0bcf8 Giorgos Korfiatis
        self.logger.debug("Got ui_prefix \"%s\"" % self._ui_prefix)
147 45c0bcf8 Giorgos Korfiatis
148 d2104099 Sofia Papagiannaki
        oa2_service_catalog = parse_endpoints(endpoints, ep_name="astakos_oa2")
149 d2104099 Sofia Papagiannaki
        self._oa2_url = \
150 d2104099 Sofia Papagiannaki
            oa2_service_catalog[0]['endpoints'][0]['publicURL']
151 d2104099 Sofia Papagiannaki
        parsed_oa2_url = urlparse.urlparse(self._oa2_url)
152 d2104099 Sofia Papagiannaki
        self._oa2_prefix = parsed_oa2_url.path
153 d2104099 Sofia Papagiannaki
154 45c0bcf8 Giorgos Korfiatis
    def _get_value(self, s):
155 45c0bcf8 Giorgos Korfiatis
        assert s in ['_account_url', '_account_prefix',
156 d2104099 Sofia Papagiannaki
                     '_ui_url', '_ui_prefix',
157 d2104099 Sofia Papagiannaki
                     '_oa2_url', '_oa2_prefix']
158 45c0bcf8 Giorgos Korfiatis
        try:
159 45c0bcf8 Giorgos Korfiatis
            return getattr(self, s)
160 45c0bcf8 Giorgos Korfiatis
        except AttributeError:
161 45c0bcf8 Giorgos Korfiatis
            self.get_endpoints()
162 45c0bcf8 Giorgos Korfiatis
            return getattr(self, s)
163 45c0bcf8 Giorgos Korfiatis
164 45c0bcf8 Giorgos Korfiatis
    @property
165 45c0bcf8 Giorgos Korfiatis
    def account_url(self):
166 45c0bcf8 Giorgos Korfiatis
        return self._get_value('_account_url')
167 45c0bcf8 Giorgos Korfiatis
168 45c0bcf8 Giorgos Korfiatis
    @property
169 45c0bcf8 Giorgos Korfiatis
    def account_prefix(self):
170 45c0bcf8 Giorgos Korfiatis
        return self._get_value('_account_prefix')
171 45c0bcf8 Giorgos Korfiatis
172 45c0bcf8 Giorgos Korfiatis
    @property
173 45c0bcf8 Giorgos Korfiatis
    def ui_url(self):
174 45c0bcf8 Giorgos Korfiatis
        return self._get_value('_ui_url')
175 45c0bcf8 Giorgos Korfiatis
176 45c0bcf8 Giorgos Korfiatis
    @property
177 45c0bcf8 Giorgos Korfiatis
    def ui_prefix(self):
178 45c0bcf8 Giorgos Korfiatis
        return self._get_value('_ui_prefix')
179 45c0bcf8 Giorgos Korfiatis
180 45c0bcf8 Giorgos Korfiatis
    @property
181 d2104099 Sofia Papagiannaki
    def oa2_url(self):
182 d2104099 Sofia Papagiannaki
        return self._get_value('_oa2_url')
183 d2104099 Sofia Papagiannaki
184 d2104099 Sofia Papagiannaki
    @property
185 d2104099 Sofia Papagiannaki
    def oa2_prefix(self):
186 d2104099 Sofia Papagiannaki
        return self._get_value('_oa2_prefix')
187 d2104099 Sofia Papagiannaki
188 d2104099 Sofia Papagiannaki
    @property
189 45c0bcf8 Giorgos Korfiatis
    def api_usercatalogs(self):
190 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "user_catalogs")
191 45c0bcf8 Giorgos Korfiatis
192 45c0bcf8 Giorgos Korfiatis
    @property
193 45c0bcf8 Giorgos Korfiatis
    def api_service_usercatalogs(self):
194 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "service/user_catalogs")
195 45c0bcf8 Giorgos Korfiatis
196 45c0bcf8 Giorgos Korfiatis
    @property
197 45c0bcf8 Giorgos Korfiatis
    def api_resources(self):
198 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "resources")
199 45c0bcf8 Giorgos Korfiatis
200 45c0bcf8 Giorgos Korfiatis
    @property
201 45c0bcf8 Giorgos Korfiatis
    def api_quotas(self):
202 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "quotas")
203 45c0bcf8 Giorgos Korfiatis
204 45c0bcf8 Giorgos Korfiatis
    @property
205 45c0bcf8 Giorgos Korfiatis
    def api_service_quotas(self):
206 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "service_quotas")
207 2c9c147e Ilias Tsitsimpis
208 45c0bcf8 Giorgos Korfiatis
    @property
209 45c0bcf8 Giorgos Korfiatis
    def api_commissions(self):
210 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "commissions")
211 2c9c147e Ilias Tsitsimpis
212 45c0bcf8 Giorgos Korfiatis
    @property
213 45c0bcf8 Giorgos Korfiatis
    def api_commissions_action(self):
214 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.api_commissions, "action")
215 45c0bcf8 Giorgos Korfiatis
216 45c0bcf8 Giorgos Korfiatis
    @property
217 45c0bcf8 Giorgos Korfiatis
    def api_feedback(self):
218 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "feedback")
219 45c0bcf8 Giorgos Korfiatis
220 45c0bcf8 Giorgos Korfiatis
    @property
221 45c0bcf8 Giorgos Korfiatis
    def api_projects(self):
222 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.account_prefix, "projects")
223 45c0bcf8 Giorgos Korfiatis
224 45c0bcf8 Giorgos Korfiatis
    @property
225 45c0bcf8 Giorgos Korfiatis
    def api_applications(self):
226 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.api_projects, "apps")
227 45c0bcf8 Giorgos Korfiatis
228 45c0bcf8 Giorgos Korfiatis
    @property
229 45c0bcf8 Giorgos Korfiatis
    def api_memberships(self):
230 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.api_projects, "memberships")
231 45c0bcf8 Giorgos Korfiatis
232 45c0bcf8 Giorgos Korfiatis
    @property
233 45c0bcf8 Giorgos Korfiatis
    def api_getservices(self):
234 45c0bcf8 Giorgos Korfiatis
        return join_urls(self.ui_prefix, "get_services")
235 2c9c147e Ilias Tsitsimpis
236 d2104099 Sofia Papagiannaki
    @property
237 d2104099 Sofia Papagiannaki
    def api_oa2_auth(self):
238 d2104099 Sofia Papagiannaki
        return join_urls(self.oa2_prefix, "auth")
239 d2104099 Sofia Papagiannaki
240 d2104099 Sofia Papagiannaki
    @property
241 d2104099 Sofia Papagiannaki
    def api_oa2_token(self):
242 d2104099 Sofia Papagiannaki
        return join_urls(self.oa2_prefix, "token")
243 d2104099 Sofia Papagiannaki
244 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
245 2c9c147e Ilias Tsitsimpis
    @retry_dec
246 2c9c147e Ilias Tsitsimpis
    def _call_astakos(self, request_path, headers=None,
247 25a04cdd Ilias Tsitsimpis
                      body=None, method="GET", log_body=True):
248 4490d7b5 Ilias Tsitsimpis
        """Make the actual call to Astakos Service"""
249 2c9c147e Ilias Tsitsimpis
        hashed_token = hashlib.sha1()
250 2c9c147e Ilias Tsitsimpis
        hashed_token.update(self.token)
251 4490d7b5 Ilias Tsitsimpis
        self.logger.debug(
252 2c9c147e Ilias Tsitsimpis
            "Make a %s request to %s, using token with hash %s, "
253 2c9c147e Ilias Tsitsimpis
            "with headers %s and body %s",
254 2c9c147e Ilias Tsitsimpis
            method, request_path, hashed_token.hexdigest(), headers,
255 2c9c147e Ilias Tsitsimpis
            body if log_body else "(not logged)")
256 4490d7b5 Ilias Tsitsimpis
257 98752f06 Ilias Tsitsimpis
        # Check Input
258 8f2d7ede Ilias Tsitsimpis
        if headers is None:
259 8f2d7ede Ilias Tsitsimpis
            headers = {}
260 8f2d7ede Ilias Tsitsimpis
        if body is None:
261 8f2d7ede Ilias Tsitsimpis
            body = {}
262 2cd636fe Stavros Sachtouris
        # Initialize log_request and log_response attributes
263 2cd636fe Stavros Sachtouris
        self.log_request = None
264 2cd636fe Stavros Sachtouris
        self.log_response = None
265 98752f06 Ilias Tsitsimpis
266 4490d7b5 Ilias Tsitsimpis
        # Build request's header and body
267 4490d7b5 Ilias Tsitsimpis
        kwargs = {}
268 8f2d7ede Ilias Tsitsimpis
        kwargs['headers'] = copy(headers)
269 2c9c147e Ilias Tsitsimpis
        kwargs['headers']['X-Auth-Token'] = self.token
270 4490d7b5 Ilias Tsitsimpis
        if body:
271 8f2d7ede Ilias Tsitsimpis
            kwargs['body'] = copy(body)
272 4490d7b5 Ilias Tsitsimpis
            kwargs['headers'].setdefault(
273 4490d7b5 Ilias Tsitsimpis
                'content-type', 'application/octet-stream')
274 4490d7b5 Ilias Tsitsimpis
        kwargs['headers'].setdefault('content-length',
275 4490d7b5 Ilias Tsitsimpis
                                     len(body) if body else 0)
276 4490d7b5 Ilias Tsitsimpis
277 4490d7b5 Ilias Tsitsimpis
        try:
278 6837f014 Ilias Tsitsimpis
            # Get the connection object
279 2c9c147e Ilias Tsitsimpis
            with self.conn_class(self.astakos_base_url) as conn:
280 2cd636fe Stavros Sachtouris
                # Log the request so other clients (like kamaki)
281 2cd636fe Stavros Sachtouris
                # can use them to produce their own log messages.
282 2cd636fe Stavros Sachtouris
                self.log_request = dict(method=method, path=request_path)
283 2cd636fe Stavros Sachtouris
                self.log_request.update(kwargs)
284 2cd636fe Stavros Sachtouris
285 6837f014 Ilias Tsitsimpis
                # Send request
286 2c9c147e Ilias Tsitsimpis
                # Used * or ** magic. pylint: disable-msg=W0142
287 21190887 Ilias Tsitsimpis
                (message, data, status) = \
288 2c9c147e Ilias Tsitsimpis
                    _do_request(conn, method, request_path, **kwargs)
289 2cd636fe Stavros Sachtouris
290 2cd636fe Stavros Sachtouris
                # Log the response so other clients (like kamaki)
291 2cd636fe Stavros Sachtouris
                # can use them to produce their own log messages.
292 2cd636fe Stavros Sachtouris
                self.log_response = dict(
293 2cd636fe Stavros Sachtouris
                    status=status, message=message, data=data)
294 4490d7b5 Ilias Tsitsimpis
        except Exception as err:
295 996061fa Ilias Tsitsimpis
            self.logger.error("Failed to send request: %s" % repr(err))
296 4490d7b5 Ilias Tsitsimpis
            raise AstakosClientException(str(err))
297 4490d7b5 Ilias Tsitsimpis
298 4490d7b5 Ilias Tsitsimpis
        # Return
299 4490d7b5 Ilias Tsitsimpis
        self.logger.debug("Request returned with status %s" % status)
300 8fe6475a Ilias Tsitsimpis
        if status == 400:
301 21190887 Ilias Tsitsimpis
            raise BadRequest(message, data)
302 be284f6a Christos Stavrakakis
        elif status == 401:
303 21190887 Ilias Tsitsimpis
            raise Unauthorized(message, data)
304 be284f6a Christos Stavrakakis
        elif status == 403:
305 21190887 Ilias Tsitsimpis
            raise Forbidden(message, data)
306 be284f6a Christos Stavrakakis
        elif status == 404:
307 21190887 Ilias Tsitsimpis
            raise NotFound(message, data)
308 be284f6a Christos Stavrakakis
        elif status < 200 or status >= 300:
309 21190887 Ilias Tsitsimpis
            raise AstakosClientException(message, data, status)
310 0a2a342c Ilias Tsitsimpis
311 0a2a342c Ilias Tsitsimpis
        try:
312 0a2a342c Ilias Tsitsimpis
            if data:
313 0a2a342c Ilias Tsitsimpis
                return simplejson.loads(unicode(data))
314 0a2a342c Ilias Tsitsimpis
            else:
315 10797183 Ilias Tsitsimpis
                return None
316 0a2a342c Ilias Tsitsimpis
        except Exception as err:
317 8975f6f6 Christos Stavrakakis
            msg = "Cannot parse response \"%s\" with simplejson: %s"
318 8975f6f6 Christos Stavrakakis
            self.logger.error(msg % (data, str(err)))
319 0a2a342c Ilias Tsitsimpis
            raise InvalidResponse(str(err), data)
320 4490d7b5 Ilias Tsitsimpis
321 4490d7b5 Ilias Tsitsimpis
    # ----------------------------------
322 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_USERCATALOGS`` (or ``API_SERVICE_USERCATALOGS``)
323 c4644612 Ilias Tsitsimpis
    #   with {'uuids': uuids}
324 2c9c147e Ilias Tsitsimpis
    def _uuid_catalog(self, uuids, req_path):
325 2c9c147e Ilias Tsitsimpis
        """Helper function to retrieve uuid catalog"""
326 1c26b500 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
327 19198628 Ilias Tsitsimpis
        req_body = parse_request({'uuids': uuids}, self.logger)
328 2c9c147e Ilias Tsitsimpis
        data = self._call_astakos(req_path, headers=req_headers,
329 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
330 2377e7c2 Ilias Tsitsimpis
        if "uuid_catalog" in data:
331 2377e7c2 Ilias Tsitsimpis
            return data.get("uuid_catalog")
332 2377e7c2 Ilias Tsitsimpis
        else:
333 2c9c147e Ilias Tsitsimpis
            msg = "_uuid_catalog request returned %s. No uuid_catalog found" \
334 2c9c147e Ilias Tsitsimpis
                  % data
335 2c9c147e Ilias Tsitsimpis
            self.logger.error(msg)
336 2c9c147e Ilias Tsitsimpis
            raise AstakosClientException(msg)
337 1c26b500 Ilias Tsitsimpis
338 2c9c147e Ilias Tsitsimpis
    def get_usernames(self, uuids):
339 4490d7b5 Ilias Tsitsimpis
        """Return a uuid_catalog dictionary for the given uuids
340 4490d7b5 Ilias Tsitsimpis

341 4490d7b5 Ilias Tsitsimpis
        Keyword arguments:
342 4490d7b5 Ilias Tsitsimpis
        uuids   -- list of user ids (list of strings)
343 4490d7b5 Ilias Tsitsimpis

344 4490d7b5 Ilias Tsitsimpis
        The returned uuid_catalog is a dictionary with uuids as
345 4490d7b5 Ilias Tsitsimpis
        keys and the corresponding user names as values
346 4490d7b5 Ilias Tsitsimpis

347 4490d7b5 Ilias Tsitsimpis
        """
348 2c9c147e Ilias Tsitsimpis
        return self._uuid_catalog(uuids, self.api_usercatalogs)
349 4490d7b5 Ilias Tsitsimpis
350 2c9c147e Ilias Tsitsimpis
    def get_username(self, uuid):
351 794c94e6 Ilias Tsitsimpis
        """Return the user name of a uuid (see get_usernames)"""
352 10797183 Ilias Tsitsimpis
        check_input("get_username", self.logger, uuid=uuid)
353 2c9c147e Ilias Tsitsimpis
        uuid_dict = self.get_usernames([uuid])
354 2377e7c2 Ilias Tsitsimpis
        if uuid in uuid_dict:
355 2377e7c2 Ilias Tsitsimpis
            return uuid_dict.get(uuid)
356 2377e7c2 Ilias Tsitsimpis
        else:
357 794c94e6 Ilias Tsitsimpis
            raise NoUserName(uuid)
358 4490d7b5 Ilias Tsitsimpis
359 2c9c147e Ilias Tsitsimpis
    def service_get_usernames(self, uuids):
360 1c26b500 Ilias Tsitsimpis
        """Return a uuid_catalog dict using a service's token"""
361 2c9c147e Ilias Tsitsimpis
        return self._uuid_catalog(uuids, self.api_service_usercatalogs)
362 1c26b500 Ilias Tsitsimpis
363 2c9c147e Ilias Tsitsimpis
    def service_get_username(self, uuid):
364 1c26b500 Ilias Tsitsimpis
        """Return the displayName of a uuid using a service's token"""
365 10797183 Ilias Tsitsimpis
        check_input("service_get_username", self.logger, uuid=uuid)
366 2c9c147e Ilias Tsitsimpis
        uuid_dict = self.service_get_usernames([uuid])
367 2377e7c2 Ilias Tsitsimpis
        if uuid in uuid_dict:
368 2377e7c2 Ilias Tsitsimpis
            return uuid_dict.get(uuid)
369 2377e7c2 Ilias Tsitsimpis
        else:
370 794c94e6 Ilias Tsitsimpis
            raise NoUserName(uuid)
371 1c26b500 Ilias Tsitsimpis
372 aaf0a42c Ilias Tsitsimpis
    # ----------------------------------
373 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_USERCATALOGS`` (or ``API_SERVICE_USERCATALOGS``)
374 c4644612 Ilias Tsitsimpis
    #   with {'displaynames': display_names}
375 2c9c147e Ilias Tsitsimpis
    def _displayname_catalog(self, display_names, req_path):
376 2c9c147e Ilias Tsitsimpis
        """Helper function to retrieve display names catalog"""
377 1c26b500 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
378 19198628 Ilias Tsitsimpis
        req_body = parse_request({'displaynames': display_names}, self.logger)
379 2c9c147e Ilias Tsitsimpis
        data = self._call_astakos(req_path, headers=req_headers,
380 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
381 2377e7c2 Ilias Tsitsimpis
        if "displayname_catalog" in data:
382 2377e7c2 Ilias Tsitsimpis
            return data.get("displayname_catalog")
383 2377e7c2 Ilias Tsitsimpis
        else:
384 2c9c147e Ilias Tsitsimpis
            msg = "_displayname_catalog request returned %s. " \
385 2c9c147e Ilias Tsitsimpis
                  "No displayname_catalog found" % data
386 2c9c147e Ilias Tsitsimpis
            self.logger.error(msg)
387 2c9c147e Ilias Tsitsimpis
            raise AstakosClientException(msg)
388 1c26b500 Ilias Tsitsimpis
389 2c9c147e Ilias Tsitsimpis
    def get_uuids(self, display_names):
390 aaf0a42c Ilias Tsitsimpis
        """Return a displayname_catalog for the given names
391 aaf0a42c Ilias Tsitsimpis

392 aaf0a42c Ilias Tsitsimpis
        Keyword arguments:
393 aaf0a42c Ilias Tsitsimpis
        display_names   -- list of user names (list of strings)
394 aaf0a42c Ilias Tsitsimpis

395 aaf0a42c Ilias Tsitsimpis
        The returned displayname_catalog is a dictionary with
396 aaf0a42c Ilias Tsitsimpis
        the names as keys and the corresponding uuids as values
397 aaf0a42c Ilias Tsitsimpis

398 aaf0a42c Ilias Tsitsimpis
        """
399 2c9c147e Ilias Tsitsimpis
        return self._displayname_catalog(
400 2c9c147e Ilias Tsitsimpis
            display_names, self.api_usercatalogs)
401 aaf0a42c Ilias Tsitsimpis
402 2c9c147e Ilias Tsitsimpis
    def get_uuid(self, display_name):
403 aaf0a42c Ilias Tsitsimpis
        """Return the uuid of a name (see getUUIDs)"""
404 10797183 Ilias Tsitsimpis
        check_input("get_uuid", self.logger, display_name=display_name)
405 2c9c147e Ilias Tsitsimpis
        name_dict = self.get_uuids([display_name])
406 2377e7c2 Ilias Tsitsimpis
        if display_name in name_dict:
407 2377e7c2 Ilias Tsitsimpis
            return name_dict.get(display_name)
408 2377e7c2 Ilias Tsitsimpis
        else:
409 2377e7c2 Ilias Tsitsimpis
            raise NoUUID(display_name)
410 aaf0a42c Ilias Tsitsimpis
411 2c9c147e Ilias Tsitsimpis
    def service_get_uuids(self, display_names):
412 1c26b500 Ilias Tsitsimpis
        """Return a display_name catalog using a service's token"""
413 2c9c147e Ilias Tsitsimpis
        return self._displayname_catalog(
414 2c9c147e Ilias Tsitsimpis
            display_names, self.api_service_usercatalogs)
415 1c26b500 Ilias Tsitsimpis
416 2c9c147e Ilias Tsitsimpis
    def service_get_uuid(self, display_name):
417 1c26b500 Ilias Tsitsimpis
        """Return the uuid of a name using a service's token"""
418 10797183 Ilias Tsitsimpis
        check_input("service_get_uuid", self.logger, display_name=display_name)
419 2c9c147e Ilias Tsitsimpis
        name_dict = self.service_get_uuids([display_name])
420 2377e7c2 Ilias Tsitsimpis
        if display_name in name_dict:
421 2377e7c2 Ilias Tsitsimpis
            return name_dict.get(display_name)
422 2377e7c2 Ilias Tsitsimpis
        else:
423 2377e7c2 Ilias Tsitsimpis
            raise NoUUID(display_name)
424 1c26b500 Ilias Tsitsimpis
425 3f8d6b11 Ilias Tsitsimpis
    # ----------------------------------
426 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_GETSERVICES``
427 794c94e6 Ilias Tsitsimpis
    def get_services(self):
428 3f8d6b11 Ilias Tsitsimpis
        """Return a list of dicts with the registered services"""
429 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_getservices)
430 c4644612 Ilias Tsitsimpis
431 c4644612 Ilias Tsitsimpis
    # ----------------------------------
432 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_RESOURCES``
433 c4644612 Ilias Tsitsimpis
    def get_resources(self):
434 c4644612 Ilias Tsitsimpis
        """Return a dict of dicts with the available resources"""
435 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_resources)
436 3f8d6b11 Ilias Tsitsimpis
437 baeb2ba5 Ilias Tsitsimpis
    # ----------------------------------
438 92683993 Ilias Tsitsimpis
    # do a POST to ``API_FEEDBACK``
439 2c9c147e Ilias Tsitsimpis
    def send_feedback(self, message, data):
440 92683993 Ilias Tsitsimpis
        """Send feedback to astakos service
441 92683993 Ilias Tsitsimpis

442 92683993 Ilias Tsitsimpis
        keyword arguments:
443 92683993 Ilias Tsitsimpis
        message     -- Feedback message
444 92683993 Ilias Tsitsimpis
        data        -- Additional information about service client status
445 92683993 Ilias Tsitsimpis

446 92683993 Ilias Tsitsimpis
        In case of success return nothing.
447 92683993 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException
448 92683993 Ilias Tsitsimpis

449 92683993 Ilias Tsitsimpis
        """
450 92683993 Ilias Tsitsimpis
        check_input("send_feedback", self.logger, message=message, data=data)
451 92683993 Ilias Tsitsimpis
        req_body = urllib.urlencode(
452 92683993 Ilias Tsitsimpis
            {'feedback_msg': message, 'feedback_data': data})
453 2c9c147e Ilias Tsitsimpis
        self._call_astakos(self.api_feedback, headers=None,
454 2c9c147e Ilias Tsitsimpis
                           body=req_body, method="POST")
455 108be31f Ilias Tsitsimpis
456 45c0bcf8 Giorgos Korfiatis
    # -----------------------------------------
457 45c0bcf8 Giorgos Korfiatis
    # do a POST to ``API_TOKENS`` with no token
458 45c0bcf8 Giorgos Korfiatis
    def get_endpoints(self):
459 45c0bcf8 Giorgos Korfiatis
        """ Get services' endpoints
460 45c0bcf8 Giorgos Korfiatis

461 45c0bcf8 Giorgos Korfiatis
        In case of error raise an AstakosClientException.
462 45c0bcf8 Giorgos Korfiatis

463 45c0bcf8 Giorgos Korfiatis
        """
464 45c0bcf8 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
465 45c0bcf8 Giorgos Korfiatis
        req_body = None
466 45c0bcf8 Giorgos Korfiatis
        r = self._call_astakos(self.api_tokens, headers=req_headers,
467 45c0bcf8 Giorgos Korfiatis
                               body=req_body, method="POST",
468 45c0bcf8 Giorgos Korfiatis
                               log_body=False)
469 45c0bcf8 Giorgos Korfiatis
        self._fill_endpoints(r)
470 45c0bcf8 Giorgos Korfiatis
        return r
471 45c0bcf8 Giorgos Korfiatis
472 45c0bcf8 Giorgos Korfiatis
    # --------------------------------------
473 45c0bcf8 Giorgos Korfiatis
    # do a POST to ``API_TOKENS`` with a token
474 45c0bcf8 Giorgos Korfiatis
    def authenticate(self, tenant_name=None):
475 2c9c147e Ilias Tsitsimpis
        """ Authenticate and get services' endpoints
476 25a04cdd Ilias Tsitsimpis

477 25a04cdd Ilias Tsitsimpis
        Keyword arguments:
478 2c9c147e Ilias Tsitsimpis
        tenant_name         -- user's uniq id (optional)
479 25a04cdd Ilias Tsitsimpis

480 25a04cdd Ilias Tsitsimpis
        It returns back the token as well as information about the token
481 45c0bcf8 Giorgos Korfiatis
        holder and the services he/she can access (in json format).
482 2c9c147e Ilias Tsitsimpis

483 2c9c147e Ilias Tsitsimpis
        The tenant_name is optional and if it is given it must match the
484 2c9c147e Ilias Tsitsimpis
        user's uuid.
485 2c9c147e Ilias Tsitsimpis

486 25a04cdd Ilias Tsitsimpis
        In case of error raise an AstakosClientException.
487 25a04cdd Ilias Tsitsimpis

488 25a04cdd Ilias Tsitsimpis
        """
489 25a04cdd Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
490 45c0bcf8 Giorgos Korfiatis
        body = {'auth': {'token': {'id': self.token}}}
491 45c0bcf8 Giorgos Korfiatis
        if tenant_name is not None:
492 45c0bcf8 Giorgos Korfiatis
            body['auth']['tenantName'] = tenant_name
493 45c0bcf8 Giorgos Korfiatis
        req_body = parse_request(body, self.logger)
494 45c0bcf8 Giorgos Korfiatis
        r = self._call_astakos(self.api_tokens, headers=req_headers,
495 45c0bcf8 Giorgos Korfiatis
                               body=req_body, method="POST",
496 45c0bcf8 Giorgos Korfiatis
                               log_body=False)
497 45c0bcf8 Giorgos Korfiatis
        self._fill_endpoints(r)
498 45c0bcf8 Giorgos Korfiatis
        return r
499 25a04cdd Ilias Tsitsimpis
500 25a04cdd Ilias Tsitsimpis
    # ----------------------------------
501 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_QUOTAS``
502 2c9c147e Ilias Tsitsimpis
    def get_quotas(self):
503 fd420756 Ilias Tsitsimpis
        """Get user's quotas
504 fd420756 Ilias Tsitsimpis

505 fd420756 Ilias Tsitsimpis
        In case of success return a dict of dicts with user's current quotas.
506 fd420756 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException
507 fd420756 Ilias Tsitsimpis

508 fd420756 Ilias Tsitsimpis
        """
509 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_quotas)
510 baeb2ba5 Ilias Tsitsimpis
511 fd420756 Ilias Tsitsimpis
    # ----------------------------------
512 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_SERVICE_QUOTAS``
513 2c9c147e Ilias Tsitsimpis
    def service_get_quotas(self, user=None):
514 5b33b8e5 Giorgos Korfiatis
        """Get all quotas for resources associated with the service
515 5b33b8e5 Giorgos Korfiatis

516 5b33b8e5 Giorgos Korfiatis
        Keyword arguments:
517 db9f7a2b Giorgos Korfiatis
        user    -- optionally, the uuid of a specific user
518 5b33b8e5 Giorgos Korfiatis

519 5b33b8e5 Giorgos Korfiatis
        In case of success return a dict of dicts of dicts with current quotas
520 db9f7a2b Giorgos Korfiatis
        for all users, or of a specified user, if user argument is set.
521 5b33b8e5 Giorgos Korfiatis
        Otherwise raise an AstakosClientException
522 5b33b8e5 Giorgos Korfiatis

523 5b33b8e5 Giorgos Korfiatis
        """
524 2c9c147e Ilias Tsitsimpis
        query = self.api_service_quotas
525 db9f7a2b Giorgos Korfiatis
        if user is not None:
526 db9f7a2b Giorgos Korfiatis
            query += "?user=" + user
527 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(query)
528 5b33b8e5 Giorgos Korfiatis
529 5b33b8e5 Giorgos Korfiatis
    # ----------------------------------
530 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS``
531 2c9c147e Ilias Tsitsimpis
    def issue_commission(self, request):
532 fd420756 Ilias Tsitsimpis
        """Issue a commission
533 fd420756 Ilias Tsitsimpis

534 fd420756 Ilias Tsitsimpis
        Keyword arguments:
535 fd420756 Ilias Tsitsimpis
        request -- commision request (dict)
536 fd420756 Ilias Tsitsimpis

537 fd420756 Ilias Tsitsimpis
        In case of success return commission's id (int).
538 fd420756 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException.
539 fd420756 Ilias Tsitsimpis

540 fd420756 Ilias Tsitsimpis
        """
541 fd420756 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
542 19198628 Ilias Tsitsimpis
        req_body = parse_request(request, self.logger)
543 fd420756 Ilias Tsitsimpis
        try:
544 2c9c147e Ilias Tsitsimpis
            response = self._call_astakos(self.api_commissions,
545 2c9c147e Ilias Tsitsimpis
                                          headers=req_headers,
546 2c9c147e Ilias Tsitsimpis
                                          body=req_body,
547 2c9c147e Ilias Tsitsimpis
                                          method="POST")
548 fd420756 Ilias Tsitsimpis
        except AstakosClientException as err:
549 fd420756 Ilias Tsitsimpis
            if err.status == 413:
550 fd420756 Ilias Tsitsimpis
                raise QuotaLimit(err.message, err.details)
551 fd420756 Ilias Tsitsimpis
            else:
552 fd420756 Ilias Tsitsimpis
                raise
553 fd420756 Ilias Tsitsimpis
554 fd420756 Ilias Tsitsimpis
        if "serial" in response:
555 fd420756 Ilias Tsitsimpis
            return response['serial']
556 fd420756 Ilias Tsitsimpis
        else:
557 2c9c147e Ilias Tsitsimpis
            msg = "issue_commission_core request returned %s. " + \
558 2c9c147e Ilias Tsitsimpis
                  "No serial found" % response
559 2c9c147e Ilias Tsitsimpis
            self.logger.error(msg)
560 2c9c147e Ilias Tsitsimpis
            raise AstakosClientException(msg)
561 fd420756 Ilias Tsitsimpis
562 2c9c147e Ilias Tsitsimpis
    def issue_one_commission(self, holder, source, provisions,
563 3a1bed03 Giorgos Korfiatis
                             name="", force=False, auto_accept=False):
564 12eab714 Ilias Tsitsimpis
        """Issue one commission (with specific holder and source)
565 12eab714 Ilias Tsitsimpis

566 12eab714 Ilias Tsitsimpis
        keyword arguments:
567 12eab714 Ilias Tsitsimpis
        holder      -- user's id (string)
568 12eab714 Ilias Tsitsimpis
        source      -- commission's source (ex system) (string)
569 8b68fa76 Giorgos Korfiatis
        provisions  -- resources with their quantity (dict from string to int)
570 3a1bed03 Giorgos Korfiatis
        name        -- description of the commission (string)
571 12eab714 Ilias Tsitsimpis
        force       -- force this commission (boolean)
572 12eab714 Ilias Tsitsimpis
        auto_accept -- auto accept this commission (boolean)
573 12eab714 Ilias Tsitsimpis

574 12eab714 Ilias Tsitsimpis
        In case of success return commission's id (int).
575 12eab714 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException.
576 12eab714 Ilias Tsitsimpis
        (See also issue_commission)
577 12eab714 Ilias Tsitsimpis

578 12eab714 Ilias Tsitsimpis
        """
579 d5f086f2 Ilias Tsitsimpis
        check_input("issue_one_commission", self.logger,
580 d5f086f2 Ilias Tsitsimpis
                    holder=holder, source=source,
581 d5f086f2 Ilias Tsitsimpis
                    provisions=provisions)
582 12eab714 Ilias Tsitsimpis
583 12eab714 Ilias Tsitsimpis
        request = {}
584 12eab714 Ilias Tsitsimpis
        request["force"] = force
585 12eab714 Ilias Tsitsimpis
        request["auto_accept"] = auto_accept
586 3a1bed03 Giorgos Korfiatis
        request["name"] = name
587 12eab714 Ilias Tsitsimpis
        try:
588 12eab714 Ilias Tsitsimpis
            request["provisions"] = []
589 567f49a2 Giorgos Korfiatis
            for resource, quantity in provisions.iteritems():
590 2c9c147e Ilias Tsitsimpis
                prov = {"holder": holder, "source": source,
591 2c9c147e Ilias Tsitsimpis
                        "resource": resource, "quantity": quantity}
592 2c9c147e Ilias Tsitsimpis
                request["provisions"].append(prov)
593 12eab714 Ilias Tsitsimpis
        except Exception as err:
594 12eab714 Ilias Tsitsimpis
            self.logger.error(str(err))
595 12eab714 Ilias Tsitsimpis
            raise BadValue(str(err))
596 12eab714 Ilias Tsitsimpis
597 2c9c147e Ilias Tsitsimpis
        return self.issue_commission(request)
598 12eab714 Ilias Tsitsimpis
599 7a0180ef Ilias Tsitsimpis
    # ----------------------------------
600 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_COMMISSIONS``
601 2c9c147e Ilias Tsitsimpis
    def get_pending_commissions(self):
602 7a0180ef Ilias Tsitsimpis
        """Get Pending Commissions
603 7a0180ef Ilias Tsitsimpis

604 7a0180ef Ilias Tsitsimpis
        In case of success return a list of pending commissions' ids
605 7a0180ef Ilias Tsitsimpis
        (list of integers)
606 7a0180ef Ilias Tsitsimpis

607 7a0180ef Ilias Tsitsimpis
        """
608 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_commissions)
609 7a0180ef Ilias Tsitsimpis
610 994f37b6 Ilias Tsitsimpis
    # ----------------------------------
611 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_COMMISSIONS``/<serial>
612 2c9c147e Ilias Tsitsimpis
    def get_commission_info(self, serial):
613 994f37b6 Ilias Tsitsimpis
        """Get Description of a Commission
614 994f37b6 Ilias Tsitsimpis

615 994f37b6 Ilias Tsitsimpis
        Keyword arguments:
616 994f37b6 Ilias Tsitsimpis
        serial  -- commission's id (int)
617 994f37b6 Ilias Tsitsimpis

618 994f37b6 Ilias Tsitsimpis
        In case of success return a dict of dicts containing
619 5c418e94 Ilias Tsitsimpis
        informations (details) about the requested commission
620 994f37b6 Ilias Tsitsimpis

621 994f37b6 Ilias Tsitsimpis
        """
622 10797183 Ilias Tsitsimpis
        check_input("get_commission_info", self.logger, serial=serial)
623 994f37b6 Ilias Tsitsimpis
624 2c9c147e Ilias Tsitsimpis
        path = self.api_commissions.rstrip('/') + "/" + str(serial)
625 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
626 994f37b6 Ilias Tsitsimpis
627 805e294c Ilias Tsitsimpis
    # ----------------------------------
628 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS``/<serial>/action"
629 2c9c147e Ilias Tsitsimpis
    def commission_action(self, serial, action):
630 b5008ef0 Ilias Tsitsimpis
        """Perform a commission action
631 805e294c Ilias Tsitsimpis

632 805e294c Ilias Tsitsimpis
        Keyword arguments:
633 805e294c Ilias Tsitsimpis
        serial  -- commission's id (int)
634 805e294c Ilias Tsitsimpis
        action  -- action to perform, currently accept/reject (string)
635 805e294c Ilias Tsitsimpis

636 805e294c Ilias Tsitsimpis
        In case of success return nothing.
637 805e294c Ilias Tsitsimpis

638 805e294c Ilias Tsitsimpis
        """
639 10797183 Ilias Tsitsimpis
        check_input("commission_action", self.logger,
640 10797183 Ilias Tsitsimpis
                    serial=serial, action=action)
641 805e294c Ilias Tsitsimpis
642 2c9c147e Ilias Tsitsimpis
        path = self.api_commissions.rstrip('/') + "/" + str(serial) + "/action"
643 805e294c Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
644 19198628 Ilias Tsitsimpis
        req_body = parse_request({str(action): ""}, self.logger)
645 2c9c147e Ilias Tsitsimpis
        self._call_astakos(path, headers=req_headers,
646 2c9c147e Ilias Tsitsimpis
                           body=req_body, method="POST")
647 805e294c Ilias Tsitsimpis
648 2c9c147e Ilias Tsitsimpis
    def accept_commission(self, serial):
649 b5008ef0 Ilias Tsitsimpis
        """Accept a commission (see commission_action)"""
650 2c9c147e Ilias Tsitsimpis
        self.commission_action(serial, "accept")
651 805e294c Ilias Tsitsimpis
652 2c9c147e Ilias Tsitsimpis
    def reject_commission(self, serial):
653 b5008ef0 Ilias Tsitsimpis
        """Reject a commission (see commission_action)"""
654 2c9c147e Ilias Tsitsimpis
        self.commission_action(serial, "reject")
655 805e294c Ilias Tsitsimpis
656 81875157 Ilias Tsitsimpis
    # ----------------------------------
657 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS_ACTION``
658 2c9c147e Ilias Tsitsimpis
    def resolve_commissions(self, accept_serials, reject_serials):
659 81875157 Ilias Tsitsimpis
        """Resolve multiple commissions at once
660 81875157 Ilias Tsitsimpis

661 81875157 Ilias Tsitsimpis
        Keyword arguments:
662 81875157 Ilias Tsitsimpis
        accept_serials  -- commissions to accept (list of ints)
663 81875157 Ilias Tsitsimpis
        reject_serials  -- commissions to reject (list of ints)
664 81875157 Ilias Tsitsimpis

665 81875157 Ilias Tsitsimpis
        In case of success return a dict of dicts describing which
666 81875157 Ilias Tsitsimpis
        commissions accepted, which rejected and which failed to
667 81875157 Ilias Tsitsimpis
        resolved.
668 81875157 Ilias Tsitsimpis

669 81875157 Ilias Tsitsimpis
        """
670 d5f086f2 Ilias Tsitsimpis
        check_input("resolve_commissions", self.logger,
671 d5f086f2 Ilias Tsitsimpis
                    accept_serials=accept_serials,
672 d5f086f2 Ilias Tsitsimpis
                    reject_serials=reject_serials)
673 81875157 Ilias Tsitsimpis
674 81875157 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
675 81875157 Ilias Tsitsimpis
        req_body = parse_request({"accept": accept_serials,
676 81875157 Ilias Tsitsimpis
                                  "reject": reject_serials},
677 81875157 Ilias Tsitsimpis
                                 self.logger)
678 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_commissions_action,
679 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body,
680 2c9c147e Ilias Tsitsimpis
                                  method="POST")
681 81875157 Ilias Tsitsimpis
682 47bb45c0 Giorgos Korfiatis
    # ----------------------------
683 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_PROJECTS``
684 2c9c147e Ilias Tsitsimpis
    def get_projects(self, name=None, state=None, owner=None):
685 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible projects
686 47bb45c0 Giorgos Korfiatis

687 47bb45c0 Giorgos Korfiatis
        Arguments:
688 47bb45c0 Giorgos Korfiatis
        name  -- filter by name (optional)
689 47bb45c0 Giorgos Korfiatis
        state -- filter by state (optional)
690 47bb45c0 Giorgos Korfiatis
        owner -- filter by owner (optional)
691 47bb45c0 Giorgos Korfiatis

692 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of project descriptions.
693 47bb45c0 Giorgos Korfiatis
        """
694 47bb45c0 Giorgos Korfiatis
        filters = {}
695 47bb45c0 Giorgos Korfiatis
        if name is not None:
696 47bb45c0 Giorgos Korfiatis
            filters["name"] = name
697 47bb45c0 Giorgos Korfiatis
        if state is not None:
698 47bb45c0 Giorgos Korfiatis
            filters["state"] = state
699 47bb45c0 Giorgos Korfiatis
        if owner is not None:
700 47bb45c0 Giorgos Korfiatis
            filters["owner"] = owner
701 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
702 47bb45c0 Giorgos Korfiatis
        req_body = (parse_request({"filter": filters}, self.logger)
703 47bb45c0 Giorgos Korfiatis
                    if filters else None)
704 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_projects,
705 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
706 47bb45c0 Giorgos Korfiatis
707 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
708 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_PROJECTS``/<project_id>
709 2c9c147e Ilias Tsitsimpis
    def get_project(self, project_id):
710 47bb45c0 Giorgos Korfiatis
        """Retrieve project description, if accessible
711 47bb45c0 Giorgos Korfiatis

712 47bb45c0 Giorgos Korfiatis
        Arguments:
713 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
714 47bb45c0 Giorgos Korfiatis

715 47bb45c0 Giorgos Korfiatis
        In case of success, return project description.
716 47bb45c0 Giorgos Korfiatis
        """
717 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
718 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
719 47bb45c0 Giorgos Korfiatis
720 47bb45c0 Giorgos Korfiatis
    # -----------------------------
721 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``
722 2c9c147e Ilias Tsitsimpis
    def create_project(self, specs):
723 47bb45c0 Giorgos Korfiatis
        """Submit application to create a new project
724 47bb45c0 Giorgos Korfiatis

725 47bb45c0 Giorgos Korfiatis
        Arguments:
726 47bb45c0 Giorgos Korfiatis
        specs -- dict describing a project
727 47bb45c0 Giorgos Korfiatis

728 47bb45c0 Giorgos Korfiatis
        In case of success, return project and application identifiers.
729 47bb45c0 Giorgos Korfiatis
        """
730 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
731 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(specs, self.logger)
732 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_projects,
733 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body,
734 2c9c147e Ilias Tsitsimpis
                                  method="POST")
735 47bb45c0 Giorgos Korfiatis
736 47bb45c0 Giorgos Korfiatis
    # ------------------------------------------
737 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``/<project_id>
738 2c9c147e Ilias Tsitsimpis
    def modify_project(self, project_id, specs):
739 47bb45c0 Giorgos Korfiatis
        """Submit application to modify an existing project
740 47bb45c0 Giorgos Korfiatis

741 47bb45c0 Giorgos Korfiatis
        Arguments:
742 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
743 47bb45c0 Giorgos Korfiatis
        specs      -- dict describing a project
744 47bb45c0 Giorgos Korfiatis

745 47bb45c0 Giorgos Korfiatis
        In case of success, return project and application identifiers.
746 47bb45c0 Giorgos Korfiatis
        """
747 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
748 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
749 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(specs, self.logger)
750 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
751 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
752 47bb45c0 Giorgos Korfiatis
753 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
754 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``/<project_id>/action
755 2c9c147e Ilias Tsitsimpis
    def project_action(self, project_id, action, reason=""):
756 47bb45c0 Giorgos Korfiatis
        """Perform action on a project
757 47bb45c0 Giorgos Korfiatis

758 47bb45c0 Giorgos Korfiatis
        Arguments:
759 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
760 47bb45c0 Giorgos Korfiatis
        action     -- action to perform, one of "suspend", "unsuspend",
761 47bb45c0 Giorgos Korfiatis
                      "terminate", "reinstate"
762 47bb45c0 Giorgos Korfiatis
        reason     -- reason of performing the action
763 47bb45c0 Giorgos Korfiatis

764 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
765 47bb45c0 Giorgos Korfiatis
        """
766 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
767 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
768 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
769 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
770 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
771 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
772 47bb45c0 Giorgos Korfiatis
773 47bb45c0 Giorgos Korfiatis
    # --------------------------------
774 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_APPLICATIONS``
775 2c9c147e Ilias Tsitsimpis
    def get_applications(self, project=None):
776 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible applications
777 47bb45c0 Giorgos Korfiatis

778 47bb45c0 Giorgos Korfiatis
        Arguments:
779 47bb45c0 Giorgos Korfiatis
        project -- filter by project (optional)
780 47bb45c0 Giorgos Korfiatis

781 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of application descriptions.
782 47bb45c0 Giorgos Korfiatis
        """
783 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
784 47bb45c0 Giorgos Korfiatis
        body = {"project": project} if project is not None else None
785 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger) if body else None
786 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_applications,
787 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
788 47bb45c0 Giorgos Korfiatis
789 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
790 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_APPLICATIONS``/<app_id>
791 2c9c147e Ilias Tsitsimpis
    def get_application(self, app_id):
792 47bb45c0 Giorgos Korfiatis
        """Retrieve application description, if accessible
793 47bb45c0 Giorgos Korfiatis

794 47bb45c0 Giorgos Korfiatis
        Arguments:
795 47bb45c0 Giorgos Korfiatis
        app_id -- application identifier
796 47bb45c0 Giorgos Korfiatis

797 47bb45c0 Giorgos Korfiatis
        In case of success, return application description.
798 47bb45c0 Giorgos Korfiatis
        """
799 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_applications, str(app_id))
800 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
801 47bb45c0 Giorgos Korfiatis
802 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
803 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_APPLICATIONS``/<app_id>/action
804 2c9c147e Ilias Tsitsimpis
    def application_action(self, app_id, action, reason=""):
805 47bb45c0 Giorgos Korfiatis
        """Perform action on an application
806 47bb45c0 Giorgos Korfiatis

807 47bb45c0 Giorgos Korfiatis
        Arguments:
808 47bb45c0 Giorgos Korfiatis
        app_id -- application identifier
809 47bb45c0 Giorgos Korfiatis
        action -- action to perform, one of "approve", "deny",
810 47bb45c0 Giorgos Korfiatis
                  "dismiss", "cancel"
811 47bb45c0 Giorgos Korfiatis
        reason -- reason of performing the action
812 47bb45c0 Giorgos Korfiatis

813 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
814 47bb45c0 Giorgos Korfiatis
        """
815 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_applications, str(app_id))
816 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
817 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
818 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
819 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
820 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
821 47bb45c0 Giorgos Korfiatis
822 47bb45c0 Giorgos Korfiatis
    # -------------------------------
823 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_MEMBERSHIPS``
824 2c9c147e Ilias Tsitsimpis
    def get_memberships(self, project=None):
825 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible memberships
826 47bb45c0 Giorgos Korfiatis

827 47bb45c0 Giorgos Korfiatis
        Arguments:
828 47bb45c0 Giorgos Korfiatis
        project -- filter by project (optional)
829 47bb45c0 Giorgos Korfiatis

830 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of membership descriptions.
831 47bb45c0 Giorgos Korfiatis
        """
832 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
833 47bb45c0 Giorgos Korfiatis
        body = {"project": project} if project is not None else None
834 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger) if body else None
835 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships,
836 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
837 47bb45c0 Giorgos Korfiatis
838 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
839 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_MEMBERSHIPS``/<memb_id>
840 2c9c147e Ilias Tsitsimpis
    def get_membership(self, memb_id):
841 47bb45c0 Giorgos Korfiatis
        """Retrieve membership description, if accessible
842 47bb45c0 Giorgos Korfiatis

843 47bb45c0 Giorgos Korfiatis
        Arguments:
844 47bb45c0 Giorgos Korfiatis
        memb_id -- membership identifier
845 47bb45c0 Giorgos Korfiatis

846 47bb45c0 Giorgos Korfiatis
        In case of success, return membership description.
847 47bb45c0 Giorgos Korfiatis
        """
848 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_memberships, str(memb_id))
849 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
850 47bb45c0 Giorgos Korfiatis
851 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
852 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``/<memb_id>/action
853 2c9c147e Ilias Tsitsimpis
    def membership_action(self, memb_id, action, reason=""):
854 47bb45c0 Giorgos Korfiatis
        """Perform action on a membership
855 47bb45c0 Giorgos Korfiatis

856 47bb45c0 Giorgos Korfiatis
        Arguments:
857 47bb45c0 Giorgos Korfiatis
        memb_id -- membership identifier
858 47bb45c0 Giorgos Korfiatis
        action  -- action to perform, one of "leave", "cancel", "accept",
859 47bb45c0 Giorgos Korfiatis
                   "reject", "remove"
860 47bb45c0 Giorgos Korfiatis
        reason  -- reason of performing the action
861 47bb45c0 Giorgos Korfiatis

862 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
863 47bb45c0 Giorgos Korfiatis
        """
864 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_memberships, str(memb_id))
865 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
866 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
867 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
868 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
869 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
870 47bb45c0 Giorgos Korfiatis
871 47bb45c0 Giorgos Korfiatis
    # --------------------------------
872 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``
873 2c9c147e Ilias Tsitsimpis
    def join_project(self, project_id):
874 47bb45c0 Giorgos Korfiatis
        """Join a project
875 47bb45c0 Giorgos Korfiatis

876 47bb45c0 Giorgos Korfiatis
        Arguments:
877 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
878 47bb45c0 Giorgos Korfiatis

879 47bb45c0 Giorgos Korfiatis
        In case of success, return membership identifier.
880 47bb45c0 Giorgos Korfiatis
        """
881 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
882 47bb45c0 Giorgos Korfiatis
        body = {"join": {"project": project_id}}
883 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger)
884 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships, headers=req_headers,
885 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
886 47bb45c0 Giorgos Korfiatis
887 47bb45c0 Giorgos Korfiatis
    # --------------------------------
888 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``
889 2c9c147e Ilias Tsitsimpis
    def enroll_member(self, project_id, email):
890 47bb45c0 Giorgos Korfiatis
        """Enroll a user in a project
891 47bb45c0 Giorgos Korfiatis

892 47bb45c0 Giorgos Korfiatis
        Arguments:
893 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
894 47bb45c0 Giorgos Korfiatis
        email      -- user identified by email
895 47bb45c0 Giorgos Korfiatis

896 47bb45c0 Giorgos Korfiatis
        In case of success, return membership identifier.
897 47bb45c0 Giorgos Korfiatis
        """
898 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
899 47bb45c0 Giorgos Korfiatis
        body = {"enroll": {"project": project_id, "user": email}}
900 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger)
901 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships, headers=req_headers,
902 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
903 2c9c147e Ilias Tsitsimpis
904 d2104099 Sofia Papagiannaki
    # --------------------------------
905 d2104099 Sofia Papagiannaki
    # do a POST to ``API_OA2_TOKEN``
906 d2104099 Sofia Papagiannaki
    def get_token(self, grant_type, client_id, client_secret, **body_params):
907 d2104099 Sofia Papagiannaki
        headers = {'Content-Type': 'application/x-www-form-urlencoded',
908 d2104099 Sofia Papagiannaki
                   'Authorization': 'Basic %s' % b64encode('%s:%s' %
909 d2104099 Sofia Papagiannaki
                                                           (client_id,
910 d2104099 Sofia Papagiannaki
                                                            client_secret))}
911 d2104099 Sofia Papagiannaki
        body_params['grant_type'] = grant_type
912 d2104099 Sofia Papagiannaki
        body = urllib.urlencode(body_params)
913 d2104099 Sofia Papagiannaki
        return self._call_astakos(self.api_oa2_token, headers=headers,
914 d2104099 Sofia Papagiannaki
                                  body=body, method="POST")
915 d2104099 Sofia Papagiannaki
916 2c9c147e Ilias Tsitsimpis
917 2c9c147e Ilias Tsitsimpis
# --------------------------------------------------------------------
918 2c9c147e Ilias Tsitsimpis
# parse endpoints
919 2c9c147e Ilias Tsitsimpis
def parse_endpoints(endpoints, ep_name=None, ep_type=None,
920 2c9c147e Ilias Tsitsimpis
                    ep_region=None, ep_version_id=None):
921 2c9c147e Ilias Tsitsimpis
    """Parse endpoints server response and extract the ones needed
922 2c9c147e Ilias Tsitsimpis

923 2c9c147e Ilias Tsitsimpis
    Keyword arguments:
924 2c9c147e Ilias Tsitsimpis
    endpoints     -- the endpoints (json response from get_endpoints)
925 2c9c147e Ilias Tsitsimpis
    ep_name       -- return only endpoints with this name (optional)
926 2c9c147e Ilias Tsitsimpis
    ep_type       -- return only endpoints with this type (optional)
927 2c9c147e Ilias Tsitsimpis
    ep_region     -- return only endpoints with this region (optional)
928 2c9c147e Ilias Tsitsimpis
    ep_version_id -- return only endpoints with this versionId (optional)
929 2c9c147e Ilias Tsitsimpis

930 9c3cbd0d Ilias Tsitsimpis
    In case one of the `name', `type', `region', `version_id' parameters
931 2c9c147e Ilias Tsitsimpis
    is given, return only the endpoints that match all of these criteria.
932 2c9c147e Ilias Tsitsimpis
    If no match is found then raise NoEndpoints exception.
933 2c9c147e Ilias Tsitsimpis

934 2c9c147e Ilias Tsitsimpis
    """
935 2c9c147e Ilias Tsitsimpis
    try:
936 2c9c147e Ilias Tsitsimpis
        catalog = endpoints['access']['serviceCatalog']
937 2c9c147e Ilias Tsitsimpis
        if ep_name is not None:
938 2c9c147e Ilias Tsitsimpis
            catalog = \
939 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['name'] == ep_name]
940 2c9c147e Ilias Tsitsimpis
        if ep_type is not None:
941 2c9c147e Ilias Tsitsimpis
            catalog = \
942 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['type'] == ep_type]
943 2c9c147e Ilias Tsitsimpis
        if ep_region is not None:
944 2c9c147e Ilias Tsitsimpis
            for c in catalog:
945 2c9c147e Ilias Tsitsimpis
                c['endpoints'] = [e for e in c['endpoints']
946 2c9c147e Ilias Tsitsimpis
                                  if e['region'] == ep_region]
947 2c9c147e Ilias Tsitsimpis
            # Remove catalog entries with no endpoints
948 2c9c147e Ilias Tsitsimpis
            catalog = \
949 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['endpoints']]
950 2c9c147e Ilias Tsitsimpis
        if ep_version_id is not None:
951 2c9c147e Ilias Tsitsimpis
            for c in catalog:
952 2c9c147e Ilias Tsitsimpis
                c['endpoints'] = [e for e in c['endpoints']
953 2c9c147e Ilias Tsitsimpis
                                  if e['versionId'] == ep_version_id]
954 2c9c147e Ilias Tsitsimpis
            # Remove catalog entries with no endpoints
955 2c9c147e Ilias Tsitsimpis
            catalog = \
956 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['endpoints']]
957 2c9c147e Ilias Tsitsimpis
958 2c9c147e Ilias Tsitsimpis
        if not catalog:
959 2c9c147e Ilias Tsitsimpis
            raise NoEndpoints(ep_name, ep_type,
960 2c9c147e Ilias Tsitsimpis
                              ep_region, ep_version_id)
961 2c9c147e Ilias Tsitsimpis
        else:
962 2c9c147e Ilias Tsitsimpis
            return catalog
963 2c9c147e Ilias Tsitsimpis
    except KeyError:
964 2c9c147e Ilias Tsitsimpis
        raise NoEndpoints()
965 2c9c147e Ilias Tsitsimpis
966 f54cf5e4 Ilias Tsitsimpis
967 f54cf5e4 Ilias Tsitsimpis
# --------------------------------------------------------------------
968 cbc0b438 Ilias Tsitsimpis
# Private functions
969 45c0bcf8 Giorgos Korfiatis
# We want _do_request to be a distinct function
970 f93cc364 Ilias Tsitsimpis
# so that we can replace it during unit tests.
971 794c94e6 Ilias Tsitsimpis
def _do_request(conn, method, url, **kwargs):
972 f8388a90 Ilias Tsitsimpis
    """The actual request. This function can easily be mocked"""
973 f8388a90 Ilias Tsitsimpis
    conn.request(method, url, **kwargs)
974 f8388a90 Ilias Tsitsimpis
    response = conn.getresponse()
975 f8388a90 Ilias Tsitsimpis
    length = response.getheader('content-length', None)
976 f8388a90 Ilias Tsitsimpis
    data = response.read(length)
977 f8388a90 Ilias Tsitsimpis
    status = int(response.status)
978 21190887 Ilias Tsitsimpis
    message = response.reason
979 21190887 Ilias Tsitsimpis
    return (message, data, status)