Merge lp:~soren/nova/image-tests into lp:~hudson-openstack/nova/trunk

Proposed by Soren Hansen
Status: Merged
Approved by: Devin Carlen
Approved revision: no longer in the source branch.
Merged at revision: 1385
Proposed branch: lp:~soren/nova/image-tests
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 256 lines (+169/-14)
3 files modified
nova/image/fake.py (+30/-11)
nova/tests/test_image.py (+132/-0)
nova/virt/libvirt/connection.py (+7/-3)
To merge this branch: bzr merge lp:~soren/nova/image-tests
Reviewer Review Type Date Requested Status
Devin Carlen (community) Approve
Josh Kearney (community) Approve
Review via email: mp+70570@code.launchpad.net

Commit message

Add a generic image service test and run it against the fake image service.

Description of the change

Add a generic image service test and run it against the fake image service.

I've removed a couple of things from the image dicts FakeImageService returns because they're not documented. If something needs them, we should update the documentation and make sure all the other drivers return them as well.

Right now, I just run these tests against the fake image service, but I want to run them against the other ones as well to make sure they all actually behave identically.

To post a comment you must log in.
lp:~soren/nova/image-tests updated
1381. By Matt Dietz

Fixes lp821144

Revert resize broken because an incorrect number of parameters and a bad call at the virt layer

Revision history for this message
Josh Kearney (jk0) wrote :

I'm game.

review: Approve
lp:~soren/nova/image-tests updated
1382. By Dan Prince

Add exception logging for instance IDs in the __public_instance_is_accessible smoke test function. This should help troubleshoot an intermittent failure.

1383. By Gabe Westmaas

Updates v1.1 servers/id/action requests to comply with the 1.1 spec

1384. By Justin Shepherd

Implemented @test.skip_unless and @test.skip_if functionality in nova/test.py.

Added nova/tests/test_skip_examples.py which contains example skip case usages.

Revision history for this message
Devin Carlen (devcamcar) wrote :

good stuff!

review: Approve
lp:~soren/nova/image-tests updated
1385. By Soren Hansen

