Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / __init__.py @ dba6ec94

History | View | Annotate | Download (4.7 kB)

1 dba6ec94 Giorgos Verigakis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 a1c50326 Giorgos Verigakis
#
3 a1c50326 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 a1c50326 Giorgos Verigakis
# without modification, are permitted provided that the following
5 a1c50326 Giorgos Verigakis
# conditions are met:
6 a1c50326 Giorgos Verigakis
#
7 a1c50326 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 a1c50326 Giorgos Verigakis
#      disclaimer.
10 a1c50326 Giorgos Verigakis
#
11 a1c50326 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 a1c50326 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 a1c50326 Giorgos Verigakis
#      provided with the distribution.
15 a1c50326 Giorgos Verigakis
#
16 a1c50326 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a1c50326 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a1c50326 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a1c50326 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a1c50326 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a1c50326 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a1c50326 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a1c50326 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a1c50326 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a1c50326 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a1c50326 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a1c50326 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 a1c50326 Giorgos Verigakis
#
29 a1c50326 Giorgos Verigakis
# The views and conclusions contained in the software and
30 a1c50326 Giorgos Verigakis
# documentation are those of the authors and should not be
31 a1c50326 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 a1c50326 Giorgos Verigakis
# or implied, of GRNET S.A.
33 a1c50326 Giorgos Verigakis
34 df79206f Giorgos Verigakis
import json
35 df79206f Giorgos Verigakis
import logging
36 df79206f Giorgos Verigakis
37 df79206f Giorgos Verigakis
import requests
38 df79206f Giorgos Verigakis
39 df79206f Giorgos Verigakis
from requests.auth import AuthBase
40 df79206f Giorgos Verigakis
41 df79206f Giorgos Verigakis
42 df79206f Giorgos Verigakis
sendlog = logging.getLogger('clients.send')
43 df79206f Giorgos Verigakis
recvlog = logging.getLogger('clients.recv')
44 df79206f Giorgos Verigakis
45 df79206f Giorgos Verigakis
46 df79206f Giorgos Verigakis
# Add a convenience json property to the responses
47 df79206f Giorgos Verigakis
def _json(self):
48 df79206f Giorgos Verigakis
    try:
49 a591a7b4 Giorgos Verigakis
        return json.loads(self.content) if self.content else {}
50 df79206f Giorgos Verigakis
    except ValueError:
51 df79206f Giorgos Verigakis
        raise ClientError("Invalid JSON reply", self.status_code)
52 df79206f Giorgos Verigakis
requests.Response.json = property(_json)
53 df79206f Giorgos Verigakis
54 df79206f Giorgos Verigakis
# Add a convenience status property to the responses
55 df79206f Giorgos Verigakis
def _status(self):
56 df79206f Giorgos Verigakis
    return requests.status_codes._codes[self.status_code][0].upper()
57 df79206f Giorgos Verigakis
requests.Response.status = property(_status)
58 df79206f Giorgos Verigakis
59 df79206f Giorgos Verigakis
60 df79206f Giorgos Verigakis
class XAuthTokenAuth(AuthBase):
61 df79206f Giorgos Verigakis
    def __init__(self, token):
62 df79206f Giorgos Verigakis
        self.token = token
63 df79206f Giorgos Verigakis
    
64 df79206f Giorgos Verigakis
    def __call__(self, r):
65 df79206f Giorgos Verigakis
        r.headers['X-Auth-Token'] = self.token
66 df79206f Giorgos Verigakis
        return r
67 df79206f Giorgos Verigakis
68 df79206f Giorgos Verigakis
69 a1c50326 Giorgos Verigakis
class ClientError(Exception):
70 a1c50326 Giorgos Verigakis
    def __init__(self, message, status=0, details=''):
71 a1c50326 Giorgos Verigakis
        self.message = message
72 a1c50326 Giorgos Verigakis
        self.status = status
73 a1c50326 Giorgos Verigakis
        self.details = details
74 a1c50326 Giorgos Verigakis
75 a1c50326 Giorgos Verigakis
76 df79206f Giorgos Verigakis
class Client(object):
77 dba6ec94 Giorgos Verigakis
    def __init__(self, base_url, token):
78 df79206f Giorgos Verigakis
        self.base_url = base_url
79 df79206f Giorgos Verigakis
        self.auth = XAuthTokenAuth(token)
80 df79206f Giorgos Verigakis
    
81 dba6ec94 Giorgos Verigakis
    def raise_for_status(self, r):        
82 dba6ec94 Giorgos Verigakis
        message = "%d %s" % (r.status_code, r.status)
