Statistics
| Branch: | Tag: | Revision:

root / astakosclient / astakosclient / __init__.py @ 75144caa

History | View | Annotate | Download (36.8 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 b39ca571 Sofia Papagiannaki
    # --------------------------------------
501 b39ca571 Sofia Papagiannaki
    # do a GET to ``API_TOKENS`` with a token
502 b39ca571 Sofia Papagiannaki
    def validate_token(self, token_id, belongsTo=None):
503 b39ca571 Sofia Papagiannaki
        """ Validate a temporary access token (oath2)
504 b39ca571 Sofia Papagiannaki

505 b39ca571 Sofia Papagiannaki
        Keyword arguments:
506 b39ca571 Sofia Papagiannaki
        belongsTo         -- confirm that token belongs to tenant
507 b39ca571 Sofia Papagiannaki

508 b39ca571 Sofia Papagiannaki
        It returns back the token as well as information about the token
509 b39ca571 Sofia Papagiannaki
        holder.
510 b39ca571 Sofia Papagiannaki

511 b39ca571 Sofia Papagiannaki
        The belongsTo is optional and if it is given it must be inside the
512 b39ca571 Sofia Papagiannaki
        token's scope.
513 b39ca571 Sofia Papagiannaki

514 b39ca571 Sofia Papagiannaki
        In case of error raise an AstakosClientException.
515 b39ca571 Sofia Papagiannaki

516 b39ca571 Sofia Papagiannaki
        """
517 b39ca571 Sofia Papagiannaki
        path = join_urls(self.api_tokens, str(token_id))
518 b39ca571 Sofia Papagiannaki
        if belongsTo is not None:
519 b39ca571 Sofia Papagiannaki
            params = {'belongsTo': belongsTo}
520 b39ca571 Sofia Papagiannaki
            path = '%s?%s' % (path, urllib.urlencode(params))
521 b39ca571 Sofia Papagiannaki
        return self._call_astakos(path, method="GET", log_body=False)
522 b39ca571 Sofia Papagiannaki
523 25a04cdd Ilias Tsitsimpis
    # ----------------------------------
524 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_QUOTAS``
525 2c9c147e Ilias Tsitsimpis
    def get_quotas(self):
526 fd420756 Ilias Tsitsimpis
        """Get user's quotas
527 fd420756 Ilias Tsitsimpis

528 fd420756 Ilias Tsitsimpis
        In case of success return a dict of dicts with user's current quotas.
529 fd420756 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException
530 fd420756 Ilias Tsitsimpis

531 fd420756 Ilias Tsitsimpis
        """
532 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_quotas)
533 baeb2ba5 Ilias Tsitsimpis
534 fd420756 Ilias Tsitsimpis
    # ----------------------------------
535 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_SERVICE_QUOTAS``
536 2c9c147e Ilias Tsitsimpis
    def service_get_quotas(self, user=None):
537 5b33b8e5 Giorgos Korfiatis
        """Get all quotas for resources associated with the service
538 5b33b8e5 Giorgos Korfiatis

539 5b33b8e5 Giorgos Korfiatis
        Keyword arguments:
540 db9f7a2b Giorgos Korfiatis
        user    -- optionally, the uuid of a specific user
541 5b33b8e5 Giorgos Korfiatis

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

546 5b33b8e5 Giorgos Korfiatis
        """
547 2c9c147e Ilias Tsitsimpis
        query = self.api_service_quotas
548 db9f7a2b Giorgos Korfiatis
        if user is not None:
549 db9f7a2b Giorgos Korfiatis
            query += "?user=" + user
550 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(query)
551 5b33b8e5 Giorgos Korfiatis
552 5b33b8e5 Giorgos Korfiatis
    # ----------------------------------
553 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS``
554 2c9c147e Ilias Tsitsimpis
    def issue_commission(self, request):
555 fd420756 Ilias Tsitsimpis
        """Issue a commission
556 fd420756 Ilias Tsitsimpis

557 fd420756 Ilias Tsitsimpis
        Keyword arguments:
558 fd420756 Ilias Tsitsimpis
        request -- commision request (dict)
559 fd420756 Ilias Tsitsimpis

560 fd420756 Ilias Tsitsimpis
        In case of success return commission's id (int).
561 fd420756 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException.
562 fd420756 Ilias Tsitsimpis

563 fd420756 Ilias Tsitsimpis
        """
