api: Add response body schemas for images APIs
This is mostly uneventful save for us needing to fix our API ref, which indicated that the 'OS-EXT-IMG-SIZE:size' field shown in the 'show' and 'detail' views was a string rather than an int. You can confirm this is *not* the case like so: >>> import openstack >>> conn = openstack.connect() >>> conn.conn.compute.get('https://example.com/compute/v2.1/images/detail').json() (obviously replace 'https://example.com/' with a compute API host) Change-Id: Ia318478dfdb50f8d57a74958b3555f6ad97351ec Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"image": {
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-IMG-SIZE:size": "74185822",
|
||||
"OS-EXT-IMG-SIZE:size": 74185822,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "25165824",
|
||||
"OS-EXT-IMG-SIZE:size": 25165824,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
|
||||
"links": [
|
||||
@@ -32,7 +32,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "58145823",
|
||||
"OS-EXT-IMG-SIZE:size": 58145823,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "a2459075-d96c-40d5-893e-577ff92e721c",
|
||||
"links": [
|
||||
@@ -62,7 +62,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "83594576",
|
||||
"OS-EXT-IMG-SIZE:size": 83594576,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "76fa36fc-c930-4bf3-8c8a-ea2a2420deb6",
|
||||
"links": [
|
||||
@@ -93,7 +93,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "84035174",
|
||||
"OS-EXT-IMG-SIZE:size": 84035174,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "cedef40a-ed67-4d10-800e-17455edce175",
|
||||
"links": [
|
||||
@@ -123,7 +123,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "26360814",
|
||||
"OS-EXT-IMG-SIZE:size": 26360814,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "c905cedb-7281-47e4-8a62-f26bc5fc4c77",
|
||||
"links": [
|
||||
@@ -154,7 +154,7 @@
|
||||
},
|
||||
{
|
||||
"OS-DCF:diskConfig": "MANUAL",
|
||||
"OS-EXT-IMG-SIZE:size": "49163826",
|
||||
"OS-EXT-IMG-SIZE:size": 49163826,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "a440c04b-79fa-479c-bed1-0b816eaec379",
|
||||
"links": [
|
||||
@@ -187,7 +187,7 @@
|
||||
},
|
||||
{
|
||||
"OS-DCF:diskConfig": "AUTO",
|
||||
"OS-EXT-IMG-SIZE:size": "74185822",
|
||||
"OS-EXT-IMG-SIZE:size": 74185822,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
@@ -219,7 +219,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "25165824",
|
||||
"OS-EXT-IMG-SIZE:size": 25165824,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "95fad737-9325-4855-b37e-20a62268ec88",
|
||||
"links": [
|
||||
@@ -248,7 +248,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "25165824",
|
||||
"OS-EXT-IMG-SIZE:size": 25165824,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "535426d4-5d75-44f4-9591-a2123d23c33f",
|
||||
"links": [
|
||||
@@ -277,7 +277,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "25165824",
|
||||
"OS-EXT-IMG-SIZE:size": 25165824,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "5f7d4f5b-3781-4a4e-9046-a2a800e807e5",
|
||||
"links": [
|
||||
@@ -307,7 +307,7 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
},
|
||||
{
|
||||
"OS-EXT-IMG-SIZE:size": "25165824",
|
||||
"OS-EXT-IMG-SIZE:size": 25165824,
|
||||
"created": "2011-01-01T01:02:03Z",
|
||||
"id": "261b52ed-f693-4147-8f3b-d25df5efd968",
|
||||
"links": [
|
||||
@@ -337,4 +337,4 @@
|
||||
"updated": "2011-01-01T01:02:03Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -38,20 +38,21 @@ SUPPORTED_FILTERS = {
|
||||
}
|
||||
|
||||
|
||||
@validation.validated
|
||||
class ImagesController(wsgi.Controller):
|
||||
"""Base controller for retrieving/displaying images."""
|
||||
|
||||
_view_builder_class = views_images.ViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
super(ImagesController, self).__init__()
|
||||
super().__init__()
|
||||
self._image_api = glance.API()
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""Return a dictionary of query param filters from the request.
|
||||
|
||||
:param req: the Request object coming from the wsgi layer
|
||||
:retval a dict of key/value filters
|
||||
:returns: a dict of key/value filters
|
||||
"""
|
||||
filters = {}
|
||||
for param in req.params:
|
||||
@@ -77,6 +78,7 @@ class ImagesController(wsgi.Controller):
|
||||
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
|
||||
@wsgi.expected_errors(404)
|
||||
@validation.query_schema(schema.show_query)
|
||||
@validation.response_body_schema(schema.show_response)
|
||||
def show(self, req, id):
|
||||
"""Return detailed information about a specific image.
|
||||
|
||||
@@ -96,6 +98,7 @@ class ImagesController(wsgi.Controller):
|
||||
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
|
||||
@wsgi.expected_errors((403, 404))
|
||||
@wsgi.response(204)
|
||||
@validation.response_body_schema(schema.delete_response)
|
||||
def delete(self, req, id):
|
||||
"""Delete an image, if allowed.
|
||||
|
||||
@@ -117,11 +120,11 @@ class ImagesController(wsgi.Controller):
|
||||
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
|
||||
@wsgi.expected_errors(400)
|
||||
@validation.query_schema(schema.index_query)
|
||||
@validation.response_body_schema(schema.index_response)
|
||||
def index(self, req):
|
||||
"""Return an index listing of images available to the request.
|
||||
|
||||
:param req: `wsgi.Request` object
|
||||
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
filters = self._get_filters(req)
|
||||
@@ -137,11 +140,11 @@ class ImagesController(wsgi.Controller):
|
||||
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
|
||||
@wsgi.expected_errors(400)
|
||||
@validation.query_schema(schema.detail_query)
|
||||
@validation.response_body_schema(schema.detail_response)
|
||||
def detail(self, req):
|
||||
"""Return a detailed index listing of images available to the request.
|
||||
|
||||
:param req: `wsgi.Request` object.
|
||||
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
filters = self._get_filters(req)
|
||||
|
@@ -10,7 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from nova.api.validation import parameter_types
|
||||
from nova.api.validation import response_types
|
||||
|
||||
# NOTE(stephenfin): These schemas are incomplete but won't be enhanced further
|
||||
# since these APIs have been removed
|
||||
@@ -50,3 +53,179 @@ index_query = {
|
||||
}
|
||||
|
||||
detail_query = index_query
|
||||
|
||||
_links_response = {
|
||||
'type': 'array',
|
||||
'prefixItems': [
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {'type': 'string', 'format': 'uri'},
|
||||
'rel': {'const': 'self'},
|
||||
},
|
||||
'required': ['href', 'rel'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {'type': 'string', 'format': 'uri'},
|
||||
'rel': {'const': 'bookmark'},
|
||||
},
|
||||
'required': ['href', 'rel'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {'type': 'string', 'format': 'uri'},
|
||||
'rel': {'const': 'alternate'},
|
||||
'type': {'const': 'application/vnd.openstack.image'},
|
||||
},
|
||||
'required': ['href', 'rel', 'type'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
],
|
||||
'minItems': 3,
|
||||
'maxItems': 3,
|
||||
}
|
||||
|
||||
_image_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'created': {'type': 'string', 'format': 'date-time'},
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'links': _links_response,
|
||||
'metadata': {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
# unlike nova's metadata, glance doesn't have a maximum length
|
||||
# on property values. Also, while glance serializes all
|
||||
# non-null values as strings, nova's image API deserializes
|
||||
# these again, so we can expected practically any primitive
|
||||
# type here. Listing all these is effectively the same as
|
||||
# providing an empty schema so we're mainly doing it for the
|
||||
# benefit of tooling.
|
||||
'^[a-zA-Z0-9-_:. ]{1,255}$': {
|
||||
'type': [
|
||||
'array',
|
||||
'boolean',
|
||||
'integer',
|
||||
'number',
|
||||
'object',
|
||||
'string',
|
||||
'null',
|
||||
]
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'minDisk': {'type': 'integer', 'minimum': 0},
|
||||
'minRam': {'type': 'integer', 'minimum': 0},
|
||||
'name': {'type': ['string', 'null']},
|
||||
'progress': {
|
||||
'type': 'integer',
|
||||
'enum': [0, 25, 50, 100],
|
||||
},
|
||||
'server': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'links': {
|
||||
'type': 'array',
|
||||
'prefixItems': [
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {'type': 'string', 'format': 'uri'},
|
||||
'rel': {'const': 'self'},
|
||||
},
|
||||
'required': ['href', 'rel'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {'type': 'string', 'format': 'uri'},
|
||||
'rel': {'const': 'bookmark'},
|
||||
},
|
||||
'required': ['href', 'rel'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
],
|
||||
'minItems': 2,
|
||||
'maxItems': 2,
|
||||
},
|
||||
},
|
||||
'required': ['id', 'links'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'status': {
|
||||
'type': 'string',
|
||||
'enum': ['ACTIVE', 'SAVING', 'DELETED', 'ERROR', 'UNKNOWN'],
|
||||
},
|
||||
'updated': {'type': ['string', 'null'], 'format': 'date-time'},
|
||||
'OS-DCF:diskConfig': {'type': 'string', 'enum': ['AUTO', 'MANUAL']},
|
||||
'OS-EXT-IMG-SIZE:size': {'type': 'integer'},
|
||||
},
|
||||
'required': [
|
||||
'created',
|
||||
'id',
|
||||
'links',
|
||||
'metadata',
|
||||
'minDisk',
|
||||
'minRam',
|
||||
'name',
|
||||
'progress',
|
||||
'status',
|
||||
'updated',
|
||||
'OS-EXT-IMG-SIZE:size',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
show_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'image': copy.deepcopy(_image_response),
|
||||
},
|
||||
'required': [],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
delete_response = {'type': 'null'}
|
||||
|
||||
index_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'images': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {'type': 'string', 'format': 'uuid'},
|
||||
'links': _links_response,
|
||||
'name': {'type': ['string', 'null']},
|
||||
},
|
||||
'required': ['id', 'links', 'name'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'images_links': response_types.collection_links,
|
||||
},
|
||||
'required': [],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
detail_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'images': {
|
||||
'type': 'array',
|
||||
'items': copy.deepcopy(_image_response),
|
||||
},
|
||||
'images_links': response_types.collection_links,
|
||||
},
|
||||
'required': ['images'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ metadata = {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^[a-zA-Z0-9-_:. ]{1,255}$': {
|
||||
'type': 'string', 'maxLength': 255,
|
||||
'type': ['string', 'null'], 'maxLength': 255,
|
||||
}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
|
27
nova/tests/fixtures/glance.py
vendored
27
nova/tests/fixtures/glance.py
vendored
@@ -30,7 +30,9 @@ class GlanceFixture(fixtures.Fixture):
|
||||
|
||||
# NOTE(justinsb): The OpenStack API can't upload an image?
|
||||
# So, make sure we've got one..
|
||||
timestamp = datetime.datetime(2011, 1, 1, 1, 2, 3)
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
|
||||
image1 = {
|
||||
'id': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
|
||||
@@ -43,7 +45,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': False,
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'size': '25165824',
|
||||
'size': 25165824,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -67,7 +69,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': True,
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'ami',
|
||||
'size': '58145823',
|
||||
'size': 58145823,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -90,7 +92,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': True,
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'raw',
|
||||
'size': '83594576',
|
||||
'size': 83594576,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -114,7 +116,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': True,
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'ami',
|
||||
'size': '84035174',
|
||||
'size': 84035174,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -137,7 +139,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': True,
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'ami',
|
||||
'size': '26360814',
|
||||
'size': 26360814,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -160,7 +162,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '49163826',
|
||||
'size': 49163826,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -185,7 +187,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -309,7 +311,7 @@ class GlanceFixture(fixtures.Fixture):
|
||||
# by the caller. This is needed to avoid a KeyError in the
|
||||
# image-size API.
|
||||
if 'size' not in image_meta:
|
||||
image_meta['size'] = None
|
||||
image_meta['size'] = 74185822
|
||||
|
||||
# Similarly, Glance provides the status on the image once it's created
|
||||
# and this is checked in the compute API when booting a server from
|
||||
@@ -325,6 +327,13 @@ class GlanceFixture(fixtures.Fixture):
|
||||
# proxy API by throwing it into the generic "properties" dict.
|
||||
image_meta.get('properties', {})['owner'] = context.project_id
|
||||
|
||||
# Glance would always populate these fields, so we need to ensure we do
|
||||
# the same
|
||||
if not image_meta.get('created_at'):
|
||||
image_meta['created_at'] = self.timestamp
|
||||
if not image_meta.get('updated_at'):
|
||||
image_meta['updated_at'] = self.timestamp
|
||||
|
||||
self.images[image_id] = image_meta
|
||||
|
||||
if data:
|
||||
|
@@ -411,7 +411,7 @@ class InstanceHelperMixin:
|
||||
'is_public': False,
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'size': '25165824',
|
||||
'size': 25165824,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -740,8 +740,9 @@ class InstanceHelperMixin:
|
||||
def _create_server_boot_from_volume(self, image_args=None,
|
||||
flavor_id=None, networks=None):
|
||||
bfv_image_id = uuids.bfv_image_uuid
|
||||
timestamp = datetime.datetime(2011, 1, 1, 1, 2, 3)
|
||||
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
image = {
|
||||
'id': bfv_image_id,
|
||||
'name': 'fake_image_name',
|
||||
@@ -752,7 +753,8 @@ class InstanceHelperMixin:
|
||||
'status': 'active',
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'min_disk': 0
|
||||
'min_disk': 0,
|
||||
'size': 74185822,
|
||||
}
|
||||
if image_args:
|
||||
image.update(image_args)
|
||||
|
@@ -111,20 +111,23 @@ class LibvirtDeviceBusMigration(base.ServersTestBase):
|
||||
'hw_video_model': 'qxl',
|
||||
'hw_vif_model': 'e1000',
|
||||
}
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
self.glance.create(
|
||||
None,
|
||||
{
|
||||
'id': uuids.hw_bus_model_image_uuid,
|
||||
'name': 'hw_bus_model_image',
|
||||
'created_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'updated_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
'status': 'active',
|
||||
'is_public': False,
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'qcow2',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -330,20 +333,23 @@ class LibvirtDeviceBusMigration(base.ServersTestBase):
|
||||
'hw_video_model': 'cirrus',
|
||||
'hw_vif_model': 'e1000',
|
||||
}
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
self.glance.create(
|
||||
None,
|
||||
{
|
||||
'id': uuids.pc_image_uuid,
|
||||
'name': 'pc_image',
|
||||
'created_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'updated_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
'status': 'active',
|
||||
'is_public': False,
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'qcow2',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -57,7 +57,9 @@ class RescueServerTestWithDeletedBaseImage(
|
||||
'nova.virt.libvirt.utils.get_instance_path', fake_path))
|
||||
|
||||
def _create_test_images(self):
|
||||
timestamp = datetime.datetime(2021, 1, 2, 3, 4, 5)
|
||||
timestamp = datetime.datetime(
|
||||
2021, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
base_image = {
|
||||
'id': uuids.base_image,
|
||||
'name': 'base_image',
|
||||
@@ -69,7 +71,7 @@ class RescueServerTestWithDeletedBaseImage(
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
@@ -88,7 +90,7 @@ class RescueServerTestWithDeletedBaseImage(
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -75,7 +75,9 @@ class UEFIServersTest(base.ServersTestBase):
|
||||
self.assertIn('COMPUTE_SECURITY_UEFI_SECURE_BOOT', traits)
|
||||
|
||||
# create a server with UEFI and secure boot
|
||||
timestamp = datetime.datetime(2021, 1, 2, 3, 4, 5)
|
||||
timestamp = datetime.datetime(
|
||||
2021, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
uefi_image = {
|
||||
'id': uuids.uefi_image,
|
||||
'name': 'uefi_image',
|
||||
@@ -87,7 +89,7 @@ class UEFIServersTest(base.ServersTestBase):
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -30,20 +30,23 @@ class LibvirtVifModelTest(base.ServersTestBase):
|
||||
CONF.set_default("image_metadata_prefilter", True, group='scheduler')
|
||||
super().setUp()
|
||||
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
self.glance.create(
|
||||
None,
|
||||
{
|
||||
'id': uuids.image_vif_model_igb,
|
||||
'name': 'image-with-igb',
|
||||
'created_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'updated_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'deleted_at': None,
|
||||
'deleted': False,
|
||||
'status': 'active',
|
||||
'is_public': False,
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'qcow2',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -44,7 +44,7 @@ class TestServerGet(test.TestCase):
|
||||
'is_public': False,
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'size': '25165824',
|
||||
'size': 25165824,
|
||||
'properties': {'kernel_id': 'nokernel',
|
||||
'ramdisk_id': 'nokernel',
|
||||
'architecture': 'x64'}}
|
||||
|
@@ -34,7 +34,9 @@ class TestNonBootableImageMeta(integrated_helpers._IntegratedTestBase):
|
||||
super().setUp()
|
||||
|
||||
# Add an image to the Glance fixture with cinder_encryption_key set
|
||||
timestamp = datetime.datetime(2011, 1, 1, 1, 2, 3)
|
||||
timestamp = datetime.datetime(
|
||||
2011, 1, 1, 1, 2, 3, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
cinder_encrypted_image = {
|
||||
'id': uuids.cinder_encrypted_image_uuid,
|
||||
'name': 'cinder_encryption_key_image',
|
||||
@@ -46,7 +48,7 @@ class TestNonBootableImageMeta(integrated_helpers._IntegratedTestBase):
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -58,7 +58,7 @@ class AggregateImagePropertiesIsolationTestCase(_AggregateTestCase):
|
||||
'is_public': False,
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'size': '25165824',
|
||||
'size': 25165824,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -39,7 +39,7 @@ class BFVRescue(integrated_helpers.ProviderUsageBaseTestCase):
|
||||
'is_public': False,
|
||||
'container_format': 'raw',
|
||||
'disk_format': 'raw',
|
||||
'size': '25165824',
|
||||
'size': 25165824,
|
||||
'min_ram': 0,
|
||||
'min_disk': 0,
|
||||
'protected': False,
|
||||
|
@@ -111,7 +111,7 @@ class DiskConfigTestCaseV21(test.TestCase):
|
||||
'is_public': False,
|
||||
'container_format': 'ova',
|
||||
'disk_format': 'vhd',
|
||||
'size': '74185822',
|
||||
'size': 74185822,
|
||||
'properties': {'auto_disk_config': 'Disabled'}}
|
||||
self.image_service.create(None, image)
|
||||
|
||||
|
@@ -68,104 +68,116 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
self.server_uuid))
|
||||
self.alternate = "%s/images/%s"
|
||||
|
||||
self.expected_image_123 = {
|
||||
"image": {'id': '123',
|
||||
'name': 'public image',
|
||||
'metadata': {'key1': 'value1'},
|
||||
'updated': NOW_API_FORMAT,
|
||||
'created': NOW_API_FORMAT,
|
||||
'status': 'ACTIVE',
|
||||
'minDisk': 10,
|
||||
'progress': 100,
|
||||
'minRam': 128,
|
||||
'OS-EXT-IMG-SIZE:size': 25165824,
|
||||
"links": [{
|
||||
"rel": "self",
|
||||
"href": "%s/123" % self.url_prefix
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href":
|
||||
"%s/123" % self.bookmark_prefix
|
||||
},
|
||||
{
|
||||
"rel": "alternate",
|
||||
"type": "application/vnd.openstack.image",
|
||||
"href": self.alternate %
|
||||
(glance.generate_glance_url('ctx'),
|
||||
123),
|
||||
}],
|
||||
self.image_a_uuid = IMAGE_FIXTURES[0]['id']
|
||||
self.expected_image_a = {
|
||||
"image": {
|
||||
'id': self.image_a_uuid,
|
||||
'name': 'public image',
|
||||
'metadata': {'key1': 'value1'},
|
||||
'updated': NOW_API_FORMAT,
|
||||
'created': NOW_API_FORMAT,
|
||||
'status': 'ACTIVE',
|
||||
'minDisk': 10,
|
||||
'progress': 100,
|
||||
'minRam': 128,
|
||||
'OS-EXT-IMG-SIZE:size': 25165824,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": f"{self.url_prefix}/{self.image_a_uuid}"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": f"{self.bookmark_prefix}/{self.image_a_uuid}"
|
||||
},
|
||||
{
|
||||
"rel": "alternate",
|
||||
"type": "application/vnd.openstack.image",
|
||||
"href": self.alternate % (
|
||||
glance.generate_glance_url('ctx'),
|
||||
self.image_a_uuid,
|
||||
),
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
self.expected_image_124 = {
|
||||
"image": {'id': '124',
|
||||
'name': 'queued snapshot',
|
||||
'metadata': {
|
||||
u'instance_uuid': self.server_uuid,
|
||||
u'user_id': u'fake',
|
||||
},
|
||||
'updated': NOW_API_FORMAT,
|
||||
'created': NOW_API_FORMAT,
|
||||
'status': 'SAVING',
|
||||
'progress': 25,
|
||||
'minDisk': 0,
|
||||
'minRam': 0,
|
||||
'OS-EXT-IMG-SIZE:size': 25165824,
|
||||
'server': {
|
||||
'id': self.server_uuid,
|
||||
"links": [{
|
||||
"rel": "self",
|
||||
"href": self.server_href,
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": self.server_bookmark,
|
||||
}],
|
||||
},
|
||||
"links": [{
|
||||
"rel": "self",
|
||||
"href": "%s/124" % self.url_prefix
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href":
|
||||
"%s/124" % self.bookmark_prefix
|
||||
},
|
||||
{
|
||||
"rel": "alternate",
|
||||
"type":
|
||||
"application/vnd.openstack.image",
|
||||
"href": self.alternate %
|
||||
(glance.generate_glance_url('ctx'),
|
||||
124),
|
||||
}],
|
||||
self.image_b_uuid = IMAGE_FIXTURES[1]['id']
|
||||
self.expected_image_b = {
|
||||
"image": {
|
||||
'id': self.image_b_uuid,
|
||||
'name': 'queued snapshot',
|
||||
'metadata': {
|
||||
'instance_uuid': self.server_uuid,
|
||||
'user_id': 'fake',
|
||||
},
|
||||
'updated': NOW_API_FORMAT,
|
||||
'created': NOW_API_FORMAT,
|
||||
'status': 'SAVING',
|
||||
'progress': 25,
|
||||
'minDisk': 0,
|
||||
'minRam': 0,
|
||||
'OS-EXT-IMG-SIZE:size': 25165824,
|
||||
'server': {
|
||||
'id': self.server_uuid,
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": self.server_href,
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": self.server_bookmark,
|
||||
}
|
||||
],
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": f"{self.url_prefix}/{self.image_b_uuid}"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": f"{self.bookmark_prefix}/{self.image_b_uuid}"
|
||||
},
|
||||
{
|
||||
"rel": "alternate",
|
||||
"type": "application/vnd.openstack.image",
|
||||
"href": self.alternate % (
|
||||
glance.generate_glance_url('ctx'),
|
||||
self.image_b_uuid,
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@mock.patch('nova.image.glance.API.get', return_value=IMAGE_FIXTURES[0])
|
||||
def test_get_image(self, get_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/123')
|
||||
actual_image = self.controller.show(request, '123')
|
||||
request = self.http_request.blank(
|
||||
self.url_base + f'images/{self.image_a_uuid}')
|
||||
actual_image = self.controller.show(request, self.image_a_uuid)
|
||||
self.assertThat(actual_image,
|
||||
matchers.DictMatches(self.expected_image_123))
|
||||
get_mocked.assert_called_once_with(mock.ANY, '123')
|
||||
matchers.DictMatches(self.expected_image_a))
|
||||
get_mocked.assert_called_once_with(mock.ANY, self.image_a_uuid)
|
||||
|
||||
@mock.patch('nova.image.glance.API.get', return_value=IMAGE_FIXTURES[1])
|
||||
def test_get_image_with_custom_prefix(self, _get_mocked):
|
||||
self.flags(compute_link_prefix='https://zoo.com:42',
|
||||
glance_link_prefix='http://circus.com:34',
|
||||
group='api')
|
||||
fake_req = self.http_request.blank(self.url_base + 'images/124')
|
||||
actual_image = self.controller.show(fake_req, '124')
|
||||
fake_req = self.http_request.blank(
|
||||
self.url_base + f'images/{self.image_b_uuid}')
|
||||
actual_image = self.controller.show(fake_req, self.image_b_uuid)
|
||||
|
||||
expected_image = self.expected_image_124
|
||||
expected_image = self.expected_image_b
|
||||
expected_image["image"]["links"][0]["href"] = (
|
||||
"https://zoo.com:42%s/images/124" % self.url_base)
|
||||
f"https://zoo.com:42{self.url_base}/images/{self.image_b_uuid}")
|
||||
expected_image["image"]["links"][1]["href"] = (
|
||||
"https://zoo.com:42%s/images/124" % self.bookmark_base)
|
||||
f"https://zoo.com:42{self.bookmark_base}/images/"
|
||||
f"{self.image_b_uuid}")
|
||||
expected_image["image"]["links"][2]["href"] = (
|
||||
"http://circus.com:34/images/124")
|
||||
f"http://circus.com:34/images/{self.image_b_uuid}")
|
||||
expected_image["image"]["server"]["links"][0]["href"] = (
|
||||
"https://zoo.com:42%s/servers/%s" % (self.url_base,
|
||||
self.server_uuid))
|
||||
@@ -190,82 +202,96 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
get_all_mocked.assert_called_once_with(mock.ANY, filters={})
|
||||
response_list = response["images"]
|
||||
|
||||
image_125 = copy.deepcopy(self.expected_image_124["image"])
|
||||
image_125['id'] = '125'
|
||||
image_125['name'] = 'saving snapshot'
|
||||
image_125['progress'] = 50
|
||||
image_125["links"][0]["href"] = "%s/125" % self.url_prefix
|
||||
image_125["links"][1]["href"] = "%s/125" % self.bookmark_prefix
|
||||
image_125["links"][2]["href"] = (
|
||||
"%s/images/125" % glance.generate_glance_url('ctx'))
|
||||
image_c = copy.deepcopy(self.expected_image_b["image"])
|
||||
image_c['id'] = IMAGE_FIXTURES[2]['id']
|
||||
image_c['name'] = 'saving snapshot'
|
||||
image_c['progress'] = 50
|
||||
image_c["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[2]['id'])
|
||||
image_c["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[2]['id'])
|
||||
image_c["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[2]['id'])
|
||||
|
||||
image_126 = copy.deepcopy(self.expected_image_124["image"])
|
||||
image_126['id'] = '126'
|
||||
image_126['name'] = 'active snapshot'
|
||||
image_126['status'] = 'ACTIVE'
|
||||
image_126['progress'] = 100
|
||||
image_126["links"][0]["href"] = "%s/126" % self.url_prefix
|
||||
image_126["links"][1]["href"] = "%s/126" % self.bookmark_prefix
|
||||
image_126["links"][2]["href"] = (
|
||||
"%s/images/126" % glance.generate_glance_url('ctx'))
|
||||
image_d = copy.deepcopy(self.expected_image_b["image"])
|
||||
image_d['id'] = IMAGE_FIXTURES[3]['id']
|
||||
image_d['name'] = 'active snapshot'
|
||||
image_d['status'] = 'ACTIVE'
|
||||
image_d['progress'] = 100
|
||||
image_d["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[3]['id'])
|
||||
image_d["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[3]['id'])
|
||||
image_d["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[3]['id'])
|
||||
|
||||
image_127 = copy.deepcopy(self.expected_image_124["image"])
|
||||
image_127['id'] = '127'
|
||||
image_127['name'] = 'killed snapshot'
|
||||
image_127['status'] = 'ERROR'
|
||||
image_127['progress'] = 0
|
||||
image_127["links"][0]["href"] = "%s/127" % self.url_prefix
|
||||
image_127["links"][1]["href"] = "%s/127" % self.bookmark_prefix
|
||||
image_127["links"][2]["href"] = (
|
||||
"%s/images/127" % glance.generate_glance_url('ctx'))
|
||||
image_e = copy.deepcopy(self.expected_image_b["image"])
|
||||
image_e['id'] = IMAGE_FIXTURES[4]['id']
|
||||
image_e['name'] = 'killed snapshot'
|
||||
image_e['status'] = 'ERROR'
|
||||
image_e['progress'] = 0
|
||||
image_e["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[4]['id'])
|
||||
image_e["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[4]['id'])
|
||||
image_e["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[4]['id'])
|
||||
|
||||
image_128 = copy.deepcopy(self.expected_image_124["image"])
|
||||
image_128['id'] = '128'
|
||||
image_128['name'] = 'deleted snapshot'
|
||||
image_128['status'] = 'DELETED'
|
||||
image_128['progress'] = 0
|
||||
image_128["links"][0]["href"] = "%s/128" % self.url_prefix
|
||||
image_128["links"][1]["href"] = "%s/128" % self.bookmark_prefix
|
||||
image_128["links"][2]["href"] = (
|
||||
"%s/images/128" % glance.generate_glance_url('ctx'))
|
||||
image_f = copy.deepcopy(self.expected_image_b["image"])
|
||||
image_f['id'] = IMAGE_FIXTURES[5]['id']
|
||||
image_f['name'] = 'deleted snapshot'
|
||||
image_f['status'] = 'DELETED'
|
||||
image_f['progress'] = 0
|
||||
image_f["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[5]['id'])
|
||||
image_f["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[5]['id'])
|
||||
image_f["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[5]['id'])
|
||||
|
||||
image_129 = copy.deepcopy(self.expected_image_124["image"])
|
||||
image_129['id'] = '129'
|
||||
image_129['name'] = 'pending_delete snapshot'
|
||||
image_129['status'] = 'DELETED'
|
||||
image_129['progress'] = 0
|
||||
image_129["links"][0]["href"] = "%s/129" % self.url_prefix
|
||||
image_129["links"][1]["href"] = "%s/129" % self.bookmark_prefix
|
||||
image_129["links"][2]["href"] = (
|
||||
"%s/images/129" % glance.generate_glance_url('ctx'))
|
||||
image_g = copy.deepcopy(self.expected_image_b["image"])
|
||||
image_g['id'] = IMAGE_FIXTURES[6]['id']
|
||||
image_g['name'] = 'pending_delete snapshot'
|
||||
image_g['status'] = 'DELETED'
|
||||
image_g['progress'] = 0
|
||||
image_g["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[6]['id'])
|
||||
image_g["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[6]['id'])
|
||||
image_g["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[6]['id'])
|
||||
|
||||
image_130 = copy.deepcopy(self.expected_image_123["image"])
|
||||
image_130['id'] = '130'
|
||||
image_130['name'] = None
|
||||
image_130['metadata'] = {}
|
||||
image_130['minDisk'] = 0
|
||||
image_130['minRam'] = 0
|
||||
image_130["links"][0]["href"] = "%s/130" % self.url_prefix
|
||||
image_130["links"][1]["href"] = "%s/130" % self.bookmark_prefix
|
||||
image_130["links"][2]["href"] = (
|
||||
"%s/images/130" % glance.generate_glance_url('ctx'))
|
||||
image_h = copy.deepcopy(self.expected_image_a["image"])
|
||||
image_h['id'] = IMAGE_FIXTURES[7]['id']
|
||||
image_h['name'] = None
|
||||
image_h['metadata'] = {}
|
||||
image_h['minDisk'] = 0
|
||||
image_h['minRam'] = 0
|
||||
image_h["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[7]['id'])
|
||||
image_h["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[7]['id'])
|
||||
image_h["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[7]['id'])
|
||||
|
||||
image_131 = copy.deepcopy(self.expected_image_123["image"])
|
||||
image_131['id'] = '131'
|
||||
image_131['name'] = None
|
||||
image_131['metadata'] = {}
|
||||
image_131['minDisk'] = 0
|
||||
image_131['minRam'] = 0
|
||||
image_131["links"][0]["href"] = "%s/131" % self.url_prefix
|
||||
image_131["links"][1]["href"] = "%s/131" % self.bookmark_prefix
|
||||
image_131["links"][2]["href"] = (
|
||||
"%s/images/131" % glance.generate_glance_url('ctx'))
|
||||
image_i = copy.deepcopy(self.expected_image_a["image"])
|
||||
image_i['id'] = IMAGE_FIXTURES[8]['id']
|
||||
image_i['name'] = None
|
||||
image_i['metadata'] = {}
|
||||
image_i['minDisk'] = 0
|
||||
image_i['minRam'] = 0
|
||||
image_i["links"][0]["href"] = "%s/%s" % (
|
||||
self.url_prefix, IMAGE_FIXTURES[8]['id'])
|
||||
image_i["links"][1]["href"] = "%s/%s" % (
|
||||
self.bookmark_prefix, IMAGE_FIXTURES[8]['id'])
|
||||
image_i["links"][2]["href"] = "%s/images/%s" % (
|
||||
glance.generate_glance_url('ctx'), IMAGE_FIXTURES[8]['id'])
|
||||
|
||||
expected = [self.expected_image_123["image"],
|
||||
self.expected_image_124["image"],
|
||||
image_125, image_126, image_127,
|
||||
image_128, image_129, image_130,
|
||||
image_131]
|
||||
expected = [self.expected_image_a["image"],
|
||||
self.expected_image_b["image"],
|
||||
image_c, image_d, image_e,
|
||||
image_f, image_g, image_h,
|
||||
image_i]
|
||||
|
||||
self.assertThat(expected, matchers.DictListMatches(response_list))
|
||||
|
||||
@@ -358,29 +384,37 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('nova.image.glance.API.delete')
|
||||
def test_delete_image(self, delete_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/124')
|
||||
request = self.http_request.blank(
|
||||
self.url_base + f'images/{self.image_a_uuid}')
|
||||
request.method = 'DELETE'
|
||||
delete_method = self.controller.delete
|
||||
delete_method(request, '124')
|
||||
delete_method(request, self.image_a_uuid)
|
||||
self.assertEqual(204, delete_method.wsgi_codes(request))
|
||||
delete_mocked.assert_called_once_with(mock.ANY, '124')
|
||||
delete_mocked.assert_called_once_with(mock.ANY, self.image_a_uuid)
|
||||
|
||||
@mock.patch('nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotAuthorized(image_id='123'))
|
||||
def test_delete_deleted_image(self, _delete_mocked):
|
||||
def test_delete_deleted_image(self):
|
||||
# If you try to delete a deleted image, you get back 403 Forbidden.
|
||||
request = self.http_request.blank(self.url_base + 'images/123')
|
||||
request = self.http_request.blank(
|
||||
self.url_base + f'images/{self.image_a_uuid}')
|
||||
request.method = 'DELETE'
|
||||
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
|
||||
request, '123')
|
||||
with mock.patch(
|
||||
'nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotAuthorized(
|
||||
image_id=self.image_a_uuid
|
||||
)
|
||||
):
|
||||
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
|
||||
request, self.image_a_uuid)
|
||||
|
||||
@mock.patch('nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotFound(image_id='123'))
|
||||
def test_delete_image_not_found(self, _delete_mocked):
|
||||
def test_delete_image_not_found(self):
|
||||
request = self.http_request.blank(self.url_base + 'images/300')
|
||||
request.method = 'DELETE'
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.delete, request, '300')
|
||||
with mock.patch(
|
||||
'nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotFound(image_id='300')
|
||||
):
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.delete, request, '300')
|
||||
|
||||
@mock.patch('nova.image.glance.API.get_all',
|
||||
return_value=[IMAGE_FIXTURES[0]])
|
||||
|
@@ -12,6 +12,8 @@
|
||||
|
||||
import datetime
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
# nova.image.glance._translate_from_glance() returns datetime
|
||||
# objects, not strings.
|
||||
NOW_DATE = datetime.datetime(2010, 10, 11, 10, 30, 22)
|
||||
@@ -22,25 +24,22 @@ def get_image_fixtures():
|
||||
|
||||
Returns a set of dicts representing images/snapshots of varying statuses
|
||||
that would be returned from a call to
|
||||
`glanceclient.client.Client.images.list`. The IDs of the images returned
|
||||
start at 123 and go to 131, with the following brief summary of image
|
||||
attributes:
|
||||
`glanceclient.client.Client.images.list`. The IDs of the images are random,
|
||||
with the following brief summary of image attributes:
|
||||
|
||||
| ID Type Status Notes
|
||||
| # Type Status Notes
|
||||
| ----------------------------------------------------------
|
||||
| 123 Public image active
|
||||
| 124 Snapshot queued
|
||||
| 125 Snapshot saving
|
||||
| 126 Snapshot active
|
||||
| 127 Snapshot killed
|
||||
| 128 Snapshot deleted
|
||||
| 129 Snapshot pending_delete
|
||||
| 130 Public image active Has no name
|
||||
| 0 Public image active
|
||||
| 1 Snapshot queued
|
||||
| 2 Snapshot saving
|
||||
| 3 Snapshot active
|
||||
| 4 Snapshot killed
|
||||
| 5 Snapshot deleted
|
||||
| 6 Snapshot pending_delete
|
||||
| 7 Public image active Has no name
|
||||
|
||||
"""
|
||||
|
||||
image_id = 123
|
||||
|
||||
fixtures = []
|
||||
|
||||
def add_fixture(**kwargs):
|
||||
@@ -49,10 +48,10 @@ def get_image_fixtures():
|
||||
fixtures.append(kwargs)
|
||||
|
||||
# Public image
|
||||
image_id = uuidutils.generate_uuid()
|
||||
add_fixture(id=str(image_id), name='public image', is_public=True,
|
||||
status='active', properties={'key1': 'value1'},
|
||||
min_ram="128", min_disk="10", size=25165824)
|
||||
image_id += 1
|
||||
|
||||
# Snapshot for User 1
|
||||
uuid = 'aa640691-d1a7-4a67-9d3c-d35ee6b3cc74'
|
||||
@@ -62,17 +61,18 @@ def get_image_fixtures():
|
||||
deleted = False if status != 'deleted' else True
|
||||
deleted_at = NOW_DATE if deleted else None
|
||||
|
||||
image_id = uuidutils.generate_uuid()
|
||||
add_fixture(id=str(image_id), name='%s snapshot' % status,
|
||||
is_public=False, status=status,
|
||||
properties=snapshot_properties, size=25165824,
|
||||
deleted=deleted, deleted_at=deleted_at)
|
||||
image_id += 1
|
||||
|
||||
# Image without a name
|
||||
image_id = uuidutils.generate_uuid()
|
||||
add_fixture(id=str(image_id), is_public=True, status='active',
|
||||
properties={}, size=25165824)
|
||||
# Image for permission tests
|
||||
image_id += 1
|
||||
image_id = uuidutils.generate_uuid()
|
||||
add_fixture(id=str(image_id), is_public=True, status='active',
|
||||
properties={}, owner='authorized_fake', size=25165824)
|
||||
|
||||
|
Reference in New Issue
Block a user