Add a generic image service test and run it against the fake image service.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nova/image/fake.py'
--- nova/image/fake.py 2011-07-08 09:35:01 +0000
+++ nova/image/fake.py 2011-08-05 13:46:49 +0000
@@ -45,9 +45,12 @@
45 'name': 'fakeimage123456',45 'name': 'fakeimage123456',
46 'created_at': timestamp,46 'created_at': timestamp,
47 'updated_at': timestamp,47 'updated_at': timestamp,
48 'deleted_at': None,
49 'deleted': False,
48 'status': 'active',50 'status': 'active',
49 'container_format': 'ami',51 'is_public': False,
50 'disk_format': 'raw',52# 'container_format': 'ami',
53# 'disk_format': 'raw',
51 'properties': {'kernel_id': FLAGS.null_kernel,54 'properties': {'kernel_id': FLAGS.null_kernel,
52 'ramdisk_id': FLAGS.null_kernel,55 'ramdisk_id': FLAGS.null_kernel,
53 'architecture': 'x86_64'}}56 'architecture': 'x86_64'}}
@@ -56,9 +59,12 @@
56 'name': 'fakeimage123456',59 'name': 'fakeimage123456',
57 'created_at': timestamp,60 'created_at': timestamp,
58 'updated_at': timestamp,61 'updated_at': timestamp,
62 'deleted_at': None,
63 'deleted': False,
59 'status': 'active',64 'status': 'active',
60 'container_format': 'ami',65 'is_public': True,
61 'disk_format': 'raw',66# 'container_format': 'ami',
67# 'disk_format': 'raw',
62 'properties': {'kernel_id': FLAGS.null_kernel,68 'properties': {'kernel_id': FLAGS.null_kernel,
63 'ramdisk_id': FLAGS.null_kernel}}69 'ramdisk_id': FLAGS.null_kernel}}
6470
@@ -66,9 +72,12 @@
66 'name': 'fakeimage123456',72 'name': 'fakeimage123456',
67 'created_at': timestamp,73 'created_at': timestamp,
68 'updated_at': timestamp,74 'updated_at': timestamp,
75 'deleted_at': None,
76 'deleted': False,
69 'status': 'active',77 'status': 'active',
70 'container_format': 'ami',78 'is_public': True,
71 'disk_format': 'raw',79# 'container_format': 'ami',
80# 'disk_format': 'raw',
72 'properties': {'kernel_id': FLAGS.null_kernel,81 'properties': {'kernel_id': FLAGS.null_kernel,
73 'ramdisk_id': FLAGS.null_kernel}}82 'ramdisk_id': FLAGS.null_kernel}}
7483
@@ -76,9 +85,12 @@
76 'name': 'fakeimage123456',85 'name': 'fakeimage123456',
77 'created_at': timestamp,86 'created_at': timestamp,
78 'updated_at': timestamp,87 'updated_at': timestamp,
88 'deleted_at': None,
89 'deleted': False,
79 'status': 'active',90 'status': 'active',
80 'container_format': 'ami',91 'is_public': True,
81 'disk_format': 'raw',92# 'container_format': 'ami',
93# 'disk_format': 'raw',
82 'properties': {'kernel_id': FLAGS.null_kernel,94 'properties': {'kernel_id': FLAGS.null_kernel,
83 'ramdisk_id': FLAGS.null_kernel}}95 'ramdisk_id': FLAGS.null_kernel}}
8496
@@ -86,9 +98,12 @@
86 'name': 'fakeimage123456',98 'name': 'fakeimage123456',
87 'created_at': timestamp,99 'created_at': timestamp,
88 'updated_at': timestamp,100 'updated_at': timestamp,
101 'deleted_at': None,
102 'deleted': False,
89 'status': 'active',103 'status': 'active',
90 'container_format': 'ami',104 'is_public': True,
91 'disk_format': 'raw',105# 'container_format': 'ami',
106# 'disk_format': 'raw',
92 'properties': {'kernel_id': FLAGS.null_kernel,107 'properties': {'kernel_id': FLAGS.null_kernel,
93 'ramdisk_id': FLAGS.null_kernel}}108 'ramdisk_id': FLAGS.null_kernel}}
94109
@@ -101,7 +116,11 @@
101116
102 def index(self, context, filters=None, marker=None, limit=None):117 def index(self, context, filters=None, marker=None, limit=None):
103 """Returns list of images."""118 """Returns list of images."""
104 return copy.deepcopy(self.images.values())119 retval = []
120 for img in self.images.values():
121 retval += [dict([(k, v) for k, v in img.iteritems()
122 if k in ['id', 'name']])]
123 return retval
105124
106 def detail(self, context, filters=None, marker=None, limit=None):125 def detail(self, context, filters=None, marker=None, limit=None):
107 """Return list of detailed image information."""126 """Return list of detailed image information."""
108127
=== added file 'nova/tests/test_image.py'
--- nova/tests/test_image.py 1970-01-01 00:00:00 +0000
+++ nova/tests/test_image.py 2011-08-05 13:46:49 +0000
@@ -0,0 +1,132 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2011 OpenStack LLC
4# Author: Soren Hansen
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18import datetime
19
20from nova import context
21from nova import exception
22from nova import test
23import nova.image
24
25class _ImageTestCase(test.TestCase):
26 def setUp(self):
27 super(_ImageTestCase, self).setUp()
28 self.context = context.get_admin_context()
29
30 def test_index(self):
31 res = self.image_service.index(self.context)
32 for image in res:
33 self.assertEquals(set(image.keys()), set(['id', 'name']))
34
35 def test_detail(self):
36 res = self.image_service.detail(self.context)
37 for image in res:
38 keys = set(image.keys())
39 self.assertEquals(keys, set(['id', 'name', 'created_at',
40 'updated_at', 'deleted_at', 'deleted',
41 'status', 'is_public', 'properties']))
42 self.assertTrue(isinstance(image['created_at'], datetime.datetime))
43 self.assertTrue(isinstance(image['updated_at'], datetime.datetime))
44
45 if not (isinstance(image['deleted_at'], datetime.datetime) or
46 image['deleted_at'] is None):
47 self.fail('image\'s "deleted_at" attribute was neither a '
48 'datetime object nor None')
49
50 def check_is_bool(image, key):
51 val = image.get('deleted')
52 if not isinstance(val, bool):
53 self.fail('image\'s "%s" attribute wasn\'t '
54 'a bool: %r' % (key, val))
55
56 check_is_bool(image, 'deleted')
57 check_is_bool(image, 'is_public')
58
59 def test_index_and_detail_have_same_results(self):
60 index = self.image_service.index(self.context)
61 detail = self.image_service.detail(self.context)
62 index_set = set([(i['id'], i['name']) for i in index])
63 detail_set = set([(i['id'], i['name']) for i in detail])
64 self.assertEqual(index_set, detail_set)
65
66 def test_show_raises_imagenotfound_for_invalid_id(self):
67 self.assertRaises(exception.ImageNotFound,
68 self.image_service.show,
69 self.context,
70 'this image does not exist')
71
72 def test_show_by_name(self):
73 self.assertRaises(exception.ImageNotFound,
74 self.image_service.show_by_name,
75 self.context,
76 'this image does not exist')
77
78 def test_create_adds_id(self):
79 index = self.image_service.index(self.context)
80 image_count = len(index)
81
82 self.image_service.create(self.context, {})
83
84 index = self.image_service.index(self.context)
85 self.assertEquals(len(index), image_count + 1)
86
87 self.assertTrue(index[0]['id'])
88
89 def test_create_keeps_id(self):
90 self.image_service.create(self.context, {'id': '34'})
91 self.image_service.show(self.context, '34')
92
93 def test_create_rejects_duplicate_ids(self):
94 self.image_service.create(self.context, {'id': '34'})
95 self.assertRaises(exception.Duplicate,
96 self.image_service.create,
97 self.context,
98 {'id': '34'})
99
100 # Make sure there's still one left
101 self.image_service.show(self.context, '34')
102
103 def test_update(self):
104 self.image_service.create(self.context,
105 {'id': '34', 'foo': 'bar'})
106
107 self.image_service.update(self.context, '34',
108 {'id': '34', 'foo': 'baz'})
109
110 img = self.image_service.show(self.context, '34')
111 self.assertEquals(img['foo'], 'baz')
112
113 def test_delete(self):
114 self.image_service.create(self.context, {'id': '34', 'foo': 'bar'})
115 self.image_service.delete(self.context, '34')
116 self.assertRaises(exception.NotFound,
117 self.image_service.show,
118 self.context,
119 '34')
120
121 def test_delete_all(self):
122 self.image_service.create(self.context, {'id': '32', 'foo': 'bar'})
123 self.image_service.create(self.context, {'id': '33', 'foo': 'bar'})
124 self.image_service.create(self.context, {'id': '34', 'foo': 'bar'})
125 self.image_service.delete_all()
126 index = self.image_service.index(self.context)
127 self.assertEquals(len(index), 0)
128
129class FakeImageTestCase(_ImageTestCase):
130 def setUp(self):
131 super(FakeImageTestCase, self).setUp()
132 self.image_service = nova.image.fake.FakeImageService()
0133
=== modified file 'nova/virt/libvirt/connection.py'
--- nova/virt/libvirt/connection.py 2011-08-05 02:22:13 +0000
+++ nova/virt/libvirt/connection.py 2011-08-05 13:46:49 +0000
@@ -392,9 +392,7 @@
392 nova.image.get_image_service(image_href)392 nova.image.get_image_service(image_href)
393 snapshot = snapshot_image_service.show(context, snapshot_image_id)393 snapshot = snapshot_image_service.show(context, snapshot_image_id)
394394
395 metadata = {'disk_format': base['disk_format'],395 metadata = {'is_public': False,
396 'container_format': base['container_format'],
397 'is_public': False,
398 'status': 'active',396 'status': 'active',
399 'name': snapshot['name'],397 'name': snapshot['name'],
400 'properties': {398 'properties': {
@@ -409,6 +407,12 @@
409 arch = base['properties']['architecture']407 arch = base['properties']['architecture']
410 metadata['properties']['architecture'] = arch408 metadata['properties']['architecture'] = arch
411409
410 if 'disk_format' in base:
411 metadata['disk_format'] = base['disk_format']
412
413 if 'container_format' in base:
414 metadata['container_format'] = base['container_format']
415
412 # Make the snapshot416 # Make the snapshot
413 snapshot_name = uuid.uuid4().hex417 snapshot_name = uuid.uuid4().hex
414 snapshot_xml = """418 snapshot_xml = """