Merge changes.

Update tests. New image indexes relative to existing indexes.
This commit is contained in:
Donal Lafferty 2011-05-19 09:23:41 +01:00
commit 593fa8e523
9 changed files with 856 additions and 34 deletions

View File

@ -42,6 +42,9 @@ from glance import utils
logger = logging.getLogger('glance.api.v1.images')
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
'size_min', 'size_max']
class Controller(wsgi.Controller):
@ -89,7 +92,8 @@ class Controller(wsgi.Controller):
'size': <SIZE>}, ...
]}
"""
images = registry.get_images_list(self.options)
filters = self._get_filters(req)
images = registry.get_images_list(self.options, filters)
return dict(images=images)
def detail(self, req):
@ -114,9 +118,24 @@ class Controller(wsgi.Controller):
'properties': {'distro': 'Ubuntu 10.04 LTS', ...}}, ...
]}
"""
images = registry.get_images_detail(self.options)
filters = self._get_filters(req)
images = registry.get_images_detail(self.options, filters)
return dict(images=images)
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
"""
filters = {}
for param in req.str_params:
if param in SUPPORTED_FILTERS or param.startswith('property-'):
filters[param] = req.str_params.get(param)
return filters
def meta(self, req, id):
"""
Returns metadata about an image in the HTTP headers of the

View File

@ -32,14 +32,14 @@ def get_registry_client(options):
return client.RegistryClient(host, port)
def get_images_list(options):
def get_images_list(options, filters):
c = get_registry_client(options)
return c.get_images()
return c.get_images(filters)
def get_images_detail(options):
def get_images_detail(options, filters):
c = get_registry_client(options)
return c.get_images_detailed()
return c.get_images_detailed(filters)
def get_image_metadata(options, image_id):

View File