564 fd420756 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
565 19198628 Ilias Tsitsimpis
        req_body = parse_request(request, self.logger)
566 fd420756 Ilias Tsitsimpis
        try:
567 2c9c147e Ilias Tsitsimpis
            response = self._call_astakos(self.api_commissions,
568 2c9c147e Ilias Tsitsimpis
                                          headers=req_headers,
569 2c9c147e Ilias Tsitsimpis
                                          body=req_body,
570 2c9c147e Ilias Tsitsimpis
                                          method="POST")
571 fd420756 Ilias Tsitsimpis
        except AstakosClientException as err:
572 fd420756 Ilias Tsitsimpis
            if err.status == 413:
573 fd420756 Ilias Tsitsimpis
                raise QuotaLimit(err.message, err.details)
574 fd420756 Ilias Tsitsimpis
            else:
575 fd420756 Ilias Tsitsimpis
                raise
576 fd420756 Ilias Tsitsimpis
577 fd420756 Ilias Tsitsimpis
        if "serial" in response:
578 fd420756 Ilias Tsitsimpis
            return response['serial']
579 fd420756 Ilias Tsitsimpis
        else:
580 2c9c147e Ilias Tsitsimpis
            msg = "issue_commission_core request returned %s. " + \
581 2c9c147e Ilias Tsitsimpis
                  "No serial found" % response
582 2c9c147e Ilias Tsitsimpis
            self.logger.error(msg)
583 2c9c147e Ilias Tsitsimpis
            raise AstakosClientException(msg)
584 fd420756 Ilias Tsitsimpis
585 2c9c147e Ilias Tsitsimpis
    def issue_one_commission(self, holder, source, provisions,
586 3a1bed03 Giorgos Korfiatis
                             name="", force=False, auto_accept=False):
587 12eab714 Ilias Tsitsimpis
        """Issue one commission (with specific holder and source)
588 12eab714 Ilias Tsitsimpis

589 12eab714 Ilias Tsitsimpis
        keyword arguments:
590 12eab714 Ilias Tsitsimpis
        holder      -- user's id (string)
591 12eab714 Ilias Tsitsimpis
        source      -- commission's source (ex system) (string)
592 8b68fa76 Giorgos Korfiatis
        provisions  -- resources with their quantity (dict from string to int)
593 3a1bed03 Giorgos Korfiatis
        name        -- description of the commission (string)
594 12eab714 Ilias Tsitsimpis
        force       -- force this commission (boolean)
595 12eab714 Ilias Tsitsimpis
        auto_accept -- auto accept this commission (boolean)
596 12eab714 Ilias Tsitsimpis

597 12eab714 Ilias Tsitsimpis
        In case of success return commission's id (int).
598 12eab714 Ilias Tsitsimpis
        Otherwise raise an AstakosClientException.
599 12eab714 Ilias Tsitsimpis
        (See also issue_commission)
600 12eab714 Ilias Tsitsimpis

601 12eab714 Ilias Tsitsimpis
        """
602 d5f086f2 Ilias Tsitsimpis
        check_input("issue_one_commission", self.logger,
603 d5f086f2 Ilias Tsitsimpis
                    holder=holder, source=source,
604 d5f086f2 Ilias Tsitsimpis
                    provisions=provisions)
605 12eab714 Ilias Tsitsimpis
606 12eab714 Ilias Tsitsimpis
        request = {}
607 12eab714 Ilias Tsitsimpis
        request["force"] = force
608 12eab714 Ilias Tsitsimpis
        request["auto_accept"] = auto_accept
609 3a1bed03 Giorgos Korfiatis
        request["name"] = name
610 12eab714 Ilias Tsitsimpis
        try:
611 12eab714 Ilias Tsitsimpis
            request["provisions"] = []
612 567f49a2 Giorgos Korfiatis
            for resource, quantity in provisions.iteritems():
613 2c9c147e Ilias Tsitsimpis
                prov = {"holder": holder, "source": source,
614 2c9c147e Ilias Tsitsimpis
                        "resource": resource, "quantity": quantity}
615 2c9c147e Ilias Tsitsimpis
                request["provisions"].append(prov)
