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