Revision 17b255c7

b/Changelog
23 23
    move and copy
24 24
- Rename file/server-meta commands to file/server-metadata
25 25
- Rename image-[add|del]member commands to members-[add|delete]
26
- Remove update option from imagre-register
26
- Remove update option from image-register
27 27
- In image-compute split properties to properties-list and properties-get
28 28
- Add optional output to methods[#3756, #3732]:
29 29
    - file:
......
52 52
    - image: members, member
53 53
    - image compute: properties
54 54
    - server: firewall, metadata
55
- Add a _format_image_headers method and use it in image_register and get_meta
56
    for uniform image meta output [#3797]
57

  
55 58
Features:
56 59

  
57 60
- A logger module container a set of basic loging method for kamaki [#3668]
b/kamaki/clients/image/__init__.py
35 35
from kamaki.clients.utils import path4url, filter_in
36 36

  
37 37

  
38
def _format_image_headers(headers):
39
    reply = dict(properties=dict())
40
    meta_prefix = 'x-image-meta-'
41
    property_prefix = 'x-image-meta-property-'
42

  
43
    for key, val in headers.items():
44
        key = key.lower()
45
        if key.startswith(property_prefix):
46
            key = key[len(property_prefix):].upper().replace('-', '_')
47
            reply['properties'][key] = val
48
        elif key.startswith(meta_prefix):
49
            key = key[len(meta_prefix):]
50
            reply[key] = val
51
    return reply
52

  
53

  
38 54
class ImageClient(Client):
39 55
    """Synnefo Plankton API client"""
40 56

  
......
80 96
        path = path4url('images', image_id)
81 97
        r = self.head(path, success=200)
82 98

  
83
        reply = {}
84
        properties = {}
85
        meta_prefix = 'x-image-meta-'
86
        property_prefix = 'x-image-meta-property-'
87

  
88
        for key, val in r.headers.items():
89
            key = key.lower()
90
            if key.startswith(property_prefix):
91
                key = key[len(property_prefix):]
92
                properties[key] = val
93
            elif key.startswith(meta_prefix):
94
                key = key[len(meta_prefix):]
95
                reply[key] = val
96

  
97
        if properties:
98
            reply['properties'] = properties
99
        return reply
99
        return _format_image_headers(r.headers)
100 100

  
101 101
    def register(self, name, location, params={}, properties={}):
102 102
        """Register an image that is uploaded at location
......
110 110

  
111 111
        :param properties: (dict) image properties (X-Image-Meta-Property)
112 112

  
113
        :returns: (dict) details of the created image
113
        :returns: (dict) metadata of the created image
114 114
        """
115 115
        path = path4url('images') + '/'
116 116
        self.set_header('X-Image-Meta-Name', name)
......
127 127
            async_headers['x-image-meta-property-%s' % key] = val
128 128

  
129 129
        r = self.post(path, success=200, async_headers=async_headers)
130
        return filter_in(r.headers, 'X-Image-')
130

  
131
        return _format_image_headers(r.headers)
131 132

  
132 133
    def unregister(self, image_id):
133 134
        """Unregister an image
b/kamaki/clients/image/test.py
228 228
            params=params, properties=props)
229 229
        expectedict = dict(example_image_headers)
230 230
        expectedict.pop('extraheaders')
231
        self.assert_dicts_are_equal(expectedict, r)
231
        from kamaki.clients.image import _format_image_headers
232
        self.assert_dicts_are_equal(_format_image_headers(expectedict), r)
232 233
        self.assertEqual(
233 234
            post.mock_calls[-1],
234 235
            call('/images/', async_headers=async_headers, success=200))
b/kamaki/clients/livetest/image.py
85 85
            self.location,
86 86
            params=dict(is_public=True))
87 87
        self._imglist[self.imgname] = dict(
88
            name=r['x-image-meta-name'], id=r['x-image-meta-id'])
88
            name=r['name'], id=r['id'])
89 89
        self._imgdetails[self.imgname] = r
90 90

  
91 91
    def tearDown(self):
......
154 154
                    'properties',
155 155
                    'size'):
156 156
                self.assertTrue(term in img)
157
                if img['properties']:
157
                if len(img['properties']):
158 158
                    for interm in ('osfamily', 'users', 'root_partition'):
159 159
                        self.assertTrue(interm in img['properties'])
160 160
        size_max = 1000000000
......
185 185
                'container-format'):
186 186
            self.assertTrue(term in r)
187 187
            for interm in (
188
                    'kernel',
189
                    'osfamily',
190
                    'users',
191
                    'gui', 'sortorder',
192
                    'root-partition',
193
                    'os',
194
                    'description'):
188
                    'KERNEL',
189
                    'OSFAMILY',
190
                    'USERS',
191
                    'GUI',
192
                    'SORTORDER',
193
                    'ROOT_PARTITION',
194
                    'OS',
195
                    'DESCRIPTION'):
195 196
                self.assertTrue(interm in r['properties'])
196 197

  
197 198
    def test_register(self):
......
204 205
        for img in self._imglist.values():
205 206
            self.assertTrue(img is not None)
206 207
            r = set(self._imgdetails[img['name']].keys())
207
            self.assertTrue(
208
                r.issubset(['x-image-meta-%s' % k for k in IMGMETA]))
208
            self.assertTrue(r.issubset(IMGMETA.union(['properties'])))
209 209

  
210 210
    def test_unregister(self):
211 211
        """Test unregister"""

Also available in: Unified diff