616 12eab714 Ilias Tsitsimpis
        except Exception as err:
617 12eab714 Ilias Tsitsimpis
            self.logger.error(str(err))
618 12eab714 Ilias Tsitsimpis
            raise BadValue(str(err))
619 12eab714 Ilias Tsitsimpis
620 2c9c147e Ilias Tsitsimpis
        return self.issue_commission(request)
621 12eab714 Ilias Tsitsimpis
622 7a0180ef Ilias Tsitsimpis
    # ----------------------------------
623 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_COMMISSIONS``
624 2c9c147e Ilias Tsitsimpis
    def get_pending_commissions(self):
625 7a0180ef Ilias Tsitsimpis
        """Get Pending Commissions
626 7a0180ef Ilias Tsitsimpis

627 7a0180ef Ilias Tsitsimpis
        In case of success return a list of pending commissions' ids
628 7a0180ef Ilias Tsitsimpis
        (list of integers)
629 7a0180ef Ilias Tsitsimpis

630 7a0180ef Ilias Tsitsimpis
        """
631 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_commissions)
632 7a0180ef Ilias Tsitsimpis
633 994f37b6 Ilias Tsitsimpis
    # ----------------------------------
634 7b5a37fd Ilias Tsitsimpis
    # do a GET to ``API_COMMISSIONS``/<serial>
635 2c9c147e Ilias Tsitsimpis
    def get_commission_info(self, serial):
636 994f37b6 Ilias Tsitsimpis
        """Get Description of a Commission
637 994f37b6 Ilias Tsitsimpis

638 994f37b6 Ilias Tsitsimpis
        Keyword arguments:
639 994f37b6 Ilias Tsitsimpis
        serial  -- commission's id (int)
640 994f37b6 Ilias Tsitsimpis

641 994f37b6 Ilias Tsitsimpis
        In case of success return a dict of dicts containing
642 5c418e94 Ilias Tsitsimpis
        informations (details) about the requested commission
643 994f37b6 Ilias Tsitsimpis

644 994f37b6 Ilias Tsitsimpis
        """
645 10797183 Ilias Tsitsimpis
        check_input("get_commission_info", self.logger, serial=serial)
646 994f37b6 Ilias Tsitsimpis
647 2c9c147e Ilias Tsitsimpis
        path = self.api_commissions.rstrip('/') + "/" + str(serial)
648 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
649 994f37b6 Ilias Tsitsimpis
650 805e294c Ilias Tsitsimpis
    # ----------------------------------
651 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS``/<serial>/action"
652 2c9c147e Ilias Tsitsimpis
    def commission_action(self, serial, action):
653 b5008ef0 Ilias Tsitsimpis
        """Perform a commission action
654 805e294c Ilias Tsitsimpis

655 805e294c Ilias Tsitsimpis
        Keyword arguments:
656 805e294c Ilias Tsitsimpis
        serial  -- commission's id (int)
657 805e294c Ilias Tsitsimpis
        action  -- action to perform, currently accept/reject (string)
658 805e294c Ilias Tsitsimpis

659 805e294c Ilias Tsitsimpis
        In case of success return nothing.
660 805e294c Ilias Tsitsimpis

661 805e294c Ilias Tsitsimpis
        """
662 10797183 Ilias Tsitsimpis
        check_input("commission_action", self.logger,
663 10797183 Ilias Tsitsimpis
                    serial=serial, action=action)
664 805e294c Ilias Tsitsimpis
665 2c9c147e Ilias Tsitsimpis
        path = self.api_commissions.rstrip('/') + "/" + str(serial) + "/action"
666 805e294c Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
667 19198628 Ilias Tsitsimpis
        req_body = parse_request({str(action): ""}, self.logger)
668 2c9c147e Ilias Tsitsimpis
        self._call_astakos(path, headers=req_headers,
669 2c9c147e Ilias Tsitsimpis
                           body=req_body, method="POST")
670 805e294c Ilias Tsitsimpis
671 2c9c147e Ilias Tsitsimpis
    def accept_commission(self, serial):
672 b5008ef0 Ilias Tsitsimpis
        """Accept a commission (see commission_action)"""
673 2c9c147e Ilias Tsitsimpis
        self.commission_action(serial, "accept")