@ -20,14 +20,9 @@ Simple client class to speak with any RESTful service that implements
the Glance Registry API
"""
import httplib
import json
import logging
import urlparse
import socket
import sys
import urllib
from glance.common import exception
from glance.client import BaseClient
@ -49,28 +44,34 @@ class RegistryClient(BaseClient):
port = port or self.DEFAULT_PORT
super(RegistryClient, self).__init__(host, port, use_ssl)
def get_images(self):
def get_images(self, filters=None):
"""
Returns a list of image id/name mappings from Registry
"""
res = self.do_request("GET", "/images")
if filters != None:
action = "/images?%s" % urllib.urlencode(filters)
else:
action = "/images"
res = self.do_request("GET", action)
data = json.loads(res.read())['images']
return data
def get_images_detailed(self):
def get_images_detailed(self, filters=None):
"""
Returns a list of detailed image data mappings from Registry
"""
res = self.do_request("GET", "/images/detail")
if filters != None:
action = "/images/detail?%s" % urllib.urlencode(filters)
else:
action = "/images/detail"
res = self.do_request("GET", action)
data = json.loads(res.read())['images']
return data
def get_image(self, image_id):
"""
Returns a mapping of image metadata from Registry
:raises exception.NotFound if image is not in registry
"""
"""Returns a mapping of image metadata from Registry"""
res = self.do_request("GET", "/images/%s" % image_id)
data = json.loads(res.read())['image']
return data

View File

@ -140,15 +140,39 @@ def image_get(context, image_id, session=None):
raise exception.NotFound("No image found with ID %s" % image_id)
def image_get_all_public(context):
"""Get all public images."""
def image_get_all_public(context, filters=None):
"""Get all public images that match zero or more filters.
:param filters: dict of filter keys and values. If a 'properties'
key is present, it is treated as a dict of key/value
filters on the image properties attribute
"""
if filters == None:
filters = {}
session = get_session()
return session.query(models.Image).\
query = session.query(models.Image).\
options(joinedload(models.Image.properties)).\
filter_by(deleted=_deleted(context)).\
filter_by(is_public=True).\
filter(models.Image.status != 'killed').\
all()
filter(models.Image.status != 'killed')
if 'size_min' in filters:
query = query.filter(models.Image.size >= filters['size_min'])
del filters['size_min']
if 'size_max' in filters:
query = query.filter(models.Image.size <= filters['size_max'])
del filters['size_max']
for (k, v) in filters.pop('properties', {}).items():
query = query.filter(models.Image.properties.any(name=k, value=v))
for (k, v) in filters.items():
query = query.filter(getattr(models.Image, k) == v)
return query.all()
def _drop_protected_attrs(model_class, values):

View File

@ -36,6 +36,9 @@ DISPLAY_FIELDS_IN_INDEX = ['id', 'name', 'size',
'disk_format', 'container_format',
'checksum']
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
'size_min', 'size_max']
class Controller(wsgi.Controller):
"""Controller for the reference implementation registry server"""
@ -45,7 +48,7 @@ class Controller(wsgi.Controller):
db_api.configure_db(options)
def index(self, req):
"""Return basic information for all public, non-deleted images
"""Return a basic filtered list of public, non-deleted images
:param req: the Request object coming from the wsgi layer
:retval a mapping of the following form::
@ -64,7 +67,8 @@ class Controller(wsgi.Controller):
}
"""
images = db_api.image_get_all_public(None)
images = db_api.image_get_all_public(None, self._get_filters(req))
results = []
for image in images:
result = {}
@ -74,7 +78,7 @@ class Controller(wsgi.Controller):
return dict(images=results)
def detail(self, req):
"""Return detailed information for all public, non-deleted images
"""Return a filtered list of public, non-deleted images in detail
:param req: the Request object coming from the wsgi layer
:retval a mapping of the following form::
@ -85,10 +89,33 @@ class Controller(wsgi.Controller):
all image model fields.
"""
images = db_api.image_get_all_public(None)
images = db_api.image_get_all_public(None, self._get_filters(req))
image_dicts = [make_image_dict(i) for i in images]
return dict(images=image_dicts)
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
"""
filters = {}
properties = {}
for param in req.str_params:
if param in SUPPORTED_FILTERS:
filters[param] = req.str_params.get(param)
if param.startswith('property-'):
_param = param[9:]
properties[_param] = req.str_params.get(param)
if len(properties) > 0:
filters['properties'] = properties
return filters
def show(self, req, id):
"""Return data about the given image id."""
try:

View File

