nova/nova/api/openstack/compute/views/images.py

167 lines
6.1 KiB
Python

# Copyright 2010-2011 OpenStack Foundation
# Copyright 2013 IBM Corp.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova.api.openstack import common
from nova.image import glance
from nova.openstack.common import timeutils
class ViewBuilder(common.ViewBuilder):
_collection_name = "images"
def basic(self, request, image):
"""Return a dictionary with basic image attributes."""
return {
"image": {
"id": image.get("id"),
"name": image.get("name"),
"links": self._get_links(request,
image["id"],
self._collection_name),
},
}
def show(self, request, image):
"""Return a dictionary with image details."""
image_dict = {
"id": image.get("id"),
"name": image.get("name"),
"minRam": int(image.get("min_ram") or 0),
"minDisk": int(image.get("min_disk") or 0),
"metadata": image.get("properties", {}),
"created": self._format_date(image.get("created_at")),
"updated": self._format_date(image.get("updated_at")),
"status": self._get_status(image),
"progress": self._get_progress(image),
"links": self._get_links(request,
image["id"],
self._collection_name),
}
instance_uuid = image.get("properties", {}).get("instance_uuid")
if instance_uuid is not None:
server_ref = self._get_href_link(request, instance_uuid, 'servers')
image_dict["server"] = {
"id": instance_uuid,
"links": [{
"rel": "self",
"href": server_ref,
},
{
"rel": "bookmark",
"href": self._get_bookmark_link(request,
instance_uuid,
'servers'),
}],
}
return dict(image=image_dict)
def detail(self, request, images):
"""Show a list of images with details."""
list_func = self.show
return self._list_view(list_func, request, images)
def index(self, request, images):
"""Show a list of images with basic attributes."""
list_func = self.basic
return self._list_view(list_func, request, images)
def _list_view(self, list_func, request, images):
"""Provide a view for a list of images."""
image_list = [list_func(request, image)["image"] for image in images]
images_links = self._get_collection_links(request,
images,
self._collection_name)
images_dict = dict(images=image_list)
if images_links:
images_dict["images_links"] = images_links
return images_dict
def _get_links(self, request, identifier, collection_name):
"""Return a list of links for this image."""
return [{
"rel": "self",
"href": self._get_href_link(request, identifier, collection_name),
},
{
"rel": "bookmark",
"href": self._get_bookmark_link(request,
identifier,
collection_name),
},
{
"rel": "alternate",
"type": "application/vnd.openstack.image",
"href": self._get_alternate_link(request, identifier),
}]
def _get_alternate_link(self, request, identifier):
"""Create an alternate link for a specific image id."""
glance_url = glance.generate_glance_url()
glance_url = self._update_glance_link_prefix(glance_url)
return '/'.join([glance_url,
request.environ["nova.context"].project_id,
self._collection_name,
str(identifier)])
@staticmethod
def _format_date(dt):
"""Return standard format for a given datetime object."""
if dt is not None:
return timeutils.isotime(dt)
@staticmethod
def _get_status(image):
"""Update the status field to standardize format."""
return {
'active': 'ACTIVE',
'queued': 'SAVING',
'saving': 'SAVING',
'deleted': 'DELETED',
'pending_delete': 'DELETED',
'killed': 'ERROR',
}.get(image.get("status"), 'UNKNOWN')
@staticmethod
def _get_progress(image):
return {
"queued": 25,
"saving": 50,
"active": 100,
}.get(image.get("status"), 0)
class ViewBuilderV3(ViewBuilder):
def _get_bookmark_link(self, request, identifier, collection_name):
"""Create a URL that refers to a specific resource."""
if collection_name == "images":
glance_url = glance.generate_image_url(identifier)
return self._update_glance_link_prefix(glance_url)
else:
raise NotImplementedError
# NOTE(cyeoh) The V3 version of _get_bookmark_link should
# only ever be called with images as the
# collection_name. The images API has been removed in the
# V3 API and the V3 version of the view only exists for
# the servers view to be able to generate the appropriate
# bookmark link for the image of the instance.