674 805e294c Ilias Tsitsimpis
675 2c9c147e Ilias Tsitsimpis
    def reject_commission(self, serial):
676 b5008ef0 Ilias Tsitsimpis
        """Reject a commission (see commission_action)"""
677 2c9c147e Ilias Tsitsimpis
        self.commission_action(serial, "reject")
678 805e294c Ilias Tsitsimpis
679 81875157 Ilias Tsitsimpis
    # ----------------------------------
680 7b5a37fd Ilias Tsitsimpis
    # do a POST to ``API_COMMISSIONS_ACTION``
681 2c9c147e Ilias Tsitsimpis
    def resolve_commissions(self, accept_serials, reject_serials):
682 81875157 Ilias Tsitsimpis
        """Resolve multiple commissions at once
683 81875157 Ilias Tsitsimpis

684 81875157 Ilias Tsitsimpis
        Keyword arguments:
685 81875157 Ilias Tsitsimpis
        accept_serials  -- commissions to accept (list of ints)
686 81875157 Ilias Tsitsimpis
        reject_serials  -- commissions to reject (list of ints)
687 81875157 Ilias Tsitsimpis

688 81875157 Ilias Tsitsimpis
        In case of success return a dict of dicts describing which
689 81875157 Ilias Tsitsimpis
        commissions accepted, which rejected and which failed to
690 81875157 Ilias Tsitsimpis
        resolved.
691 81875157 Ilias Tsitsimpis

692 81875157 Ilias Tsitsimpis
        """
693 d5f086f2 Ilias Tsitsimpis
        check_input("resolve_commissions", self.logger,
694 d5f086f2 Ilias Tsitsimpis
                    accept_serials=accept_serials,
695 d5f086f2 Ilias Tsitsimpis
                    reject_serials=reject_serials)
696 81875157 Ilias Tsitsimpis
697 81875157 Ilias Tsitsimpis
        req_headers = {'content-type': 'application/json'}
698 81875157 Ilias Tsitsimpis
        req_body = parse_request({"accept": accept_serials,
699 81875157 Ilias Tsitsimpis
                                  "reject": reject_serials},
700 81875157 Ilias Tsitsimpis
                                 self.logger)
701 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_commissions_action,
702 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body,
703 2c9c147e Ilias Tsitsimpis
                                  method="POST")
704 81875157 Ilias Tsitsimpis
705 47bb45c0 Giorgos Korfiatis
    # ----------------------------
706 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_PROJECTS``
707 2c9c147e Ilias Tsitsimpis
    def get_projects(self, name=None, state=None, owner=None):
708 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible projects
709 47bb45c0 Giorgos Korfiatis

710 47bb45c0 Giorgos Korfiatis
        Arguments:
711 47bb45c0 Giorgos Korfiatis
        name  -- filter by name (optional)
712 47bb45c0 Giorgos Korfiatis
        state -- filter by state (optional)
713 47bb45c0 Giorgos Korfiatis
        owner -- filter by owner (optional)
714 47bb45c0 Giorgos Korfiatis

715 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of project descriptions.
716 47bb45c0 Giorgos Korfiatis
        """
717 47bb45c0 Giorgos Korfiatis
        filters = {}
718 47bb45c0 Giorgos Korfiatis
        if name is not None:
719 47bb45c0 Giorgos Korfiatis
            filters["name"] = name
720 47bb45c0 Giorgos Korfiatis
        if state is not None:
721 47bb45c0 Giorgos Korfiatis
            filters["state"] = state
722 47bb45c0 Giorgos Korfiatis
        if owner is not None:
723 47bb45c0 Giorgos Korfiatis
            filters["owner"] = owner
724 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
725 47bb45c0 Giorgos Korfiatis
        req_body = (parse_request({"filter": filters}, self.logger)
726 47bb45c0 Giorgos Korfiatis
                    if filters else None)
727 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_projects,
728 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
729 47bb45c0 Giorgos Korfiatis
730 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
731 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_PROJECTS``/<project_id>
732 2c9c147e Ilias Tsitsimpis
    def get_project(self, project_id):
733 47bb45c0 Giorgos Korfiatis
        """Retrieve project description, if accessible
734 47bb45c0 Giorgos Korfiatis

735 47bb45c0 Giorgos Korfiatis
        Arguments:
