Skip to content

Commit

Permalink
Added min_disk and min_ram properties to images
Browse files Browse the repository at this point in the history
Fixes LP Bug#849368

Change-Id: I3e17370537144d117d99af5fa5a21df830b7c7ed
  • Loading branch information
ameade committed Sep 20, 2011
1 parent ec4af4b commit 20b7c69
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 14 deletions.
1 change: 1 addition & 0 deletions Authors
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Adam Gandelman <[email protected]>
Alex Meade <[email protected]>
Andrey Brindeyev <[email protected]>
Brian Lamar <[email protected]>
Brian Waldon <[email protected]>
Expand Down
8 changes: 6 additions & 2 deletions bin/glance
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def get_image_filters_from_args(args):
return FAILURE

SUPPORTED_FILTERS = ['name', 'disk_format', 'container_format', 'status',
'size_min', 'size_max']
'min_ram', 'min_disk', 'size_min', 'size_max']
filters = {}
for (key, value) in fields.items():
if key not in SUPPORTED_FILTERS:
Expand All @@ -141,6 +141,8 @@ def print_image_formatted(client, image):
print "Size: %d" % int(image['size'])
print "Disk format: %s" % image['disk_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']:
print "Owner: %s" % image['owner']
if len(image['properties']) > 0:
Expand Down Expand Up @@ -216,6 +218,8 @@ EXAMPLES
'is_public': common_utils.bool_from_string(
fields.pop('is_public', False)),
'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')}

# Strip any args that are not supported
Expand Down Expand Up @@ -329,7 +333,7 @@ to spell field names correctly. :)"""
fields.pop(field)

base_image_fields = ['disk_format', 'container_format', 'name',
'location', 'owner']
'min_disk', 'min_ram', 'location', 'owner']
for field in base_image_fields:
fvalue = fields.pop(field, None)
if fvalue is not None:
Expand Down
26 changes: 26 additions & 0 deletions doc/source/glanceapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ JSON-encoded mapping in the following format::
'deleted_at': '',
'status': 'active',
'is_public': true,
'min_ram': 256,
'min_disk': 5,
'owner': null,
'properties': {'distro': 'Ubuntu 10.04 LTS'}},
...]}
Expand All @@ -95,6 +97,12 @@ JSON-encoded mapping in the following format::
The `is_public` field is a boolean indicating whether the image is
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
indicate the owner of the image

Expand Down Expand Up @@ -181,6 +189,8 @@ following shows an example of the HTTP headers returned from the above
x-image-meta-deleted_at
x-image-meta-status available
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-property-distro Ubuntu 10.04 LTS

Expand Down Expand Up @@ -241,6 +251,8 @@ returned from the above ``GET`` request::
x-image-meta-deleted_at
x-image-meta-status available
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-property-distro Ubuntu 10.04 LTS

Expand Down Expand Up @@ -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
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``

This header is optional and only meaningful for admins.
Expand Down
5 changes: 4 additions & 1 deletion glance/api/v1/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
logger = logging.getLogger('glance.api.v1.images')

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')

Expand Down Expand Up @@ -130,6 +131,8 @@ def detail(self, req):
'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM>,
'min_disk': <MIN_DISK>,
'min_ram': <MIN_RAM>,
'store': <STORE>,
'status': <STATUS>,
'created_at': <TIMESTAMP>,
Expand Down
10 changes: 8 additions & 2 deletions glance/registry/db/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@

IMAGE_ATTRS = BASE_MODEL_ATTRS | set(['name', 'status', 'size',
'disk_format', 'container_format',
'is_public', 'location', 'checksum',
'owner'])
'min_disk', 'min_ram', 'is_public',
'location', 'checksum', 'owner'])

CONTAINER_FORMATS = ['ami', 'ari', 'aki', 'bare', 'ovf']
DISK_FORMATS = ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi',
Expand Down Expand Up @@ -327,6 +327,12 @@ def _image_update(context, values, image_id, purge_props=False):
if 'size' in values:
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))
image_ref = models.Image()

Expand Down
Original file line number Diff line number Diff line change
@@ -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()
2 changes: 2 additions & 0 deletions glance/registry/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ class Image(BASE, ModelBase):
is_public = Column(Boolean, nullable=False, default=False)
location = Column(Text)
checksum = Column(String(32))
min_disk = Column(Integer(), default=0)
min_ram = Column(Integer(), default=0)
owner = Column(String(255))


Expand Down
2 changes: 1 addition & 1 deletion glance/registry/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
'checksum']

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',
'size', 'id', 'created_at', 'updated_at')
Expand Down
35 changes: 27 additions & 8 deletions glance/tests/functional/test_bin_glance.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,8 @@ def test_results_filtering(self):
_add_args = [
"name=Name1 disk_format=vhd container_format=ovf 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):
Expand Down Expand Up @@ -402,9 +403,27 @@ def test_results_filtering(self):

self.assertEqual(0, exitcode)
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[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()

Expand Down Expand Up @@ -483,9 +502,9 @@ def test_results_pagination(self):

self.assertEqual(0, exitcode)
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[10].startswith('Id: 1'))
self.assertTrue(image_lines[12].startswith('Id: 1'))

def test_results_sorting(self):
self.cleanup()
Expand Down Expand Up @@ -555,7 +574,7 @@ def test_results_sorting(self):

self.assertEqual(0, exitcode)
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[10].startswith('Id: 2'))
self.assertTrue(image_lines[19].startswith('Id: 5'))
self.assertTrue(image_lines[12].startswith('Id: 2'))
self.assertTrue(image_lines[23].startswith('Id: 5'))
Loading

0 comments on commit 20b7c69

Please sign in to comment.