~0x44/nova/extdoc

« back to all changes in this revision

Viewing changes to nova/image/glance.py

  • Committer: Tarmac
  • Author(s): Brian Waldon
  • Date: 2011-09-13 15:23:15 UTC
  • mfrom: (1517.2.17 image-service-cleanup)
  • Revision ID: tarmac-20110913152315-a21jg0bvjjlyga82
- remove translation of non-recognized attributes to user metadata, now just ignored
- ensure all keys are defined in image dictionaries, defaulting to None if glance client doesn't provide one
- remove BaseImageService
- reorganize some GlanceImageService tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
from nova import flags
32
32
from nova import log as logging
33
33
from nova import utils
34
 
from nova.image import service
35
34
 
36
35
 
37
36
LOG = logging.getLogger('nova.image.glance')
114
113
    return (glance_client, image_id)
115
114
 
116
115
 
117
 
class GlanceImageService(service.BaseImageService):
 
116
class GlanceImageService(object):
118
117
    """Provides storage and retrieval of disk image objects within Glance."""
119
118
 
120
 
    GLANCE_ONLY_ATTRS = ['size', 'location', 'disk_format',
121
 
                         'container_format', 'checksum']
122
 
 
123
 
    # NOTE(sirp): Overriding to use _translate_to_service provided by
124
 
    # BaseImageService
125
 
    SERVICE_IMAGE_ATTRS = service.BaseImageService.BASE_IMAGE_ATTRS +\
126
 
                          GLANCE_ONLY_ATTRS
127
 
 
128
119
    def __init__(self, client=None):
129
120
        self._client = client
130
121
 
160
151
        images = []
161
152
        for image_meta in image_metas:
162
153
            if self._is_image_available(context, image_meta):
163
 
                base_image_meta = self._translate_to_base(image_meta)
 
154
                base_image_meta = self._translate_from_glance(image_meta)
164
155
                images.append(base_image_meta)
165
156
        return images
166
157
 
224
215
        if not self._is_image_available(context, image_meta):
225
216
            raise exception.ImageNotFound(image_id=image_id)
226
217
 
227
 
        base_image_meta = self._translate_to_base(image_meta)
 
218
        base_image_meta = self._translate_from_glance(image_meta)
228
219
        return base_image_meta
229
220
 
230
221
    def show_by_name(self, context, name):
248
239
        for chunk in image_chunks:
249
240
            data.write(chunk)
250
241
 
251
 
        base_image_meta = self._translate_to_base(image_meta)
 
242
        base_image_meta = self._translate_from_glance(image_meta)
252
243
        return base_image_meta
253
244
 
254
245
    def create(self, context, image_meta, data=None):
260
251
        # Translate Base -> Service
261
252
        LOG.debug(_('Creating image in Glance. Metadata passed in %s'),
262
253
                  image_meta)
263
 
        sent_service_image_meta = self._translate_to_service(image_meta)
 
254
        sent_service_image_meta = self._translate_to_glance(image_meta)
264
255
        LOG.debug(_('Metadata after formatting for Glance %s'),
265
256
                  sent_service_image_meta)
266
257
 
268
259
            sent_service_image_meta, data)
269
260
 
270
261
        # Translate Service -> Base
271
 
        base_image_meta = self._translate_to_base(recv_service_image_meta)
 
262
        base_image_meta = self._translate_from_glance(recv_service_image_meta)
272
263
        LOG.debug(_('Metadata returned from Glance formatted for Base %s'),
273
264
                  base_image_meta)
274
265
        return base_image_meta
281
272
        """
282
273
        # NOTE(vish): show is to check if image is available
283
274
        self.show(context, image_id)
284
 
        image_meta = _convert_to_string(image_meta)
 
275
        image_meta = self._translate_to_glance(image_meta)
285
276
        try:
286
277
            client = self._get_client(context)
287
278
            image_meta = client.update_image(image_id, image_meta, data)
288
279
        except glance_exception.NotFound:
289
280
            raise exception.ImageNotFound(image_id=image_id)
290
281
 
291
 
        base_image_meta = self._translate_to_base(image_meta)
 
282
        base_image_meta = self._translate_from_glance(image_meta)
292
283
        return base_image_meta
293
284
 
294
285
    def delete(self, context, image_id):
310
301
        pass
311
302
 
312
303
    @classmethod
313
 
    def _translate_to_service(cls, image_meta):
314
 
        image_meta = super(GlanceImageService,
315
 
                           cls)._translate_to_service(image_meta)
 
304
    def _translate_to_glance(cls, image_meta):
316
305
        image_meta = _convert_to_string(image_meta)
 
306
        image_meta = _remove_read_only(image_meta)
317
307
        return image_meta
318
308
 
319
309
    @classmethod
320
 
    def _translate_to_base(cls, image_meta):
321
 
        """Override translation to handle conversion to datetime objects."""
322
 
        image_meta = service.BaseImageService._propertify_metadata(
323
 
                        image_meta, cls.SERVICE_IMAGE_ATTRS)
 
310
    def _translate_from_glance(cls, image_meta):
 
311
        image_meta = _limit_attributes(image_meta)
324
312
        image_meta = _convert_timestamps_to_datetimes(image_meta)
325
313
        image_meta = _convert_from_string(image_meta)
326
314
        return image_meta
330
318
        """Check image availability.
331
319
 
332
320
        Under Glance, images are always available if the context has
333
 
        an auth_token.  Otherwise, we fall back to the superclass
334
 
        method.
 
321
        an auth_token.
335
322
 
336
323
        """
337
324
        if hasattr(context, 'auth_token') and context.auth_token:
338
325
            return True
339
 
        return service.BaseImageService._is_image_available(context,
340
 
                                                            image_meta)
 
326
 
 
327
        if image_meta['is_public'] or context.is_admin:
 
328
            return True
 
329
 
 
330
        properties = image_meta['properties']
 
331
 
 
332
        if context.project_id and ('project_id' in properties):
 
333
            return str(properties['project_id']) == str(context.project_id)
 
334
 
 
335
        try:
 
336
            user_id = properties['user_id']
 
337
        except KeyError:
 
338
            return False
 
339
 
 
340
        return str(user_id) == str(context.user_id)
341
341
 
342
342
 
343
343
# utility functions
397
397
 
398
398
def _convert_to_string(metadata):
399
399
    return _convert(_json_dumps, metadata)
 
400
 
 
401
 
 
402
def _limit_attributes(image_meta):
 
403
    IMAGE_ATTRIBUTES = ['size', 'location', 'disk_format',
 
404
                        'container_format', 'checksum', 'id',
 
405
                        'name', 'created_at', 'updated_at',
 
406
                        'deleted_at', 'deleted', 'status',
 
407
                        'is_public']
 
408
    output = {}
 
409
    for attr in IMAGE_ATTRIBUTES:
 
410
        output[attr] = image_meta.get(attr)
 
411
 
 
412
    output['properties'] = image_meta.get('properties', {})
 
413
 
 
414
    return output
 
415
 
 
416
 
 
417
def _remove_read_only(image_meta):
 
418
    IMAGE_ATTRIBUTES = ['updated_at', 'created_at', 'deleted_at']
 
419
    output = copy.deepcopy(image_meta)
 
420
    for attr in IMAGE_ATTRIBUTES:
 
421
        if attr in output:
 
422
            del output[attr]
 
423
    return output