736 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
737 47bb45c0 Giorgos Korfiatis

738 47bb45c0 Giorgos Korfiatis
        In case of success, return project description.
739 47bb45c0 Giorgos Korfiatis
        """
740 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
741 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
742 47bb45c0 Giorgos Korfiatis
743 47bb45c0 Giorgos Korfiatis
    # -----------------------------
744 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``
745 2c9c147e Ilias Tsitsimpis
    def create_project(self, specs):
746 47bb45c0 Giorgos Korfiatis
        """Submit application to create a new project
747 47bb45c0 Giorgos Korfiatis

748 47bb45c0 Giorgos Korfiatis
        Arguments:
749 47bb45c0 Giorgos Korfiatis
        specs -- dict describing a project
750 47bb45c0 Giorgos Korfiatis

751 47bb45c0 Giorgos Korfiatis
        In case of success, return project and application identifiers.
752 47bb45c0 Giorgos Korfiatis
        """
753 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
754 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(specs, self.logger)
755 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_projects,
756 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body,
757 2c9c147e Ilias Tsitsimpis
                                  method="POST")
758 47bb45c0 Giorgos Korfiatis
759 47bb45c0 Giorgos Korfiatis
    # ------------------------------------------
760 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``/<project_id>
761 2c9c147e Ilias Tsitsimpis
    def modify_project(self, project_id, specs):
762 47bb45c0 Giorgos Korfiatis
        """Submit application to modify an existing project
763 47bb45c0 Giorgos Korfiatis

764 47bb45c0 Giorgos Korfiatis
        Arguments:
765 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
766 47bb45c0 Giorgos Korfiatis
        specs      -- dict describing a project
767 47bb45c0 Giorgos Korfiatis

768 47bb45c0 Giorgos Korfiatis
        In case of success, return project and application identifiers.
769 47bb45c0 Giorgos Korfiatis
        """
770 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
771 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
772 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(specs, self.logger)
773 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
774 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
775 47bb45c0 Giorgos Korfiatis
776 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
777 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_PROJECTS``/<project_id>/action
778 2c9c147e Ilias Tsitsimpis
    def project_action(self, project_id, action, reason=""):
779 47bb45c0 Giorgos Korfiatis
        """Perform action on a project
780 47bb45c0 Giorgos Korfiatis

781 47bb45c0 Giorgos Korfiatis
        Arguments:
782 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
783 47bb45c0 Giorgos Korfiatis
        action     -- action to perform, one of "suspend", "unsuspend",
784 47bb45c0 Giorgos Korfiatis
                      "terminate", "reinstate"
785 47bb45c0 Giorgos Korfiatis
        reason     -- reason of performing the action
786 47bb45c0 Giorgos Korfiatis

787 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
788 47bb45c0 Giorgos Korfiatis
        """
789 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_projects, str(project_id))
790 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
791 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
792 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
793 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
794 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
795 47bb45c0 Giorgos Korfiatis
796 47bb45c0 Giorgos Korfiatis
    # --------------------------------
797 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_APPLICATIONS``
798 2c9c147e Ilias Tsitsimpis
    def get_applications(self, project=None):
799 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible applications
800 47bb45c0 Giorgos Korfiatis

801 47bb45c0 Giorgos Korfiatis
        Arguments:
802 47bb45c0 Giorgos Korfiatis
        project -- filter by project (optional)
803 47bb45c0 Giorgos Korfiatis

804 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of application descriptions.
805 47bb45c0 Giorgos Korfiatis
        """
806 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
807 47bb45c0 Giorgos Korfiatis
        body = {"project": project} if project is not None else None
808 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger) if body else None
809 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_applications,
810 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
811 47bb45c0 Giorgos Korfiatis
812 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
813 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_APPLICATIONS``/<app_id>
814 2c9c147e Ilias Tsitsimpis
    def get_application(self, app_id):
815 47bb45c0 Giorgos Korfiatis
        """Retrieve application description, if accessible
816 47bb45c0 Giorgos Korfiatis

817 47bb45c0 Giorgos Korfiatis
        Arguments:
818 47bb45c0 Giorgos Korfiatis
        app_id -- application identifier
819 47bb45c0 Giorgos Korfiatis

820 47bb45c0 Giorgos Korfiatis
        In case of success, return application description.
821 47bb45c0 Giorgos Korfiatis
        """
