Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / astakos / __init__.py @ cabc72ae

History | View | Annotate | Download (7.3 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 db93db3e Stavros Sachtouris
from astakosclient import AstakosClient as SynnefoAstakosClient
36 9d3cd179 Stavros Sachtouris
37 9d3cd179 Stavros Sachtouris
from kamaki.clients import Client, ClientError
38 528550d9 Stavros Sachtouris
39 528550d9 Stavros Sachtouris
40 43ca98ee Giorgos Verigakis
class AstakosClient(Client):
41 cabc72ae Stavros Sachtouris
    """Synnefo Astakos cached client wraper"""
42 44b8928d Giorgos Verigakis
43 528550d9 Stavros Sachtouris
    def __init__(self, base_url, token=None):
44 33dc6317 Stavros Sachtouris
        super(AstakosClient, self).__init__(base_url, token)
45 cabc72ae Stavros Sachtouris
        self._astakos = dict()
46 cabc72ae Stavros Sachtouris
        self._uuids = dict()
47 cabc72ae Stavros Sachtouris
        self._cache = dict()
48 cabc72ae Stavros Sachtouris
        self._uuids2usernames = dict()
49 cabc72ae Stavros Sachtouris
        self._usernames2uuids = dict()
50 cabc72ae Stavros Sachtouris
51 cabc72ae Stavros Sachtouris
    def _resolve_token(self, token):
52 cabc72ae Stavros Sachtouris
        """
53 cabc72ae Stavros Sachtouris
        :returns: (str) a single token
54 cabc72ae Stavros Sachtouris

55 cabc72ae Stavros Sachtouris
        :raises AssertionError: if no token exists (either param or member)
56 cabc72ae Stavros Sachtouris
        """
57 cabc72ae Stavros Sachtouris
        token = token or self.token or self.tokenlist[0]
58 cabc72ae Stavros Sachtouris
        assert token, 'No token provided'
59 cabc72ae Stavros Sachtouris
        return token[0] if (
60 cabc72ae Stavros Sachtouris
            isinstance(token, list) or isinstance(token, tuple)) else token
61 cabc72ae Stavros Sachtouris
62 0238c167 Stavros Sachtouris
    def authenticate(self, token=None):
63 409371de Stavros Sachtouris
        """Get authentication information and store it in this client
64 409371de Stavros Sachtouris
        As long as the AstakosClient instance is alive, the latest
65 409371de Stavros Sachtouris
        authentication information for this token will be available
66 409371de Stavros Sachtouris

67 0d79eb23 Stavros Sachtouris
        :param token: (str) custom token to authenticate
68 0d79eb23 Stavros Sachtouris
        """
69 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
70 cabc72ae Stavros Sachtouris
        astakos = SynnefoAstakosClient(
71 cabc72ae Stavros Sachtouris
            token, self.base_url, logger=getLogger('_my_.astakosclient'))
72 cabc72ae Stavros Sachtouris
        r = astakos.get_endpoints()
73 b44a5a37 Stavros Sachtouris
        uuid = r['access']['user']['id']
74 db93db3e Stavros Sachtouris
        self._uuids[token] = uuid
75 b44a5a37 Stavros Sachtouris
        self._cache[uuid] = r
76 cabc72ae Stavros Sachtouris
        self._astakos[uuid] = astakos
77 cabc72ae Stavros Sachtouris
        self._uuids2usernames[token] = dict()
78 cabc72ae Stavros Sachtouris
        self._usernames2uuids[token] = dict()
79 b44a5a37 Stavros Sachtouris
80 b44a5a37 Stavros Sachtouris
    def get_token(self, uuid):
81 b44a5a37 Stavros Sachtouris
        return self._cache[uuid]['access']['token']['id']
82 5207c784 Stavros Sachtouris
83 cabc72ae Stavros Sachtouris
    def _validate_token(self, token):
84 cabc72ae Stavros Sachtouris
        if (token not in self._uuids) or (
85 cabc72ae Stavros Sachtouris
                self.get_token(self._uuids[token]) != token):
86 cabc72ae Stavros Sachtouris
            self._uuids.pop(token, None)
87 cabc72ae Stavros Sachtouris
            self.authenticate(token)
88 cabc72ae Stavros Sachtouris
89 528550d9 Stavros Sachtouris
    def get_services(self, token=None):
90 528550d9 Stavros Sachtouris
        """
91 528550d9 Stavros Sachtouris
        :returns: (list) [{name:..., type:..., endpoints:[...]}, ...]
92 528550d9 Stavros Sachtouris
        """
93 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
94 cabc72ae Stavros Sachtouris
        self._validate_token(token)
95 cabc72ae Stavros Sachtouris
        r = self._cache[self._uuids[token]]
96 3950a864 Stavros Sachtouris
        return r['access']['serviceCatalog']
97 528550d9 Stavros Sachtouris
98 528550d9 Stavros Sachtouris
    def get_service_details(self, service_type, token=None):
99 528550d9 Stavros Sachtouris
        """
100 528550d9 Stavros Sachtouris
        :param service_type: (str) compute, object-store, image, account, etc.
101 528550d9 Stavros Sachtouris

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

104 528550d9 Stavros Sachtouris
        :raises ClientError: (600) if service_type not in service catalog
105 528550d9 Stavros Sachtouris
        """
106 528550d9 Stavros Sachtouris
        services = self.get_services(token)
107 528550d9 Stavros Sachtouris
        for service in services:
108 528550d9 Stavros Sachtouris
            try:
109 528550d9 Stavros Sachtouris
                if service['type'].lower() == service_type.lower():
110 528550d9 Stavros Sachtouris
                    return service
111 528550d9 Stavros Sachtouris
            except KeyError:
112 528550d9 Stavros Sachtouris
                self.log.warning('Misformated service %s' % service)
113 528550d9 Stavros Sachtouris
        raise ClientError(
114 528550d9 Stavros Sachtouris
            'Service type "%s" not in service catalog' % service_type, 600)
115 528550d9 Stavros Sachtouris
116 528550d9 Stavros Sachtouris
    def get_service_endpoints(self, service_type, version=None, token=None):
117 528550d9 Stavros Sachtouris
        """
118 528550d9 Stavros Sachtouris
        :param service_type: (str) can be compute, object-store, etc.
119 528550d9 Stavros Sachtouris

120 528550d9 Stavros Sachtouris
        :param version: (str) the version id of the service
121 528550d9 Stavros Sachtouris

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

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

126 528550d9 Stavros Sachtouris
        :raises ClientError: (601) if #matching endpoints != 1
127 528550d9 Stavros Sachtouris
        """
128 528550d9 Stavros Sachtouris
        service = self.get_service_details(service_type, token)
129 528550d9 Stavros Sachtouris
        matches = []
130 528550d9 Stavros Sachtouris
        for endpoint in service['endpoints']:
131 528550d9 Stavros Sachtouris
            if (not version) or (
132 e7884f25 Stavros Sachtouris
                    endpoint['versionId'].lower() == version.lower()):
133 528550d9 Stavros Sachtouris
                matches.append(endpoint)
134 528550d9 Stavros Sachtouris
        if len(matches) != 1:
135 528550d9 Stavros Sachtouris
            raise ClientError(
136 528550d9 Stavros Sachtouris
                '%s endpoints match type %s %s' % (
137 528550d9 Stavros Sachtouris
                    len(matches), service_type,
138 e7884f25 Stavros Sachtouris
                    ('and versionId %s' % version) if version else ''),
139 528550d9 Stavros Sachtouris
                601)
140 528550d9 Stavros Sachtouris
        return matches[0]
141 528550d9 Stavros Sachtouris
142 528550d9 Stavros Sachtouris
    def list_users(self):
143 528550d9 Stavros Sachtouris
        """list cached users information"""
144 9a8861d1 Stavros Sachtouris
        if not self._cache:
145 9a8861d1 Stavros Sachtouris
            self.authenticate()
146 2182231b Stavros Sachtouris
        r = []
147 2182231b Stavros Sachtouris
        for k, v in self._cache.items():
148 3950a864 Stavros Sachtouris
            r.append(dict(v['access']['user']))
149 b44a5a37 Stavros Sachtouris
            r[-1].update(dict(auth_token=self.get_token(k)))
150 2182231b Stavros Sachtouris
        return r
151 76d3b2d7 Stavros Sachtouris
152 528550d9 Stavros Sachtouris
    def user_info(self, token=None):
153 2182231b Stavros Sachtouris
        """Get (cached) user information"""
154 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
155 cabc72ae Stavros Sachtouris
        self._validate_token(token)
156 cabc72ae Stavros Sachtouris
        r = self._cache[self._uuids[token]]
157 3950a864 Stavros Sachtouris
        return r['access']['user']
158 76d3b2d7 Stavros Sachtouris
159 5207c784 Stavros Sachtouris
    def term(self, key, token=None):
160 5207c784 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
161 f724cd35 Stavros Sachtouris
        return self.user_term(key, token)
162 f724cd35 Stavros Sachtouris
163 f724cd35 Stavros Sachtouris
    def user_term(self, key, token=None):
164 f724cd35 Stavros Sachtouris
        """Get (cached) term, from user credentials"""
165 528550d9 Stavros Sachtouris
        return self.user_info(token).get(key, None)
166 9d3cd179 Stavros Sachtouris
167 cabc72ae Stavros Sachtouris
    def post_user_catalogs(self, uuids=None, displaynames=None, token=None):
168 9d3cd179 Stavros Sachtouris
        """POST base_url/user_catalogs
169 9d3cd179 Stavros Sachtouris

170 9d3cd179 Stavros Sachtouris
        :param uuids: (list or tuple) user uuids
171 9d3cd179 Stavros Sachtouris

172 95641ecc Stavros Sachtouris
        :param displaynames: (list or tuple) usernames (mut. excl. to uuids)
173 95641ecc Stavros Sachtouris

174 95641ecc Stavros Sachtouris
        :returns: (dict) {uuid1: name1, uuid2: name2, ...} or oposite
175 9d3cd179 Stavros Sachtouris
        """
176 cabc72ae Stavros Sachtouris
        return self.uuids2usernames(uuids, token) if (
177 cabc72ae Stavros Sachtouris
            uuids) else self.usernnames2uuids(displaynames, token)
178 cabc72ae Stavros Sachtouris
179 cabc72ae Stavros Sachtouris
    def uuids2usernames(self, uuids, token=None):
180 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
181 cabc72ae Stavros Sachtouris
        self._validate_token(token)
182 cabc72ae Stavros Sachtouris
        astakos = self._astakos[self._uuids[token]]
183 cabc72ae Stavros Sachtouris
        if set(uuids).difference(self._uuids2usernames[token]):
184 cabc72ae Stavros Sachtouris
            self._uuids2usernames[token].update(astakos.get_usernames(uuids))
185 cabc72ae Stavros Sachtouris
        return self._uuids2usernames[token]
186 cabc72ae Stavros Sachtouris
187 cabc72ae Stavros Sachtouris
    def usernames2uuids(self, usernames, token=None):
188 cabc72ae Stavros Sachtouris
        token = self._resolve_token(token)
189 cabc72ae Stavros Sachtouris
        self._validate_token(token)
190 cabc72ae Stavros Sachtouris
        astakos = self._astakos[self._uuids[token]]
191 cabc72ae Stavros Sachtouris
        if set(usernames).difference(self._usernames2uuids[token]):
192 cabc72ae Stavros Sachtouris
            self._usernames2uuids[token].update(astakos.get_uuids(usernames))
193 cabc72ae Stavros Sachtouris
        return self._usernames2uuids