~0x44/nova/extdoc

« back to all changes in this revision

Viewing changes to nova/image/service.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:
1
 
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
 
 
3
 
# Copyright 2010 OpenStack LLC.
4
 
# All Rights Reserved.
5
 
#
6
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
7
 
#    not use this file except in compliance with the License. You may obtain
8
 
#    a copy of the License at
9
 
#
10
 
#         http://www.apache.org/licenses/LICENSE-2.0
11
 
#
12
 
#    Unless required by applicable law or agreed to in writing, software
13
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
 
#    License for the specific language governing permissions and limitations
16
 
#    under the License.
17
 
 
18
 
 
19
 
from nova import utils
20
 
 
21
 
 
22
 
class BaseImageService(object):
23
 
    """Base class for providing image search and retrieval services.
24
 
 
25
 
    ImageService exposes two concepts of metadata:
26
 
 
27
 
        1. First-class attributes: This is metadata that is common to all
28
 
           ImageService subclasses and is shared across all hypervisors. These
29
 
           attributes are defined by IMAGE_ATTRS.
30
 
 
31
 
        2. Properties: This is metdata that is specific to an ImageService,
32
 
           and Image, or a particular hypervisor. Any attribute not present in
33
 
           BASE_IMAGE_ATTRS should be considered an image property.
34
 
 
35
 
    This means that ImageServices will return BASE_IMAGE_ATTRS as keys in the
36
 
    metadata dict, all other attributes will be returned as keys in the nested
37
 
    'properties' dict.
38
 
 
39
 
    """
40
 
 
41
 
    BASE_IMAGE_ATTRS = ['id', 'name', 'created_at', 'updated_at',
42
 
                        'deleted_at', 'deleted', 'status', 'is_public']
43
 
 
44
 
    # NOTE(sirp): ImageService subclasses may override this to aid translation
45
 
    # between BaseImageService attributes and additional metadata stored by
46
 
    # the ImageService subclass
47
 
    SERVICE_IMAGE_ATTRS = []
48
 
 
49
 
    def index(self, context, *args, **kwargs):
50
 
        """List images.
51
 
 
52
 
        :returns: a sequence of mappings with the following signature
53
 
                  {'id': opaque id of image, 'name': name of image}
54
 
 
55
 
        """
56
 
        raise NotImplementedError
57
 
 
58
 
    def detail(self, context, *args, **kwargs):
59
 
        """Detailed information about an images.
60
 
 
61
 
        :returns: a sequence of mappings with the following signature
62
 
                    {'id': opaque id of image,
63
 
                     'name': name of image,
64
 
                     'created_at': creation datetime object,
65
 
                     'updated_at': modification datetime object,
66
 
                     'deleted_at': deletion datetime object or None,
67
 
                     'deleted': boolean indicating if image has been deleted,
68
 
                     'status': string description of image status,
69
 
                     'is_public': boolean indicating if image is public
70
 
                     }
71
 
 
72
 
        If the service does not implement a method that provides a detailed
73
 
        set of information about images, then the method should raise
74
 
        NotImplementedError, in which case Nova will emulate this method
75
 
        with repeated calls to show() for each image received from the
76
 
        index() method.
77
 
 
78
 
        """
79
 
        raise NotImplementedError
80
 
 
81
 
    def show(self, context, image_id):
82
 
        """Detailed information about an image.
83
 
 
84
 
        :returns: a mapping with the following signature:
85
 
            {'id': opaque id of image,
86
 
             'name': name of image,
87
 
             'created_at': creation datetime object,
88
 
             'updated_at': modification datetime object,
89
 
             'deleted_at': deletion datetime object or None,
90
 
             'deleted': boolean indicating if image has been deleted,
91
 
             'status': string description of image status,
92
 
             'is_public': boolean indicating if image is public
93
 
             }, ...
94
 
 
95
 
        :raises: NotFound if the image does not exist
96
 
 
97
 
        """
98
 
        raise NotImplementedError