822 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_applications, str(app_id))
823 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
824 47bb45c0 Giorgos Korfiatis
825 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
826 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_APPLICATIONS``/<app_id>/action
827 2c9c147e Ilias Tsitsimpis
    def application_action(self, app_id, action, reason=""):
828 47bb45c0 Giorgos Korfiatis
        """Perform action on an application
829 47bb45c0 Giorgos Korfiatis

830 47bb45c0 Giorgos Korfiatis
        Arguments:
831 47bb45c0 Giorgos Korfiatis
        app_id -- application identifier
832 47bb45c0 Giorgos Korfiatis
        action -- action to perform, one of "approve", "deny",
833 47bb45c0 Giorgos Korfiatis
                  "dismiss", "cancel"
834 47bb45c0 Giorgos Korfiatis
        reason -- reason of performing the action
835 47bb45c0 Giorgos Korfiatis

836 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
837 47bb45c0 Giorgos Korfiatis
        """
838 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_applications, str(app_id))
839 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
840 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
841 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
842 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
843 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
844 47bb45c0 Giorgos Korfiatis
845 47bb45c0 Giorgos Korfiatis
    # -------------------------------
846 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_MEMBERSHIPS``
847 2c9c147e Ilias Tsitsimpis
    def get_memberships(self, project=None):
848 47bb45c0 Giorgos Korfiatis
        """Retrieve all accessible memberships
849 47bb45c0 Giorgos Korfiatis

850 47bb45c0 Giorgos Korfiatis
        Arguments:
851 47bb45c0 Giorgos Korfiatis
        project -- filter by project (optional)
852 47bb45c0 Giorgos Korfiatis

853 47bb45c0 Giorgos Korfiatis
        In case of success, return a list of membership descriptions.
854 47bb45c0 Giorgos Korfiatis
        """
855 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
856 47bb45c0 Giorgos Korfiatis
        body = {"project": project} if project is not None else None
857 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger) if body else None
858 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships,
859 2c9c147e Ilias Tsitsimpis
                                  headers=req_headers, body=req_body)
860 47bb45c0 Giorgos Korfiatis
861 47bb45c0 Giorgos Korfiatis
    # -----------------------------------------
862 47bb45c0 Giorgos Korfiatis
    # do a GET to ``API_MEMBERSHIPS``/<memb_id>
863 2c9c147e Ilias Tsitsimpis
    def get_membership(self, memb_id):
864 47bb45c0 Giorgos Korfiatis
        """Retrieve membership description, if accessible
865 47bb45c0 Giorgos Korfiatis

866 47bb45c0 Giorgos Korfiatis
        Arguments:
867 47bb45c0 Giorgos Korfiatis
        memb_id -- membership identifier
868 47bb45c0 Giorgos Korfiatis

869 47bb45c0 Giorgos Korfiatis
        In case of success, return membership description.
870 47bb45c0 Giorgos Korfiatis
        """
871 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_memberships, str(memb_id))
872 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path)
873 47bb45c0 Giorgos Korfiatis
874 47bb45c0 Giorgos Korfiatis
    # -------------------------------------------------
875 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``/<memb_id>/action
876 2c9c147e Ilias Tsitsimpis
    def membership_action(self, memb_id, action, reason=""):
877 47bb45c0 Giorgos Korfiatis
        """Perform action on a membership
878 47bb45c0 Giorgos Korfiatis

879 47bb45c0 Giorgos Korfiatis
        Arguments:
880 47bb45c0 Giorgos Korfiatis
        memb_id -- membership identifier
881 47bb45c0 Giorgos Korfiatis
        action  -- action to perform, one of "leave", "cancel", "accept",
882 47bb45c0 Giorgos Korfiatis
                   "reject", "remove"
883 47bb45c0 Giorgos Korfiatis
        reason  -- reason of performing the action
884 47bb45c0 Giorgos Korfiatis

885 47bb45c0 Giorgos Korfiatis
        In case of success, return nothing.
886 47bb45c0 Giorgos Korfiatis
        """
887 2c9c147e Ilias Tsitsimpis
        path = join_urls(self.api_memberships, str(memb_id))
888 47bb45c0 Giorgos Korfiatis
        path = join_urls(path, "action")
