Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / astakos / __init__.py @ 9d3cd179

History | View | Annotate | Download (6.1 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2 43ca98ee Giorgos Verigakis
#
3 43ca98ee Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 43ca98ee Giorgos Verigakis
# without modification, are permitted provided that the following
5 43ca98ee Giorgos Verigakis
# conditions are met:
6 43ca98ee Giorgos Verigakis
#
7 43ca98ee Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 43ca98ee Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 43ca98ee Giorgos Verigakis
#      disclaimer.
10 43ca98ee Giorgos Verigakis
#
11 43ca98ee Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 43ca98ee Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 43ca98ee Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 43ca98ee Giorgos Verigakis
#      provided with the distribution.
15 43ca98ee Giorgos Verigakis
#
16 43ca98ee Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 43ca98ee Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 43ca98ee Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 43ca98ee Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 43ca98ee Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 43ca98ee Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 43ca98ee Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 43ca98ee Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 43ca98ee Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 43ca98ee Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 43ca98ee Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 43ca98ee Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 43ca98ee Giorgos Verigakis
#
29 43ca98ee Giorgos Verigakis
# The views and conclusions contained in the software and
30 43ca98ee Giorgos Verigakis
# documentation are those of the authors and should not be
31 43ca98ee Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 43ca98ee Giorgos Verigakis
# or implied, of GRNET S.A.
33 43ca98ee Giorgos Verigakis
34 528550d9 Stavros Sachtouris
from logging import getLogger
35 9d3cd179 Stavros Sachtouris
from json import dumps
36 9d3cd179 Stavros Sachtouris
37 9d3cd179 Stavros Sachtouris
from kamaki.clients import Client, ClientError
38 9d3cd179 Stavros Sachtouris
from kamaki.clients.utils import path4url
39 528550d9 Stavros Sachtouris
40 528550d9 Stavros Sachtouris
41 43ca98ee Giorgos Verigakis
class AstakosClient(Client):
42 76e7661e Stavros Sachtouris
    """Synnefo Astakos API client"""
43 44b8928d Giorgos Verigakis
44 528550d9 Stavros Sachtouris
    def __init__(self, base_url, token=None):
45 33dc6317 Stavros Sachtouris
        super(AstakosClient, self).__init__(base_url, token)
46 9d74de5d Stavros Sachtouris
        self._cache = {}
47 b44a5a37 Stavros Sachtouris
        self._uuids = {}
48 528550d9 Stavros Sachtouris
        self.log = getLogger('__name__')
49 2f749e6e Stavros Sachtouris
50 0238c167 Stavros Sachtouris
    def authenticate(self, token=None):
51 409371de Stavros Sachtouris
        """Get authentication information and store it in this client
52 409371de Stavros Sachtouris
        As long as the AstakosClient instance is alive, the latest
53 409371de Stavros Sachtouris
        authentication information for this token will be available
54 409371de Stavros Sachtouris

55 0d79eb23 Stavros Sachtouris
        :param token: (str) custom token to authenticate
56 0d79eb23 Stavros Sachtouris

57 0d79eb23 Stavros Sachtouris
        :returns: (dict) authentication information
58 0d79eb23 Stavros Sachtouris
        """
59 3f61753d Stavros Sachtouris
        self.token = token or self.token
60 8cec3671 Stavros Sachtouris
        body = dict(auth=dict(token=dict(id=self.token)))
61 b44a5a37 Stavros Sachtouris
        r = self.post('/tokens', json=body).json
62 b44a5a37 Stavros Sachtouris
        uuid = r['access']['user']['id']
63 b44a5a37 Stavros Sachtouris
        self._uuids[self.token] = uuid
64 b44a5a37 Stavros Sachtouris
        self._cache[uuid] = r
65 b44a5a37 Stavros Sachtouris
        return self._cache[uuid]
66 b44a5a37 Stavros Sachtouris
67 b44a5a37 Stavros Sachtouris
    def get_token(self, uuid):
68 b44a5a37 Stavros Sachtouris
        return self._cache[uuid]['access']['token']['id']
69 5207c784 Stavros Sachtouris
70 528550d9 Stavros Sachtouris
    def get_services(self, token=None):
71 528550d9 Stavros Sachtouris
        """
72 528550d9 Stavros Sachtouris
        :returns: (list) [{name:..., type:..., endpoints:[...]}, ...]
73 528550d9 Stavros Sachtouris
        """
74 528550d9 Stavros Sachtouris
        token_bu = self.token or token
75 528550d9 Stavros Sachtouris
        token = token or self.token
76 528550d9 Stavros Sachtouris
        try:
77 b44a5a37 Stavros Sachtouris
            r = self._cache[self._uuids[token]]
78 528550d9 Stavros Sachtouris
        except KeyError:
79 528550d9 Stavros Sachtouris
            r = self.authenticate(token)
80 528550d9 Stavros Sachtouris
        finally:
81 528550d9 Stavros Sachtouris
            self.token = token_bu
82 3950a864 Stavros Sachtouris
        return r['access']['serviceCatalog']
83 528550d9 Stavros Sachtouris
84 528550d9 Stavros Sachtouris
    def get_service_details(self, service_type, token=None):
85 528550d9 Stavros Sachtouris
        """
86 528550d9 Stavros Sachtouris
        :param service_type: (str) compute, object-store, image, account, etc.
87 528550d9 Stavros Sachtouris

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

90 528550d9 Stavros Sachtouris
        :raises ClientError: (600) if service_type not in service catalog
91 528550d9 Stavros Sachtouris
        """
92 528550d9 Stavros Sachtouris
        services = self.get_services(token)
93 528550d9 Stavros Sachtouris
        for service in services:
94 528550d9 Stavros Sachtouris
            try:
95 528550d9 Stavros Sachtouris
                if service['type'].lower() == service_type.lower():
96 528550d9 Stavros Sachtouris
                    return service
97 528550d9 Stavros Sachtouris
            except KeyError:
98 528550d9 Stavros Sachtouris
                self.log.warning('Misformated service %s' % service)
99 528550d9 Stavros Sachtouris
        raise ClientError(
100 528550d9 Stavros Sachtouris
            'Service type "%s" not in service catalog' % service_type, 600)
101 528550d9 Stavros Sachtouris
102 528550d9 Stavros Sachtouris
    def get_service_endpoints(self, service_type, version=None, token=None):
103 528550d9 Stavros Sachtouris
        """
104 528550d9 Stavros Sachtouris
        :param service_type: (str) can be compute, object-store, etc.
105 528550d9 Stavros Sachtouris

106 528550d9 Stavros Sachtouris
        :param version: (str) the version id of the service
107 528550d9 Stavros Sachtouris

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

110 528550d9 Stavros Sachtouris
        :raises ClientError: (600) if service_type not in service catalog
111 528550d9 Stavros Sachtouris

112 528550d9 Stavros Sachtouris
        :raises ClientError: (601) if #matching endpoints != 1
113 528550d9 Stavros Sachtouris
        """
114 528550d9 Stavros Sachtouris
        service = self.get_service_details(service_type, token)
115 528550d9 Stavros Sachtouris
        matches = []
116 528550d9 Stavros Sachtouris
        for endpoint in service['endpoints']:
117 528550d9 Stavros Sachtouris
            if (not version) or (
118 e7884f25 Stavros Sachtouris
                    endpoint['versionId'].lower() == version.lower()):
119 528550d9 Stavros Sachtouris
                matches.append(endpoint)
120 528550d9 Stavros Sachtouris
        if len(matches) != 1:
121 528550d9 Stavros Sachtouris
            raise ClientError(
122 528550d9 Stavros Sachtouris
                '%s endpoints match type %s %s' % (
123 528550d9 Stavros Sachtouris
                    len(matches), service_type,
124 e7884f25 Stavros Sachtouris
                    ('and versionId %s' % version) if version else ''),
125 528550d9 Stavros Sachtouris
                601)
126 528550d9 Stavros Sachtouris
        return matches[0]
127 528550d9 Stavros Sachtouris
128 528550d9 Stavros Sachtouris
    def list_users(self):
129 528550d9 Stavros Sachtouris
        """list cached users information"""
130 9a8861d1 Stavros Sachtouris
        if not self._cache:
131 9a8861d1 Stavros Sachtouris
            self.authenticate()
132 2182231b Stavros Sachtouris
        r = []
133 2182231b Stavros Sachtouris
        for k, v in self._cache.items():
134 3950a864 Stavros Sachtouris
            r.append(dict(v['access']['user']))
135 b44a5a37 Stavros Sachtouris
            r[-1].update(dict(auth_token=self.get_token(k)))
136 2182231b Stavros Sachtouris
        return r
137 76d3b2d7 Stavros Sachtouris
138 528550d9 Stavros Sachtouris
    def user_info(self, token=None):
139 2182231b Stavros Sachtouris
        """Get (cached) user information"""
140 528550d9 Stavros Sachtouris
        token_bu = self.token or token
141 3f61753d Stavros Sachtouris
        token = token or self.token
142 3f61753d Stavros Sachtouris
        try:
143 b44a5a37 Stavros Sachtouris
            r = self._cache[self._uuids[token]]
144 3f61753d Stavros Sachtouris
        except KeyError:
145 409371de Stavros Sachtouris
            r = self.authenticate(token)
146 528550d9 Stavros Sachtouris
        finally:
147 528550d9 Stavros Sachtouris
            self.token = token_bu
148 3950a864 Stavros Sachtouris
        return r['access']['user']
149 76d3b2d7 Stavros Sachtouris
150 5207c784 Stavros Sachtouris
    def term(self, key, token=None):
151 5207c784 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
152 f724cd35 Stavros Sachtouris
        return self.user_term(key, token)
153 f724cd35 Stavros Sachtouris
154 f724cd35 Stavros Sachtouris
    def user_term(self, key, token=None):
155 f724cd35 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
156 528550d9 Stavros Sachtouris
        return self.user_info(token).get(key, None)
157 9d3cd179 Stavros Sachtouris
158 9d3cd179 Stavros Sachtouris
    def post_user_catalogs(self, uuids):
159 9d3cd179 Stavros Sachtouris
        """POST base_url/user_catalogs
160 9d3cd179 Stavros Sachtouris

161 9d3cd179 Stavros Sachtouris
        :param uuids: (list or tuple) user uuids
162 9d3cd179 Stavros Sachtouris

163 9d3cd179 Stavros Sachtouris
        :returns: (dict) {uuid1: name1, uuid2: name2, ...}
164 9d3cd179 Stavros Sachtouris
        """
165 9d3cd179 Stavros Sachtouris
        account_url = self.get_service_endpoints('account')['publicURL']
166 9d3cd179 Stavros Sachtouris
        account = AstakosClient(account_url, self.token)
167 9d3cd179 Stavros Sachtouris
        json_data = dict(uuids=uuids)
168 9d3cd179 Stavros Sachtouris
        return account.post('user_catalogs', json=json_data)