35
35
This means that ImageServices will return BASE_IMAGE_ATTRS as keys in the
36
36
metadata dict, all other attributes will be returned as keys in the nested
39
41
BASE_IMAGE_ATTRS = ['id', 'name', 'created_at', 'updated_at',
40
42
'deleted_at', 'deleted', 'status', 'is_public']
45
47
SERVICE_IMAGE_ATTRS = []
47
49
def index(self, context):
49
Returns a sequence of mappings of id and name information about
53
:retval: a sequence of mappings with the following signature
54
{'id': opaque id of image, 'name': name of image}
52
:returns: a sequence of mappings with the following signature
53
{'id': opaque id of image, 'name': name of image}
57
56
raise NotImplementedError
59
58
def detail(self, context):
61
Returns a sequence of mappings of detailed information about images.
59
"""Detailed information about an images.
64
:retval: a sequence of mappings with the following signature
61
:returns: a sequence of mappings with the following signature
65
62
{'id': opaque id of image,
66
63
'name': name of image,
67
64
'created_at': creation datetime object,
77
74
NotImplementedError, in which case Nova will emulate this method
78
75
with repeated calls to show() for each image received from the
81
79
raise NotImplementedError
83
81
def show(self, context, image_id):
85
Returns a dict containing image metadata for the given opaque image id.
87
:retval a mapping with the following signature:
82
"""Detailed information about an image.
84
:returns: a mapping with the following signature:
89
85
{'id': opaque id of image,
90
86
'name': name of image,
91
87
'created_at': creation datetime object,
96
92
'is_public': boolean indicating if image is public
99
:raises NotFound if the image does not exist
95
:raises: NotFound if the image does not exist
101
98
raise NotImplementedError
103
100
def get(self, context, data):
105
Returns a dict containing image metadata and writes image data to data.
107
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
109
:raises NotFound if the image does not exist
111
108
raise NotImplementedError
113
110
def create(self, context, metadata, data=None):
115
Store the image metadata and data and return the new image metadata.
111
"""Store the image metadata and data.
117
:raises AlreadyExists if the image already exist.
113
:returns: the new image metadata.
114
:raises: AlreadyExists if the image already exist.
120
117
raise NotImplementedError
122
119
def update(self, context, image_id, metadata, data=None):
123
"""Update the given image metadata and data and return the metadata
120
"""Update the given image metadata and data and return the metadata.
125
:raises NotFound if the image does not exist.
122
:raises: NotFound if the image does not exist.
128
125
raise NotImplementedError
130
127
def delete(self, context, image_id):
132
Delete the given image.
128
"""Delete the given image.
134
:raises NotFound if the image does not exist.
130
:raises: NotFound if the image does not exist.
137
133
raise NotImplementedError
140
136
def _is_image_available(context, image_meta):
137
"""Check image availability.
142
139
Images are always available if they are public or if the user is an
145
142
Otherwise, we filter by project_id (if present) and then fall-back to
146
143
images owned by user.
148
146
# FIXME(sirp): We should be filtering by user_id on the Glance side
149
147
# for security; however, we can't do that until we get authn/authz
170
168
This is used by subclasses to expose only a metadata dictionary that
171
169
is the same across ImageService implementations.
173
172
return cls._propertify_metadata(metadata, cls.BASE_IMAGE_ATTRS)
176
175
def _translate_to_service(cls, metadata):
177
"""Return a metadata dictionary that is usable by the ImageService
176
"""Return a metadata dict that is usable by the ImageService subclass.
180
178
As an example, Glance has additional attributes (like 'location'); the
181
179
BaseImageService considers these properties, but we need to translate
182
180
these back to first-class attrs for sending to Glance. This method
183
181
handles this by allowing you to specify the attributes an ImageService
184
182
considers first-class.
186
185
if not cls.SERVICE_IMAGE_ATTRS:
187
raise NotImplementedError(_("Cannot use this without specifying "
188
"SERVICE_IMAGE_ATTRS for subclass"))
186
raise NotImplementedError(_('Cannot use this without specifying '
187
'SERVICE_IMAGE_ATTRS for subclass'))
189
188
return cls._propertify_metadata(metadata, cls.SERVICE_IMAGE_ATTRS)
192
191
def _propertify_metadata(metadata, keys):
193
"""Return a dict with any unrecognized keys placed in the nested
192
"""Move unknown keys to a nested 'properties' dict.
194
:returns: a new dict with the keys moved.
196
197
flattened = utils.flatten_dict(metadata)
197
198
attributes, properties = utils.partition_dict(flattened, keys)