889 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
890 47bb45c0 Giorgos Korfiatis
        req_body = parse_request({action: reason}, self.logger)
891 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(path, headers=req_headers,
892 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
893 47bb45c0 Giorgos Korfiatis
894 47bb45c0 Giorgos Korfiatis
    # --------------------------------
895 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``
896 2c9c147e Ilias Tsitsimpis
    def join_project(self, project_id):
897 47bb45c0 Giorgos Korfiatis
        """Join a project
898 47bb45c0 Giorgos Korfiatis

899 47bb45c0 Giorgos Korfiatis
        Arguments:
900 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
901 47bb45c0 Giorgos Korfiatis

902 47bb45c0 Giorgos Korfiatis
        In case of success, return membership identifier.
903 47bb45c0 Giorgos Korfiatis
        """
904 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
905 47bb45c0 Giorgos Korfiatis
        body = {"join": {"project": project_id}}
906 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger)
907 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships, headers=req_headers,
908 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
909 47bb45c0 Giorgos Korfiatis
910 47bb45c0 Giorgos Korfiatis
    # --------------------------------
911 47bb45c0 Giorgos Korfiatis
    # do a POST to ``API_MEMBERSHIPS``
912 2c9c147e Ilias Tsitsimpis
    def enroll_member(self, project_id, email):
913 47bb45c0 Giorgos Korfiatis
        """Enroll a user in a project
914 47bb45c0 Giorgos Korfiatis

915 47bb45c0 Giorgos Korfiatis
        Arguments:
916 47bb45c0 Giorgos Korfiatis
        project_id -- project identifier
917 47bb45c0 Giorgos Korfiatis
        email      -- user identified by email
918 47bb45c0 Giorgos Korfiatis

919 47bb45c0 Giorgos Korfiatis
        In case of success, return membership identifier.
920 47bb45c0 Giorgos Korfiatis
        """
921 47bb45c0 Giorgos Korfiatis
        req_headers = {'content-type': 'application/json'}
922 47bb45c0 Giorgos Korfiatis
        body = {"enroll": {"project": project_id, "user": email}}
923 47bb45c0 Giorgos Korfiatis
        req_body = parse_request(body, self.logger)
924 2c9c147e Ilias Tsitsimpis
        return self._call_astakos(self.api_memberships, headers=req_headers,
925 2c9c147e Ilias Tsitsimpis
                                  body=req_body, method="POST")
926 2c9c147e Ilias Tsitsimpis
927 d2104099 Sofia Papagiannaki
    # --------------------------------
928 d2104099 Sofia Papagiannaki
    # do a POST to ``API_OA2_TOKEN``
929 d2104099 Sofia Papagiannaki
    def get_token(self, grant_type, client_id, client_secret, **body_params):
930 75144caa Sofia Papagiannaki
        headers = {'content-type': 'application/x-www-form-urlencoded',
931 d2104099 Sofia Papagiannaki
                   'Authorization': 'Basic %s' % b64encode('%s:%s' %
932 d2104099 Sofia Papagiannaki
                                                           (client_id,
933 d2104099 Sofia Papagiannaki
                                                            client_secret))}
934 d2104099 Sofia Papagiannaki
        body_params['grant_type'] = grant_type
935 d2104099 Sofia Papagiannaki
        body = urllib.urlencode(body_params)
936 d2104099 Sofia Papagiannaki
        return self._call_astakos(self.api_oa2_token, headers=headers,
937 d2104099 Sofia Papagiannaki
                                  body=body, method="POST")
938 d2104099 Sofia Papagiannaki
939 2c9c147e Ilias Tsitsimpis
940 2c9c147e Ilias Tsitsimpis
# --------------------------------------------------------------------
941 2c9c147e Ilias Tsitsimpis
# parse endpoints
942 2c9c147e Ilias Tsitsimpis
def parse_endpoints(endpoints, ep_name=None, ep_type=None,
943 2c9c147e Ilias Tsitsimpis
                    ep_region=None, ep_version_id=None):