99
 
 
100
 
    def get(self, context, data):
101
 
        """Get an image.
102
 
 
103
 
        :param data: a file-like object to hold binary image data
104
 
        :returns: a dict containing image metadata, writes image data to data.
105
 
        :raises: NotFound if the image does not exist
106
 
 
107
 
        """
108
 
        raise NotImplementedError
109
 
 
110
 
    def create(self, context, metadata, data=None):
111
 
        """Store the image metadata and data.
112
 
 
113
 
        :returns: the new image metadata.
114
 
        :raises: AlreadyExists if the image already exist.
115
 
 
116
 
        """
117
 
        raise NotImplementedError
118
 
 
119
 
    def update(self, context, image_id, metadata, data=None):
120
 
        """Update the given image metadata and data and return the metadata.
121
 
 
122
 
        :raises: NotFound if the image does not exist.
123
 
 
124
 
        """
125
 
        raise NotImplementedError
126
 
 
127
 
    def delete(self, context, image_id):
128
 
        """Delete the given image.
129
 
 
130
 
        :raises: NotFound if the image does not exist.
131
 
 
132
 
        """
133
 
        raise NotImplementedError
134
 
 
135
 
    @staticmethod
136
 
    def _is_image_available(context, image_meta):
137
 
        """Check image availability.
138
 
 
139
 
        Images are always available if they are public or if the user is an
140
 
        admin.
141
 
 
142
 
        Otherwise, we filter by project_id (if present) and then fall-back to
143
 
        images owned by user.
144
 
 
145
 
        """
146
 
        # FIXME(sirp): We should be filtering by user_id on the Glance side
147
 
        # for security; however, we can't do that until we get authn/authz
148
 
        # sorted out. Until then, filtering in Nova.
149
 
        if image_meta['is_public'] or context.is_admin:
150
 
            return True
151
 
 
152
 
        properties = image_meta['properties']
153
 
 
154
 
        if context.project_id and ('project_id' in properties):
155
 
            return str(properties['project_id']) == str(context.project_id)
156
 
 
157
 
        try:
158
 
            user_id = properties['user_id']
159
 
        except KeyError:
160
 
            return False
161
 
 
162
 
        return str(user_id) == str(context.user_id)
163
 
 
164
 
    @classmethod
165
 
    def _translate_to_base(cls, metadata):
166
 
        """Return a metadata dictionary that is BaseImageService compliant.
167
 
 
168
 
        This is used by subclasses to expose only a metadata dictionary that
169
 
        is the same across ImageService implementations.
170
 
 
171
 
        """
172
 
        return cls._propertify_metadata(metadata, cls.BASE_IMAGE_ATTRS)
173
 
 
174
 
    @classmethod
175
 
    def _translate_to_service(cls, metadata):
176
 
        """Return a metadata dict that is usable by the ImageService subclass.
177
 
 
178
 
        As an example, Glance has additional attributes (like 'location'); the
179
 
        BaseImageService considers these properties, but we need to translate
180
 
        these back to first-class attrs for sending to Glance. This method
181
 
        handles this by allowing you to specify the attributes an ImageService
182
 
        considers first-class.
183
 
 
184
 
        """
185
 
        if not cls.SERVICE_IMAGE_ATTRS:
186
 
            raise NotImplementedError(_('Cannot use this without specifying '
187
 
                                        'SERVICE_IMAGE_ATTRS for subclass'))
188
 
        return cls._propertify_metadata(metadata, cls.SERVICE_IMAGE_ATTRS)
189
 
 
190
 
    @staticmethod
191
 
    def _propertify_metadata(metadata, keys):
192
 
        """Move unknown keys to a nested 'properties' dict.
193
 
 
194
 
        :returns: a new dict with the keys moved.
195
 
 
196
 
        """
197
 
        flattened = utils.flatten_dict(metadata)
198
 
        attributes, properties = utils.partition_dict(flattened, keys)
199
 
        attributes['properties'] = properties
200
 
        return attributes