@ -787,3 +787,213 @@ class TestCurlApi(functional.FunctionalTest):
"Could not find '%s' in '%s'" % (expected, out))
self.stop_servers()
def test_filtered_images(self):
"""
Set up three test images and ensure each query param filter works
"""
self.cleanup()
self.start_servers()
api_port = self.api_port
registry_port = self.registry_port
# 0. GET /images
# Verify no public images
cmd = "curl http://0.0.0.0:%d/v1/images" % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
self.assertEqual('{"images": []}', out.strip())
# 1. POST /images with three public images with various attributes
cmd = ("curl -i -X POST "
"-H 'Expect: ' " # Necessary otherwise sends 100 Continue
"-H 'X-Image-Meta-Name: Image1' "
"-H 'X-Image-Meta-Status: active' "
"-H 'X-Image-Meta-Container-Format: ovf' "
"-H 'X-Image-Meta-Disk-Format: vdi' "
"-H 'X-Image-Meta-Size: 19' "
"-H 'X-Image-Meta-Is-Public: True' "
"-H 'X-Image-Meta-Property-pants: are on' "
"http://0.0.0.0:%d/v1/images") % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
lines = out.split("\r\n")
status_line = lines[0]
self.assertEqual("HTTP/1.1 201 Created", status_line)
cmd = ("curl -i -X POST "
"-H 'Expect: ' " # Necessary otherwise sends 100 Continue
"-H 'X-Image-Meta-Name: My Image!' "
"-H 'X-Image-Meta-Status: active' "
"-H 'X-Image-Meta-Container-Format: ovf' "
"-H 'X-Image-Meta-Disk-Format: vhd' "
"-H 'X-Image-Meta-Size: 20' "
"-H 'X-Image-Meta-Is-Public: True' "
"-H 'X-Image-Meta-Property-pants: are on' "
"http://0.0.0.0:%d/v1/images") % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
lines = out.split("\r\n")
status_line = lines[0]
self.assertEqual("HTTP/1.1 201 Created", status_line)
cmd = ("curl -i -X POST "
"-H 'Expect: ' " # Necessary otherwise sends 100 Continue
"-H 'X-Image-Meta-Name: My Image!' "
"-H 'X-Image-Meta-Status: saving' "
"-H 'X-Image-Meta-Container-Format: ami' "
"-H 'X-Image-Meta-Disk-Format: ami' "
"-H 'X-Image-Meta-Size: 21' "
"-H 'X-Image-Meta-Is-Public: True' "
"-H 'X-Image-Meta-Property-pants: are off' "
"http://0.0.0.0:%d/v1/images") % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
lines = out.split("\r\n")
status_line = lines[0]
self.assertEqual("HTTP/1.1 201 Created", status_line)
# 2. GET /images
# Verify three public images
cmd = "curl http://0.0.0.0:%d/v1/images" % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 3)
# 3. GET /images with name filter
# Verify correct images returned with name
cmd = "curl http://0.0.0.0:%d/v1/images?name=My%%20Image!" % api_port
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 2)
for image in images["images"]:
self.assertEqual(image["name"], "My Image!")
# 4. GET /images with status filter
# Verify correct images returned with status
cmd = ("curl http://0.0.0.0:%d/v1/images/detail?status=queued"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 3)
for image in images["images"]:
self.assertEqual(image["status"], "queued")
cmd = ("curl http://0.0.0.0:%d/v1/images/detail?status=active"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 0)
# 5. GET /images with container_format filter
# Verify correct images returned with container_format
cmd = ("curl http://0.0.0.0:%d/v1/images?container_format=ovf"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 2)
for image in images["images"]:
self.assertEqual(image["container_format"], "ovf")
# 6. GET /images with disk_format filter
# Verify correct images returned with disk_format
cmd = ("curl http://0.0.0.0:%d/v1/images?disk_format=vdi"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 1)
for image in images["images"]:
self.assertEqual(image["disk_format"], "vdi")
# 7. GET /images with size_max filter
# Verify correct images returned with size <= expected
cmd = ("curl http://0.0.0.0:%d/v1/images?size_max=20"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 2)
for image in images["images"]:
self.assertTrue(image["size"] <= 20)
# 8. GET /images with size_min filter
# Verify correct images returned with size >= expected
cmd = ("curl http://0.0.0.0:%d/v1/images?size_min=20"
% api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 2)
for image in images["images"]:
self.assertTrue(image["size"] >= 20)
# 9. GET /images with property filter
# Verify correct images returned with property
cmd = ("curl http://0.0.0.0:%d/v1/images/detail?"
"property-pants=are%%20on" % api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 2)
for image in images["images"]:
self.assertEqual(image["properties"]["pants"], "are on")
# 10. GET /images with property filter and name filter
# Verify correct images returned with property and name
# Make sure you quote the url when using more than one param!
cmd = ("curl 'http://0.0.0.0:%d/v1/images/detail?"
"name=My%%20Image!&property-pants=are%%20on'" % api_port)
exitcode, out, err = execute(cmd)
self.assertEqual(0, exitcode)
images = json.loads(out.strip())
self.assertEqual(len(images["images"]), 1)
for image in images["images"]:
self.assertEqual(image["properties"]["pants"], "are on")
self.assertEqual(image["name"], "My Image!")

View File