944 2c9c147e Ilias Tsitsimpis
    """Parse endpoints server response and extract the ones needed
945 2c9c147e Ilias Tsitsimpis

946 2c9c147e Ilias Tsitsimpis
    Keyword arguments:
947 2c9c147e Ilias Tsitsimpis
    endpoints     -- the endpoints (json response from get_endpoints)
948 2c9c147e Ilias Tsitsimpis
    ep_name       -- return only endpoints with this name (optional)
949 2c9c147e Ilias Tsitsimpis
    ep_type       -- return only endpoints with this type (optional)
950 2c9c147e Ilias Tsitsimpis
    ep_region     -- return only endpoints with this region (optional)
951 2c9c147e Ilias Tsitsimpis
    ep_version_id -- return only endpoints with this versionId (optional)
952 2c9c147e Ilias Tsitsimpis

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

957 2c9c147e Ilias Tsitsimpis
    """
958 2c9c147e Ilias Tsitsimpis
    try:
959 2c9c147e Ilias Tsitsimpis
        catalog = endpoints['access']['serviceCatalog']
960 2c9c147e Ilias Tsitsimpis
        if ep_name is not None:
961 2c9c147e Ilias Tsitsimpis
            catalog = \
962 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['name'] == ep_name]
963 2c9c147e Ilias Tsitsimpis
        if ep_type is not None:
964 2c9c147e Ilias Tsitsimpis
            catalog = \
965 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['type'] == ep_type]
966 2c9c147e Ilias Tsitsimpis
        if ep_region is not None:
967 2c9c147e Ilias Tsitsimpis
            for c in catalog:
968 2c9c147e Ilias Tsitsimpis
                c['endpoints'] = [e for e in c['endpoints']
969 2c9c147e Ilias Tsitsimpis
                                  if e['region'] == ep_region]
970 2c9c147e Ilias Tsitsimpis
            # Remove catalog entries with no endpoints
971 2c9c147e Ilias Tsitsimpis
            catalog = \
972 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['endpoints']]
973 2c9c147e Ilias Tsitsimpis
        if ep_version_id is not None:
974 2c9c147e Ilias Tsitsimpis
            for c in catalog:
975 2c9c147e Ilias Tsitsimpis
                c['endpoints'] = [e for e in c['endpoints']
976 2c9c147e Ilias Tsitsimpis
                                  if e['versionId'] == ep_version_id]
977 2c9c147e Ilias Tsitsimpis
            # Remove catalog entries with no endpoints
978 2c9c147e Ilias Tsitsimpis
            catalog = \
979 2c9c147e Ilias Tsitsimpis
                [c for c in catalog if c['endpoints']]
980 2c9c147e Ilias Tsitsimpis
981 2c9c147e Ilias Tsitsimpis
        if not catalog:
982 2c9c147e Ilias Tsitsimpis
            raise NoEndpoints(ep_name, ep_type,
983 2c9c147e Ilias Tsitsimpis
                              ep_region, ep_version_id)
984 2c9c147e Ilias Tsitsimpis
        else:
985 2c9c147e Ilias Tsitsimpis
            return catalog
986 2c9c147e Ilias Tsitsimpis
    except KeyError:
987 2c9c147e Ilias Tsitsimpis
        raise NoEndpoints()
988 2c9c147e Ilias Tsitsimpis
989 f54cf5e4 Ilias Tsitsimpis
990 f54cf5e4 Ilias Tsitsimpis
# --------------------------------------------------------------------
991 cbc0b438 Ilias Tsitsimpis
# Private functions
992 45c0bcf8 Giorgos Korfiatis
# We want _do_request to be a distinct function
993 f93cc364 Ilias Tsitsimpis
# so that we can replace it during unit tests.
994 794c94e6 Ilias Tsitsimpis
def _do_request(conn, method, url, **kwargs):
995 f8388a90 Ilias Tsitsimpis
    """The actual request. This function can easily be mocked"""
996 f8388a90 Ilias Tsitsimpis
    conn.request(method, url, **kwargs)
997 f8388a90 Ilias Tsitsimpis
    response = conn.getresponse()
998 f8388a90 Ilias Tsitsimpis
    length = response.getheader('content-length', None)
999 f8388a90 Ilias Tsitsimpis
    data = response.read(length)
1000 f8388a90 Ilias Tsitsimpis
    status = int(response.status)
1001 21190887 Ilias Tsitsimpis
    message = response.reason
1002 21190887 Ilias Tsitsimpis
    return (message, data, status)