83 dba6ec94 Giorgos Verigakis
        details = r.text
84 df79206f Giorgos Verigakis
        raise ClientError(message, r.status_code, details)
85 df79206f Giorgos Verigakis
86 df79206f Giorgos Verigakis
    def request(self, method, path, **kwargs):
87 df79206f Giorgos Verigakis
        raw = kwargs.pop('raw', False)
88 df79206f Giorgos Verigakis
        success = kwargs.pop('success', 200)
89 df79206f Giorgos Verigakis
        if 'json' in kwargs:
90 df79206f Giorgos Verigakis
            data = json.dumps(kwargs.pop('json'))
91 df79206f Giorgos Verigakis
            kwargs['data'] = data
92 df79206f Giorgos Verigakis
            headers = kwargs.setdefault('headers', {})
93 df79206f Giorgos Verigakis
            headers['content-type'] = 'application/json'
94 df79206f Giorgos Verigakis
95 df79206f Giorgos Verigakis
        url = self.base_url + path
96 df79206f Giorgos Verigakis
        kwargs.setdefault('auth', self.auth)
97 df79206f Giorgos Verigakis
        r = requests.request(method, url, **kwargs)
98 df79206f Giorgos Verigakis
        
99 df79206f Giorgos Verigakis
        req = r.request
100 df79206f Giorgos Verigakis
        sendlog.info('%s %s', req.method, req.url)
101 df79206f Giorgos Verigakis
        for key, val in req.headers.items():
102 df79206f Giorgos Verigakis
            sendlog.info('%s: %s', key, val)
103 df79206f Giorgos Verigakis
        sendlog.info('')
104 df79206f Giorgos Verigakis
        if req.data:
105 df79206f Giorgos Verigakis
            sendlog.info('%s', req.data)
106 df79206f Giorgos Verigakis
        
107 df79206f Giorgos Verigakis
        recvlog.info('%d %s', r.status_code, r.status)
108 df79206f Giorgos Verigakis
        for key, val in r.headers.items():
109 df79206f Giorgos Verigakis
            recvlog.info('%s: %s', key, val)
110 df79206f Giorgos Verigakis
        recvlog.info('')
111 df79206f Giorgos Verigakis
        if not raw and r.text:
112 df79206f Giorgos Verigakis
            recvlog.debug(r.text)
113 df79206f Giorgos Verigakis
        
114 df79206f Giorgos Verigakis
        if success is not None:
115 df79206f Giorgos Verigakis
            # Success can either be an in or a collection
116 df79206f Giorgos Verigakis
            success = (success,) if isinstance(success, int) else success
117 df79206f Giorgos Verigakis
            if r.status_code not in success:
118 df79206f Giorgos Verigakis
                self.raise_for_status(r)
119 df79206f Giorgos Verigakis
120 a1c50326 Giorgos Verigakis
        return r
121 a1c50326 Giorgos Verigakis
122 df79206f Giorgos Verigakis
    def delete(self, path, **kwargs):
123 df79206f Giorgos Verigakis
        return self.request('delete', path, **kwargs)
124 df79206f Giorgos Verigakis
125 df79206f Giorgos Verigakis
    def get(self, path, **kwargs):
126 df79206f Giorgos Verigakis
        return self.request('get', path, **kwargs)
127 df79206f Giorgos Verigakis
128 df79206f Giorgos Verigakis
    def head(self, path, **kwargs):
129 df79206f Giorgos Verigakis
        return self.request('head', path, **kwargs)
130 df79206f Giorgos Verigakis
131 df79206f Giorgos Verigakis
    def post(self, path, **kwargs):
132 df79206f Giorgos Verigakis
        return self.request('post', path, **kwargs)
133 df79206f Giorgos Verigakis
134 df79206f Giorgos Verigakis
    def put(self, path, **kwargs):
135 df79206f Giorgos Verigakis
        return self.request('put', path, **kwargs)
136 df79206f Giorgos Verigakis
137 a1c50326 Giorgos Verigakis
138 df79206f Giorgos Verigakis
from .compute import ComputeClient as compute
139 df79206f Giorgos Verigakis
from .image import ImageClient as image
140 df79206f Giorgos Verigakis
from .storage import StorageClient as storage
141 df79206f Giorgos Verigakis
from .cyclades import CycladesClient as cyclades
142 df79206f Giorgos Verigakis
from .pithos import PithosClient as pithos
143 dba6ec94 Giorgos Verigakis
from .astakos import AstakosClient as astakos