@ -400,9 +400,32 @@ def stub_out_registry_db_image_api(stubs):
else:
return images[0]
def image_get_all_public(self, _context, public=True):
return [f for f in self.images
if f['is_public'] == public]
def image_get_all_public(self, _context, filters):
images = [f for f in self.images if f['is_public'] == True]
if 'size_min' in filters:
size_min = int(filters.pop('size_min'))
images = [f for f in images if int(f['size']) >= size_min]
if 'size_max' in filters:
size_max = int(filters.pop('size_max'))
images = [f for f in images if int(f['size']) <= size_max]
def _prop_filter(key, value):
def _func(image):
for prop in image['properties']:
if prop['name'] == key:
return prop['value'] == value
return False
return _func
for k, v in filters.pop('properties', {}).items():
images = filter(_prop_filter(k, v), images)
for k, v in filters.items():
images = [f for f in images if f[k] == v]
return images
fake_datastore = FakeDatastore()
stubs.Set(glance.registry.db.api, 'image_create',

View File

@ -26,6 +26,7 @@ import webob
from glance.api import v1 as server
from glance.registry import server as rserver
import glance.registry.db.api
from tests import stubs
VERBOSE = False
@ -87,6 +88,50 @@ class TestRegistryAPI(unittest.TestCase):
for k, v in fixture.iteritems():
self.assertEquals(v, images[0][k])
def test_get_index_filter_name(self):
"""Tests that the /images registry API returns list of
public images that have a specific name. This is really a sanity
check, filtering is tested more in-depth using /images/detail
"""
fixture = {'id': 2,
'name': 'fake image #2',
'size': 19,
'checksum': None}
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images?name=new name! #123')
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), 2)
for image in images:
self.assertEqual('new name! #123', image['name'])
def test_get_details(self):
"""Tests that the /images/detail registry API returns
a mapping containing a list of detailed image information
@ -112,6 +157,324 @@ class TestRegistryAPI(unittest.TestCase):
for k, v in fixture.iteritems():
self.assertEquals(v, images[0][k])
def test_get_details_filter_name(self):
"""Tests that the /images/detail registry API returns list of
public images that have a specific name
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?name=new name! #123')
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), 2)
for image in images:
self.assertEqual('new name! #123', image['name'])
def test_get_details_filter_status(self):
"""Tests that the /images/detail registry API returns list of
public images that have a specific status
"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #4',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?status=saving')
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('saving', image['status'])
def test_get_details_filter_container_format(self):
"""Tests that the /images/detail registry API returns list of
public images that have a specific container_format
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vdi',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?container_format=ovf')
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), 2)
for image in images:
self.assertEqual('ovf', image['container_format'])
def test_get_details_filter_disk_format(self):
"""Tests that the /images/detail registry API returns list of
public images that have a specific disk_format
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?disk_format=vhd')
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), 2)
for image in images:
self.assertEqual('vhd', image['disk_format'])
def test_get_details_filter_size_min(self):
"""Tests that the /images/detail registry API returns list of
public images that have a size greater than or equal to size_min
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 18,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?size_min=19')
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), 2)
for image in images:
self.assertTrue(image['size'] >= 19)
def test_get_details_filter_size_max(self):
"""Tests that the /images/detail registry API returns list of
public images that have a size less than or equal to size_max
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 18,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?size_max=19')
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), 2)
for image in images:
self.assertTrue(image['size'] <= 19)
def test_get_details_filter_size_min_max(self):
"""Tests that the /images/detail registry API returns list of
public images that have a size less than or equal to size_max
and greater than or equal to size_min
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 18,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 2,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #5',
'size': 6,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?size_min=18&size_max=19')
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), 2)
for image in images:
self.assertTrue(image['size'] <= 19 and image['size'] >= 18)
def test_get_details_filter_property(self):
"""Tests that the /images/detail registry API returns list of
public images that have a specific custom property
"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'fake image #3',
'size': 19,
'checksum': None,
'properties': {'prop_123': 'v a'}}
glance.registry.db.api.image_create(None, extra_fixture)
extra_fixture = {'id': self.next_image_id + 1,
'status': 'active',
'is_public': True,
'disk_format': 'ami',
'container_format': 'ami',
'name': 'fake image #4',
'size': 19,
'checksum': None,
'properties': {'prop_123': 'v b'}}
glance.registry.db.api.image_create(None, extra_fixture)
req = webob.Request.blank('/images/detail?property-prop_123=v%20a')
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('v a', image['properties']['prop_123'])
def test_create_image(self):
"""Tests that the /images POST registry API creates the image"""
fixture = {'name': 'fake public image',

View File

@ -24,8 +24,9 @@ import unittest
import webob
from glance import client
from glance.registry import client as rclient
from glance.common import exception
import glance.registry.db.api
from glance.registry import client as rclient
from tests import stubs
@ -69,6 +70,26 @@ class TestRegistryClient(unittest.TestCase):
for k, v in fixture.items():
self.assertEquals(v, images[0][k])
def test_get_image_index_by_name(self):
"""Test correct set of public, name-filtered image returned. This
is just a sanity check, we test the details call more in-depth."""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images({'name': 'new name! #123'})
self.assertEquals(len(images), 1)
for image in images:
self.assertEquals('new name! #123', image['name'])
def test_get_image_details(self):
"""Tests that the detailed info about public images returned"""
fixture = {'id': 2,
@ -87,6 +108,140 @@ class TestRegistryClient(unittest.TestCase):
for k, v in fixture.items():
self.assertEquals(v, images[0][k])
def test_get_image_details_by_name(self):
"""Tests that a detailed call can be filtered by name"""
extra_fixture = {'id': self.next_image_id,
'status': 'active',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'name': 'new name! #123'})
self.assertEquals(len(images), 1)
for image in images:
self.assertEquals('new name! #123', image['name'])
def test_get_image_details_by_status(self):
"""Tests that a detailed call can be filtered by status"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'status': 'saving'})
self.assertEquals(len(images), 1)
for image in images:
self.assertEquals('saving', image['status'])
def test_get_image_details_by_container_format(self):
"""Tests that a detailed call can be filtered by container_format"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'container_format': 'ovf'})
self.assertEquals(len(images), 2)
for image in images:
self.assertEquals('ovf', image['container_format'])
def test_get_image_details_by_disk_format(self):
"""Tests that a detailed call can be filtered by disk_format"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'disk_format': 'vhd'})
self.assertEquals(len(images), 2)
for image in images:
self.assertEquals('vhd', image['disk_format'])
def test_get_image_details_with_maximum_size(self):
"""Tests that a detailed call can be filtered by size_max"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 21,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'size_max': 20})
self.assertEquals(len(images), 1)
for image in images:
self.assertTrue(image['size'] <= 20)
def test_get_image_details_with_minimum_size(self):
"""Tests that a detailed call can be filtered by size_min"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 20,
'checksum': None}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'size_min': 20})
self.assertEquals(len(images), 1)
for image in images:
self.assertTrue(image['size'] >= 20)
def test_get_image_details_by_property(self):
"""Tests that a detailed call can be filtered by a property"""
extra_fixture = {'id': self.next_image_id,
'status': 'saving',
'is_public': True,
'disk_format': 'vhd',
'container_format': 'ovf',
'name': 'new name! #123',
'size': 19,
'checksum': None,
'properties': {'p a': 'v a'}}
glance.registry.db.api.image_create(None, extra_fixture)
images = self.client.get_images_detailed({'property-p a': 'v a'})
self.assertEquals(len(images), 1)
for image in images:
self.assertEquals('v a', image['properties']['p a'])
def test_get_image(self):
"""Tests that the detailed info about an image returned"""
fixture = {'id': 1,