Added min_disk and min_ram properties to images
Fixes LP Bug#849368 Change-Id: I3e17370537144d117d99af5fa5a21df830b7c7ed
This commit is contained in:
parent
ec4af4bea7
commit
20b7c69758
1
Authors
1
Authors
@ -1,4 +1,5 @@
|
|||||||
Adam Gandelman <adam.gandelman@canonical.com>
|
Adam Gandelman <adam.gandelman@canonical.com>
|
||||||
|
Alex Meade <alex.meade@rackspace.com>
|
||||||
Andrey Brindeyev <abrindeyev@griddynamics.com>
|
Andrey Brindeyev <abrindeyev@griddynamics.com>
|
||||||
Brian Lamar <brian.lamar@rackspace.com>
|
Brian Lamar <brian.lamar@rackspace.com>
|
||||||
Brian Waldon <brian.waldon@rackspace.com>
|
Brian Waldon <brian.waldon@rackspace.com>
|
||||||
|
@ -114,7 +114,7 @@ def get_image_filters_from_args(args):
|
|||||||
return FAILURE
|
return FAILURE
|
||||||
|
|
||||||
SUPPORTED_FILTERS = ['name', 'disk_format', 'container_format', 'status',
|
SUPPORTED_FILTERS = ['name', 'disk_format', 'container_format', 'status',
|
||||||
'size_min', 'size_max']
|
'min_ram', 'min_disk', 'size_min', 'size_max']
|
||||||
filters = {}
|
filters = {}
|
||||||
for (key, value) in fields.items():
|
for (key, value) in fields.items():
|
||||||
if key not in SUPPORTED_FILTERS:
|
if key not in SUPPORTED_FILTERS:
|
||||||
@ -141,6 +141,8 @@ def print_image_formatted(client, image):
|
|||||||
print "Size: %d" % int(image['size'])
|
print "Size: %d" % int(image['size'])
|
||||||
print "Disk format: %s" % image['disk_format']
|
print "Disk format: %s" % image['disk_format']
|
||||||
print "Container format: %s" % image['container_format']
|
print "Container format: %s" % image['container_format']
|
||||||
|
print "Minimum Ram Required (MB): %s" % image['min_ram']
|
||||||
|
print "Minimum Disk Required (GB): %s" % image['min_disk']
|
||||||
if image['owner']:
|
if image['owner']:
|
||||||
print "Owner: %s" % image['owner']
|
print "Owner: %s" % image['owner']
|
||||||
if len(image['properties']) > 0:
|
if len(image['properties']) > 0:
|
||||||
@ -216,6 +218,8 @@ EXAMPLES
|
|||||||
'is_public': common_utils.bool_from_string(
|
'is_public': common_utils.bool_from_string(
|
||||||
fields.pop('is_public', False)),
|
fields.pop('is_public', False)),
|
||||||
'disk_format': fields.pop('disk_format', 'raw'),
|
'disk_format': fields.pop('disk_format', 'raw'),
|
||||||
|
'min_disk': fields.pop('min_disk', 0),
|
||||||
|
'min_ram': fields.pop('min_ram', 0),
|
||||||
'container_format': fields.pop('container_format', 'ovf')}
|
'container_format': fields.pop('container_format', 'ovf')}
|
||||||
|
|
||||||
# Strip any args that are not supported
|
# Strip any args that are not supported
|
||||||
@ -329,7 +333,7 @@ to spell field names correctly. :)"""
|
|||||||
fields.pop(field)
|
fields.pop(field)
|
||||||
|
|
||||||
base_image_fields = ['disk_format', 'container_format', 'name',
|
base_image_fields = ['disk_format', 'container_format', 'name',
|
||||||
'location', 'owner']
|
'min_disk', 'min_ram', 'location', 'owner']
|
||||||
for field in base_image_fields:
|
for field in base_image_fields:
|
||||||
fvalue = fields.pop(field, None)
|
fvalue = fields.pop(field, None)
|
||||||
if fvalue is not None:
|
if fvalue is not None:
|
||||||
|
@ -73,6 +73,8 @@ JSON-encoded mapping in the following format::
|
|||||||
'deleted_at': '',
|
'deleted_at': '',
|
||||||
'status': 'active',
|
'status': 'active',
|
||||||
'is_public': true,
|
'is_public': true,
|
||||||
|
'min_ram': 256,
|
||||||
|
'min_disk': 5,
|
||||||
'owner': null,
|
'owner': null,
|
||||||
'properties': {'distro': 'Ubuntu 10.04 LTS'}},
|
'properties': {'distro': 'Ubuntu 10.04 LTS'}},
|
||||||
...]}
|
...]}
|
||||||
@ -95,6 +97,12 @@ JSON-encoded mapping in the following format::
|
|||||||
The `is_public` field is a boolean indicating whether the image is
|
The `is_public` field is a boolean indicating whether the image is
|
||||||
publically available
|
publically available
|
||||||
|
|
||||||
|
The 'min_ram' field is an integer specifying the minimum amount of
|
||||||
|
ram needed to run this image on an instance, in megabytes
|
||||||
|
|
||||||
|
The 'min_disk' field is an integer specifying the minimum amount of
|
||||||
|
disk space needed to run this image on an instance, in gigabytes
|
||||||
|
|
||||||
The `owner` field is a string which may either be null or which will
|
The `owner` field is a string which may either be null or which will
|
||||||
indicate the owner of the image
|
indicate the owner of the image
|
||||||
|
|
||||||
@ -181,6 +189,8 @@ following shows an example of the HTTP headers returned from the above
|
|||||||
x-image-meta-deleted_at
|
x-image-meta-deleted_at
|
||||||
x-image-meta-status available
|
x-image-meta-status available
|
||||||
x-image-meta-is-public true
|
x-image-meta-is-public true
|
||||||
|
x-image-meta-min-ram 256
|
||||||
|
x-image-meta-min-disk 0
|
||||||
x-image-meta-owner null
|
x-image-meta-owner null
|
||||||
x-image-meta-property-distro Ubuntu 10.04 LTS
|
x-image-meta-property-distro Ubuntu 10.04 LTS
|
||||||
|
|
||||||
@ -241,6 +251,8 @@ returned from the above ``GET`` request::
|
|||||||
x-image-meta-deleted_at
|
x-image-meta-deleted_at
|
||||||
x-image-meta-status available
|
x-image-meta-status available
|
||||||
x-image-meta-is-public true
|
x-image-meta-is-public true
|
||||||
|
x-image-meta-min-ram 256
|
||||||
|
x-image-meta-min-disk 5
|
||||||
x-image-meta-owner null
|
x-image-meta-owner null
|
||||||
x-image-meta-property-distro Ubuntu 10.04 LTS
|
x-image-meta-property-distro Ubuntu 10.04 LTS
|
||||||
|
|
||||||
@ -383,6 +395,20 @@ The list of metadata headers that Glance accepts are listed below.
|
|||||||
When not present, the image is assumed to be *not public* and specific to
|
When not present, the image is assumed to be *not public* and specific to
|
||||||
a user.
|
a user.
|
||||||
|
|
||||||
|
* ``x-image-meta-min-ram``
|
||||||
|
|
||||||
|
This header is optional. When present it shall be the expected minimum ram
|
||||||
|
required in megabytes to run this image on a server.
|
||||||
|
|
||||||
|
When not present, the image is assumed to have a minimum ram requirement of 0.
|
||||||
|
|
||||||
|
* ``x-image-meta-min-disk``
|
||||||
|
|
||||||
|
This header is optional. When present it shall be the expected minimum disk
|
||||||
|
space required in gigabytes to run this image on a server.
|
||||||
|
|
||||||
|
When not present, the image is assumed to have a minimum disk space requirement of 0.
|
||||||
|
|
||||||
* ``x-image-meta-owner``
|
* ``x-image-meta-owner``
|
||||||
|
|
||||||
This header is optional and only meaningful for admins.
|
This header is optional and only meaningful for admins.
|
||||||
|
@ -55,7 +55,8 @@ from glance import utils
|
|||||||
logger = logging.getLogger('glance.api.v1.images')
|
logger = logging.getLogger('glance.api.v1.images')
|
||||||
|
|
||||||
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
|
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
|
||||||
'size_min', 'size_max', 'is_public']
|
'min_ram', 'min_disk', 'size_min', 'size_max',
|
||||||
|
'is_public']
|
||||||
|
|
||||||
SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
|
SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
|
||||||
|
|
||||||
@ -130,6 +131,8 @@ class Controller(api.BaseController):
|
|||||||
'disk_format': <DISK_FORMAT>,
|
'disk_format': <DISK_FORMAT>,
|
||||||
'container_format': <CONTAINER_FORMAT>,
|
'container_format': <CONTAINER_FORMAT>,
|
||||||
'checksum': <CHECKSUM>,
|
'checksum': <CHECKSUM>,
|
||||||
|
'min_disk': <MIN_DISK>,
|
||||||
|
'min_ram': <MIN_RAM>,
|
||||||
'store': <STORE>,
|
'store': <STORE>,
|
||||||
'status': <STATUS>,
|
'status': <STATUS>,
|
||||||
'created_at': <TIMESTAMP>,
|
'created_at': <TIMESTAMP>,
|
||||||
|
@ -47,8 +47,8 @@ BASE_MODEL_ATTRS = set(['id', 'created_at', 'updated_at', 'deleted_at',
|
|||||||
|
|
||||||
IMAGE_ATTRS = BASE_MODEL_ATTRS | set(['name', 'status', 'size',
|
IMAGE_ATTRS = BASE_MODEL_ATTRS | set(['name', 'status', 'size',
|
||||||
'disk_format', 'container_format',
|
'disk_format', 'container_format',
|
||||||
'is_public', 'location', 'checksum',
|
'min_disk', 'min_ram', 'is_public',
|
||||||
'owner'])
|
'location', 'checksum', 'owner'])
|
||||||
|
|
||||||
CONTAINER_FORMATS = ['ami', 'ari', 'aki', 'bare', 'ovf']
|
CONTAINER_FORMATS = ['ami', 'ari', 'aki', 'bare', 'ovf']
|
||||||
DISK_FORMATS = ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi',
|
DISK_FORMATS = ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi',
|
||||||
@ -327,6 +327,12 @@ def _image_update(context, values, image_id, purge_props=False):
|
|||||||
if 'size' in values:
|
if 'size' in values:
|
||||||
values['size'] = int(values['size'])
|
values['size'] = int(values['size'])
|
||||||
|
|
||||||
|
if 'min_ram' in values:
|
||||||
|
values['min_ram'] = int(values['min_ram'])
|
||||||
|
|
||||||
|
if 'min_disk' in values:
|
||||||
|
values['min_disk'] = int(values['min_disk'])
|
||||||
|
|
||||||
values['is_public'] = bool(values.get('is_public', False))
|
values['is_public'] = bool(values.get('is_public', False))
|
||||||
image_ref = models.Image()
|
image_ref = models.Image()
|
||||||
|
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2011 OpenStack LLC.
|
||||||
|
# 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 migrate.changeset import *
|
||||||
|
from sqlalchemy import *
|
||||||
|
from sqlalchemy.sql import and_, not_
|
||||||
|
|
||||||
|
from glance.registry.db.migrate_repo.schema import (
|
||||||
|
Boolean, DateTime, Integer, String, Text, from_migration_import)
|
||||||
|
|
||||||
|
|
||||||
|
def get_images_table(meta):
|
||||||
|
"""
|
||||||
|
Returns the Table object for the images table that
|
||||||
|
corresponds to the images table definition of this version.
|
||||||
|
"""
|
||||||
|
images = Table('images', meta,
|
||||||
|
Column('id', Integer(), primary_key=True, nullable=False),
|
||||||
|
Column('name', String(255)),
|
||||||
|
Column('disk_format', String(20)),
|
||||||
|
Column('container_format', String(20)),
|
||||||
|
Column('size', Integer()),
|
||||||
|
Column('status', String(30), nullable=False),
|
||||||
|
Column('is_public', Boolean(), nullable=False, default=False,
|
||||||
|
index=True),
|
||||||
|
Column('location', Text()),
|
||||||
|
Column('created_at', DateTime(), nullable=False),
|
||||||
|
Column('updated_at', DateTime()),
|
||||||
|
Column('deleted_at', DateTime()),
|
||||||
|
Column('deleted', Boolean(), nullable=False, default=False,
|
||||||
|
index=True),
|
||||||
|
Column('checksum', String(32)),
|
||||||
|
Column('min_disk', Integer(), default=0),
|
||||||
|
Column('min_ram', Integer(), default=0),
|
||||||
|
mysql_engine='InnoDB',
|
||||||
|
useexisting=True)
|
||||||
|
|
||||||
|
return images
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_properties_table(meta):
|
||||||
|
"""
|
||||||
|
No changes to the image properties table from 008...
|
||||||
|
"""
|
||||||
|
(define_image_properties_table,) = from_migration_import(
|
||||||
|
'008_add_image_members_table', ['define_image_properties_table'])
|
||||||
|
|
||||||
|
image_properties = define_image_properties_table(meta)
|
||||||
|
return image_properties
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
meta = MetaData()
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
|
||||||
|
images = get_images_table(meta)
|
||||||
|
|
||||||
|
min_disk = Column('min_disk', Integer(), default=0)
|
||||||
|
min_disk.create(images)
|
||||||
|
|
||||||
|
min_ram = Column('min_ram', Integer(), default=0)
|
||||||
|
min_ram.create(images)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(migrate_engine):
|
||||||
|
meta = MetaData()
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
|
||||||
|
images = get_images_table(meta)
|
||||||
|
|
||||||
|
images.columns['min_disk'].drop()
|
||||||
|
images.columns['min_ram'].drop()
|
@ -105,6 +105,8 @@ class Image(BASE, ModelBase):
|
|||||||
is_public = Column(Boolean, nullable=False, default=False)
|
is_public = Column(Boolean, nullable=False, default=False)
|
||||||
location = Column(Text)
|
location = Column(Text)
|
||||||
checksum = Column(String(32))
|
checksum = Column(String(32))
|
||||||
|
min_disk = Column(Integer(), default=0)
|
||||||
|
min_ram = Column(Integer(), default=0)
|
||||||
owner = Column(String(255))
|
owner = Column(String(255))
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ DISPLAY_FIELDS_IN_INDEX = ['id', 'name', 'size',
|
|||||||
'checksum']
|
'checksum']
|
||||||
|
|
||||||
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
|
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
|
||||||
'size_min', 'size_max']
|
'min_ram', 'min_disk', 'size_min', 'size_max']
|
||||||
|
|
||||||
SUPPORTED_SORT_KEYS = ('name', 'status', 'container_format', 'disk_format',
|
SUPPORTED_SORT_KEYS = ('name', 'status', 'container_format', 'disk_format',
|
||||||
'size', 'id', 'created_at', 'updated_at')
|
'size', 'id', 'created_at', 'updated_at')
|
||||||
|
@ -318,7 +318,8 @@ class TestBinGlance(functional.FunctionalTest):
|
|||||||
_add_args = [
|
_add_args = [
|
||||||
"name=Name1 disk_format=vhd container_format=ovf foo=bar",
|
"name=Name1 disk_format=vhd container_format=ovf foo=bar",
|
||||||
"name=Name2 disk_format=ami container_format=ami foo=bar",
|
"name=Name2 disk_format=ami container_format=ami foo=bar",
|
||||||
"name=Name3 disk_format=vhd container_format=ovf foo=baz",
|
"name=Name3 disk_format=vhd container_format=ovf foo=baz "
|
||||||
|
"min_disk=7 min_ram=256",
|
||||||
]
|
]
|
||||||
|
|
||||||
for i, args in enumerate(_add_args):
|
for i, args in enumerate(_add_args):
|
||||||
@ -402,9 +403,27 @@ class TestBinGlance(functional.FunctionalTest):
|
|||||||
|
|
||||||
self.assertEqual(0, exitcode)
|
self.assertEqual(0, exitcode)
|
||||||
image_lines = out.split("\n")[1:-1]
|
image_lines = out.split("\n")[1:-1]
|
||||||
self.assertEqual(20, len(image_lines))
|
self.assertEqual(24, len(image_lines))
|
||||||
self.assertTrue(image_lines[1].startswith('Id: 2'))
|
self.assertTrue(image_lines[1].startswith('Id: 2'))
|
||||||
self.assertTrue(image_lines[11].startswith('Id: 1'))
|
self.assertTrue(image_lines[13].startswith('Id: 1'))
|
||||||
|
|
||||||
|
# 10. Check min_ram filter
|
||||||
|
cmd = "min_ram=256"
|
||||||
|
exitcode, out, err = execute("%s %s" % (_details_cmd, cmd))
|
||||||
|
|
||||||
|
self.assertEqual(0, exitcode)
|
||||||
|
image_lines = out.split("\n")[2:-1]
|
||||||
|
self.assertEqual(11, len(image_lines))
|
||||||
|
self.assertTrue(image_lines[0].startswith('Id: 3'))
|
||||||
|
|
||||||
|
# 11. Check min_disk filter
|
||||||
|
cmd = "min_disk=7"
|
||||||
|
exitcode, out, err = execute("%s %s" % (_details_cmd, cmd))
|
||||||
|
|
||||||
|
self.assertEqual(0, exitcode)
|
||||||
|
image_lines = out.split("\n")[2:-1]
|
||||||
|
self.assertEqual(11, len(image_lines))
|
||||||
|
self.assertTrue(image_lines[0].startswith('Id: 3'))
|
||||||
|
|
||||||
self.stop_servers()
|
self.stop_servers()
|
||||||
|
|
||||||
@ -483,9 +502,9 @@ class TestBinGlance(functional.FunctionalTest):
|
|||||||
|
|
||||||
self.assertEqual(0, exitcode)
|
self.assertEqual(0, exitcode)
|
||||||
image_lines = out.split("\n")[1:-1]
|
image_lines = out.split("\n")[1:-1]
|
||||||
self.assertEqual(18, len(image_lines))
|
self.assertEqual(22, len(image_lines))
|
||||||
self.assertTrue(image_lines[1].startswith('Id: 3'))
|
self.assertTrue(image_lines[1].startswith('Id: 3'))
|
||||||
self.assertTrue(image_lines[10].startswith('Id: 1'))
|
self.assertTrue(image_lines[12].startswith('Id: 1'))
|
||||||
|
|
||||||
def test_results_sorting(self):
|
def test_results_sorting(self):
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
@ -555,7 +574,7 @@ class TestBinGlance(functional.FunctionalTest):
|
|||||||
|
|
||||||
self.assertEqual(0, exitcode)
|
self.assertEqual(0, exitcode)
|
||||||
image_lines = out.split("\n")[1:-1]
|
image_lines = out.split("\n")[1:-1]
|
||||||
self.assertEqual(27, len(image_lines))
|
self.assertEqual(33, len(image_lines))
|
||||||
self.assertTrue(image_lines[1].startswith('Id: 3'))
|
self.assertTrue(image_lines[1].startswith('Id: 3'))
|
||||||
self.assertTrue(image_lines[10].startswith('Id: 2'))
|
self.assertTrue(image_lines[12].startswith('Id: 2'))
|
||||||
self.assertTrue(image_lines[19].startswith('Id: 5'))
|
self.assertTrue(image_lines[23].startswith('Id: 5'))
|
||||||
|
@ -62,6 +62,8 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
'deleted_at': None,
|
'deleted_at': None,
|
||||||
'deleted': False,
|
'deleted': False,
|
||||||
'checksum': None,
|
'checksum': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'min_ram': 0,
|
||||||
'size': 13,
|
'size': 13,
|
||||||
'location': "swift://user:passwd@acct/container/obj.tar.0",
|
'location': "swift://user:passwd@acct/container/obj.tar.0",
|
||||||
'properties': {'type': 'kernel'}},
|
'properties': {'type': 'kernel'}},
|
||||||
@ -76,6 +78,8 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
'deleted_at': None,
|
'deleted_at': None,
|
||||||
'deleted': False,
|
'deleted': False,
|
||||||
'checksum': None,
|
'checksum': None,
|
||||||
|
'min_disk': 5,
|
||||||
|
'min_ram': 256,
|
||||||
'size': 19,
|
'size': 19,
|
||||||
'location': "file:///tmp/glance-tests/2",
|
'location': "file:///tmp/glance-tests/2",
|
||||||
'properties': {}}]
|
'properties': {}}]
|
||||||
@ -107,6 +111,8 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
fixture = {'id': 2,
|
fixture = {'id': 2,
|
||||||
'name': 'fake image #2',
|
'name': 'fake image #2',
|
||||||
'size': 19,
|
'size': 19,
|
||||||
|
'min_ram': 256,
|
||||||
|
'min_disk': 5,
|
||||||
'checksum': None}
|
'checksum': None}
|
||||||
req = webob.Request.blank('/images/2')
|
req = webob.Request.blank('/images/2')
|
||||||
res = req.get_response(self.api)
|
res = req.get_response(self.api)
|
||||||
@ -779,6 +785,8 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
'name': 'fake image #2',
|
'name': 'fake image #2',
|
||||||
'is_public': True,
|
'is_public': True,
|
||||||
'size': 19,
|
'size': 19,
|
||||||
|
'min_disk': 5,
|
||||||
|
'min_ram': 256,
|
||||||
'checksum': None,
|
'checksum': None,
|
||||||
'disk_format': 'vhd',
|
'disk_format': 'vhd',
|
||||||
'container_format': 'ovf',
|
'container_format': 'ovf',
|
||||||
@ -958,6 +966,84 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
for image in images:
|
for image in images:
|
||||||
self.assertEqual('ovf', image['container_format'])
|
self.assertEqual('ovf', image['container_format'])
|
||||||
|
|
||||||
|
def test_get_details_filter_min_disk(self):
|
||||||
|
"""
|
||||||
|
Tests that the /images/detail registry API returns list of
|
||||||
|
public images that have a specific min_disk
|
||||||
|
"""
|
||||||
|
extra_fixture = {'id': 3,
|
||||||
|
'status': 'active',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf',
|
||||||
|
'name': 'fake image #3',
|
||||||
|
'size': 19,
|
||||||
|
'min_disk': 7,
|
||||||
|
'checksum': None}
|
||||||
|
|
||||||
|
db_api.image_create(self.context, extra_fixture)
|
||||||
|
|
||||||
|
extra_fixture = {'id': 4,
|
||||||
|
'status': 'active',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'ami',
|
||||||
|
'container_format': 'ami',
|
||||||
|
'name': 'fake image #4',
|
||||||
|
'size': 19,
|
||||||
|
'checksum': None}
|
||||||
|
|
||||||
|
db_api.image_create(self.context, extra_fixture)
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images/detail?min_disk=7')
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
images = res_dict['images']
|
||||||
|
self.assertEquals(len(images), 1)
|
||||||
|
|
||||||
|
for image in images:
|
||||||
|
self.assertEqual(7, image['min_disk'])
|
||||||
|
|
||||||
|
def test_get_details_filter_min_ram(self):
|
||||||
|
"""
|
||||||
|
Tests that the /images/detail registry API returns list of
|
||||||
|
public images that have a specific min_ram
|
||||||
|
"""
|
||||||
|
extra_fixture = {'id': 3,
|
||||||
|
'status': 'active',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf',
|
||||||
|
'name': 'fake image #3',
|
||||||
|
'size': 19,
|
||||||
|
'min_ram': 514,
|
||||||
|
'checksum': None}
|
||||||
|
|
||||||
|
db_api.image_create(self.context, extra_fixture)
|
||||||
|
|
||||||
|
extra_fixture = {'id': 4,
|
||||||
|
'status': 'active',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'ami',
|
||||||
|
'container_format': 'ami',
|
||||||
|
'name': 'fake image #4',
|
||||||
|
'size': 19,
|
||||||
|
'checksum': None}
|
||||||
|
|
||||||
|
db_api.image_create(self.context, extra_fixture)
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images/detail?min_ram=514')
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
images = res_dict['images']
|
||||||
|
self.assertEquals(len(images), 1)
|
||||||
|
|
||||||
|
for image in images:
|
||||||
|
self.assertEqual(514, image['min_ram'])
|
||||||
|
|
||||||
def test_get_details_filter_disk_format(self):
|
def test_get_details_filter_disk_format(self):
|
||||||
"""
|
"""
|
||||||
Tests that the /images/detail registry API returns list of
|
Tests that the /images/detail registry API returns list of
|
||||||
@ -1307,6 +1393,92 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
# Test status was updated properly
|
# Test status was updated properly
|
||||||
self.assertEquals('active', res_dict['image']['status'])
|
self.assertEquals('active', res_dict['image']['status'])
|
||||||
|
|
||||||
|
def test_create_image_with_min_disk(self):
|
||||||
|
"""Tests that the /images POST registry API creates the image"""
|
||||||
|
fixture = {'name': 'fake public image',
|
||||||
|
'is_public': True,
|
||||||
|
'min_disk': 5,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf'}
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images')
|
||||||
|
|
||||||
|
req.method = 'POST'
|
||||||
|
req.content_type = 'application/json'
|
||||||
|
req.body = json.dumps(dict(image=fixture))
|
||||||
|
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
|
||||||
|
self.assertEquals(5, res_dict['image']['min_disk'])
|
||||||
|
|
||||||
|
def test_create_image_with_min_ram(self):
|
||||||
|
"""Tests that the /images POST registry API creates the image"""
|
||||||
|
fixture = {'name': 'fake public image',
|
||||||
|
'is_public': True,
|
||||||
|
'min_ram': 256,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf'}
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images')
|
||||||
|
|
||||||
|
req.method = 'POST'
|
||||||
|
req.content_type = 'application/json'
|
||||||
|
req.body = json.dumps(dict(image=fixture))
|
||||||
|
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
|
||||||
|
self.assertEquals(256, res_dict['image']['min_ram'])
|
||||||
|
|
||||||
|
def test_create_image_with_min_ram_default(self):
|
||||||
|
"""Tests that the /images POST registry API creates the image"""
|
||||||
|
fixture = {'name': 'fake public image',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf'}
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images')
|
||||||
|
|
||||||
|
req.method = 'POST'
|
||||||
|
req.content_type = 'application/json'
|
||||||
|
req.body = json.dumps(dict(image=fixture))
|
||||||
|
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
|
||||||
|
self.assertEquals(0, res_dict['image']['min_ram'])
|
||||||
|
|
||||||
|
def test_create_image_with_min_disk_default(self):
|
||||||
|
"""Tests that the /images POST registry API creates the image"""
|
||||||
|
fixture = {'name': 'fake public image',
|
||||||
|
'is_public': True,
|
||||||
|
'disk_format': 'vhd',
|
||||||
|
'container_format': 'ovf'}
|
||||||
|
|
||||||
|
req = webob.Request.blank('/images')
|
||||||
|
|
||||||
|
req.method = 'POST'
|
||||||
|
req.content_type = 'application/json'
|
||||||
|
req.body = json.dumps(dict(image=fixture))
|
||||||
|
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
|
||||||
|
self.assertEquals(res.status_int, 200)
|
||||||
|
|
||||||
|
res_dict = json.loads(res.body)
|
||||||
|
|
||||||
|
self.assertEquals(0, res_dict['image']['min_disk'])
|
||||||
|
|
||||||
def test_create_image_with_bad_container_format(self):
|
def test_create_image_with_bad_container_format(self):
|
||||||
"""Tests proper exception is raised if a bad disk_format is set"""
|
"""Tests proper exception is raised if a bad disk_format is set"""
|
||||||
fixture = {'id': 3,
|
fixture = {'id': 3,
|
||||||
@ -1385,6 +1557,8 @@ class TestRegistryAPI(unittest.TestCase):
|
|||||||
def test_update_image(self):
|
def test_update_image(self):
|
||||||
"""Tests that the /images PUT registry API updates the image"""
|
"""Tests that the /images PUT registry API updates the image"""
|
||||||
fixture = {'name': 'fake public image #2',
|
fixture = {'name': 'fake public image #2',
|
||||||
|
'min_disk': 5,
|
||||||
|
'min_ram': 256,
|
||||||
'disk_format': 'raw'}
|
'disk_format': 'raw'}
|
||||||
|
|
||||||
req = webob.Request.blank('/images/2')
|
req = webob.Request.blank('/images/2')
|
||||||
|
Loading…
Reference in New Issue
Block a user