90
92
return webob.exc.HTTPNoContent()
92
94
def create(self, req, body):
93
"""Snapshot a server instance and save the image.
95
"""Snapshot or backup a server instance and save the image.
97
Images now have an `image_type` associated with them, which can be
98
'snapshot' or the backup type, like 'daily' or 'weekly'.
100
If the image_type is backup-like, then the rotation factor can be
101
included and that will cause the oldest backups that exceed the
102
rotation factor to be deleted.
95
104
:param req: `wsgi.Request` object
106
def get_param(param):
108
return body["image"][param]
110
raise webob.exc.HTTPBadRequest(explanation="Missing required "
97
113
context = req.environ['nova.context']
98
114
content_type = req.get_content_type()
101
117
raise webob.exc.HTTPBadRequest()
119
image_type = body["image"].get("image_type", "snapshot")
104
122
server_id = self._server_id_from_req(req, body)
105
image_name = body["image"]["name"]
107
124
raise webob.exc.HTTPBadRequest()
126
image_name = get_param("name")
109
127
props = self._get_extra_properties(req, body)
111
image = self._compute_service.snapshot(context, server_id,
129
if image_type == "snapshot":
130
image = self._compute_service.snapshot(
131
context, server_id, image_name,
132
extra_properties=props)
133
elif image_type == "backup":
134
# NOTE(sirp): Unlike snapshot, backup is not a customer facing
135
# API call; rather, it's used by the internal backup scheduler
136
if not FLAGS.allow_admin_api:
137
raise webob.exc.HTTPBadRequest(
138
explanation="Admin API Required")
140
backup_type = get_param("backup_type")
141
rotation = int(get_param("rotation"))
143
image = self._compute_service.backup(
144
context, server_id, image_name,
145
backup_type, rotation, extra_properties=props)
147
LOG.error(_("Invalid image_type '%s' passed") % image_type)
148
raise webob.exc.HTTPBadRequest(explanation="Invalue image_type: "
113
151
return dict(image=self.get_builder(req).build(image, detail=True))
115
153
def get_builder(self, request):
116
154
"""Indicates that you must use a Controller subclass."""
117
raise NotImplementedError
155
raise NotImplementedError()
119
157
def _server_id_from_req(self, req, data):
120
158
raise NotImplementedError()
182
220
context = req.environ['nova.context']
183
221
filters = self._get_filters(req)
184
(marker, limit) = common.get_pagination_params(req)
185
images = self._image_service.index(
186
context, filters=filters, marker=marker, limit=limit)
222
page_params = common.get_pagination_params(req)
223
images = self._image_service.index(context, filters=filters,
187
225
builder = self.get_builder(req).build
188
226
return dict(images=[builder(image, detail=False) for image in images])
196
234
context = req.environ['nova.context']
197
235
filters = self._get_filters(req)
198
(marker, limit) = common.get_pagination_params(req)
199
images = self._image_service.detail(
200
context, filters=filters, marker=marker, limit=limit)
236
page_params = common.get_pagination_params(req)
237
images = self._image_service.detail(context, filters=filters,
201
239
builder = self.get_builder(req).build
202
240
return dict(images=[builder(image, detail=True) for image in images])
224
262
return {'instance_ref': server_ref}
265
class ImageXMLSerializer(wsgi.XMLDictSerializer):
269
"image": ["id", "name", "updated", "created", "status",
270
"serverId", "progress", "serverRef"],
271
"link": ["rel", "type", "href"],
275
xmlns = wsgi.XMLNS_V11
278
self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer()
280
def _image_to_xml(self, xml_doc, image):
282
metadata = image.pop('metadata').items()
284
LOG.debug(_("Image object missing metadata attribute"))
287
node = self._to_xml_node(xml_doc, self.metadata, 'image', image)
288
metadata_node = self.metadata_serializer.meta_list_to_xml(xml_doc,
290
node.appendChild(metadata_node)
293
def _image_list_to_xml(self, xml_doc, images):
294
container_node = xml_doc.createElement('images')
296
item_node = self._image_to_xml(xml_doc, image)
297
container_node.appendChild(item_node)
298
return container_node
300
def _image_to_xml_string(self, image):
301
xml_doc = minidom.Document()
302
item_node = self._image_to_xml(xml_doc, image)
303
self._add_xmlns(item_node)
304
return item_node.toprettyxml(indent=' ')
306
def _image_list_to_xml_string(self, images):
307
xml_doc = minidom.Document()
308
container_node = self._image_list_to_xml(xml_doc, images)
309
self._add_xmlns(container_node)
310
return container_node.toprettyxml(indent=' ')
312
def detail(self, images_dict):
313
return self._image_list_to_xml_string(images_dict['images'])
315
def show(self, image_dict):
316
return self._image_to_xml_string(image_dict['image'])
318
def create(self, image_dict):
319
return self._image_to_xml_string(image_dict['image'])
227
322
def create_resource(version='1.0'):
229
324
'1.0': ControllerV10,
230
325
'1.1': ControllerV11,
234
'1.0': wsgi.XMLNS_V10,
235
'1.1': wsgi.XMLNS_V11,
330
"image": ["id", "name", "updated", "created", "status",
331
"serverId", "progress", "serverRef"],
332
"link": ["rel", "type", "href"],
337
'1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
338
'1.1': ImageXMLSerializer(),
240
"image": ["id", "name", "updated", "created", "status",
241
"serverId", "progress", "serverRef"],
242
"link": ["rel", "type", "href"],
247
'application/xml': wsgi.XMLDictSerializer(xmlns=xmlns,
342
'application/xml': xml_serializer,
251
345
return wsgi.Resource(controller, serializers=serializers)