Revision cd75ff39 kamaki/clients/image.py

b/kamaki/clients/image.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
"""
35
    OpenStack Image Service API 1.0 client
36
"""
37 34

  
38
from urllib import quote
35
from . import Client, ClientError
39 36

  
40
from . import ClientError
41
from .http import HTTPClient
42 37

  
43

  
44
class ImageClient(HTTPClient):
45
    @property
46
    def url(self):
47
        url = self.config.get('image_url') or self.config.get('url')
48
        if not url:
49
            raise ClientError('No URL was given')
50
        return url
38
class ImageClient(Client):
39
    """OpenStack Image Service API 1.0 and GRNET Plankton client"""
51 40
    
52
    @property
53
    def token(self):
54
        token = self.config.get('image_token') or self.config.get('token')
55
        if not token:
56
            raise ClientError('No token was given')
57
        return token
41
    def raise_for_status(self, r):
42
        if r.status_code == 404:
43
            raise ClientError("Image not found", r.status_code)
44
        
45
        # Fallback to the default
46
        super(ImageClient, self).raise_for_status(r)
58 47
    
59 48
    def list_public(self, detail=False, filters={}, order=''):
60 49
        path = '/images/detail' if detail else '/images/'
......
70 59
        if order:
71 60
            params['sort_key'] = order
72 61
        
73
        if params:
74
            path += '?' + '&'.join('%s=%s' % item for item in params.items())
75
        return self.http_get(path)
62
        r = self.get(path, params=params, success=200)
63
        return r.json
76 64
    
77 65
    def get_meta(self, image_id):
78
        path = '/images/%s' % image_id
79
        resp, buf = self.raw_http_cmd('HEAD', path)
66
        path = '/images/%s' % (image_id,)
67
        r = self.head(path, success=200)
68
        
80 69
        reply = {}
81
        prefix = 'x-image-meta-'
82
        for key, val in resp.getheaders():
70
        properties = {}
71
        meta_prefix = 'x-image-meta-'
72
        property_prefix = 'x-image-meta-property-'
73
        
74
        for key, val in r.headers.items():
83 75
            key = key.lower()
84
            if not key.startswith(prefix):
85
                continue
86
            key = key[len(prefix):]
87
            reply[key] = val
76
            if key.startswith(property_prefix):
77
                key = key[len(property_prefix):]
78
                properties[key] = val
79
            elif key.startswith(meta_prefix):
80
                key = key[len(meta_prefix):]
81
                reply[key] = val
82
        
83
        if properties:
84
            reply['properties'] = properties
88 85
        return reply
89 86
    
90 87
    def register(self, name, location, params={}, properties={}):
91 88
        path = '/images/'
92 89
        headers = {}
93
        headers['x-image-meta-name'] = quote(name)
90
        headers['x-image-meta-name'] = name
94 91
        headers['x-image-meta-location'] = location
92
        
95 93
        for key, val in params.items():
96 94
            if key in ('id', 'store', 'disk_format', 'container_format',
97 95
                       'size', 'checksum', 'is_public', 'owner'):
98 96
                key = 'x-image-meta-' + key.replace('_', '-')
99 97
                headers[key] = val
98
        
100 99
        for key, val in properties.items():
101
            headers['x-image-meta-property-' + quote(key)] = quote(val)
102
        return self.http_post(path, headers=headers, success=200)
100
            headers['x-image-meta-property-' + key] = val
101
        
102
        self.post(path, headers=headers, success=200)
103 103
    
104 104
    def list_members(self, image_id):
105
        path = '/images/%s/members' % image_id
106
        reply = self.http_get(path)
107
        return reply['members']
105
        path = '/images/%s/members' % (image_id,)
106
        r = self.get(path, success=200)
107
        return r.json['members']
108 108

  
109 109
    def list_shared(self, member):
110
        path = '/shared-images/%s' % member
111
        reply = self.http_get(path)
112
        return reply['shared_images']
110
        path = '/shared-images/%s' % (member,)
111
        r = self.get(path, success=200)
112
        return r.json['shared_images']
113 113

  
114 114
    def add_member(self, image_id, member):
115 115
        path = '/images/%s/members/%s' % (image_id, member)
116
        self.http_put(path)
116
        r = self.put(path, success=204)
117 117
    
118 118
    def remove_member(self, image_id, member):
119 119
        path = '/images/%s/members/%s' % (image_id, member)
120
        self.http_delete(path)
120
        self.delete(path, success=204)
121 121
    
122 122
    def set_members(self, image_id, members):
123 123
        path = '/images/%s/members' % image_id
124 124
        req = {'memberships': [{'member_id': member} for member in members]}
125
        body = json.dumps(req)
126
        self.http_put(path, body)
125
        self.put(path, json=req, success=204)

Also available in: Unified diff