Merge lp:~rconradharris/nova/lp742229 into lp:~hudson-openstack/nova/trunk

Proposed by Rick Harris
Status: Merged
Approved by: Jay Pipes
Approved revision: 887
Merged at revision: 891
Proposed branch: lp:~rconradharris/nova/lp742229
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 130 lines (+78/-15)
2 files modified
nova/api/openstack/servers.py (+23/-15)
nova/tests/api/openstack/test_servers.py (+55/-0)
To merge this branch: bzr merge lp:~rconradharris/nova/lp742229
Reviewer Review Type Date Requested Status
Jay Pipes (community) Approve
Josh Kearney (community) Approve
Review via email: mp+54810@code.launchpad.net

Description of the change

disk_format is now an ImageService property. Adds tests to prevent regression.

To post a comment you must log in.
Revision history for this message
Josh Kearney (jk0) wrote :

Big pimpin'.

review: Approve
Revision history for this message
Jay Pipes (jaypipes) wrote :

lgtm2

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/api/openstack/servers.py'
2--- nova/api/openstack/servers.py 2011-03-24 22:32:00 +0000
3+++ nova/api/openstack/servers.py 2011-03-25 04:54:23 +0000
4@@ -502,33 +502,41 @@
5 return dict(actions=actions)
6
7 def _get_kernel_ramdisk_from_image(self, req, image_id):
8- """Retrevies kernel and ramdisk IDs from Glance
9-
10- Only 'machine' (ami) type use kernel and ramdisk outside of the
11- image.
12- """
13- # FIXME(sirp): Since we're retrieving the kernel_id from an
14- # image_property, this means only Glance is supported.
15- # The BaseImageService needs to expose a consistent way of accessing
16- # kernel_id and ramdisk_id
17- image = self._image_service.show(req.environ['nova.context'], image_id)
18-
19- if image['status'] != 'active':
20+ """Fetch an image from the ImageService, then if present, return the
21+ associated kernel and ramdisk image IDs.
22+ """
23+ context = req.environ['nova.context']
24+ image_meta = self._image_service.show(context, image_id)
25+ # NOTE(sirp): extracted to a separate method to aid unit-testing, the
26+ # new method doesn't need a request obj or an ImageService stub
27+ kernel_id, ramdisk_id = self._do_get_kernel_ramdisk_from_image(
28+ image_meta)
29+ return kernel_id, ramdisk_id
30+
31+ @staticmethod
32+ def _do_get_kernel_ramdisk_from_image(image_meta):
33+ """Given an ImageService image_meta, return kernel and ramdisk image
34+ ids if present.
35+
36+ This is only valid for `ami` style images.
37+ """
38+ image_id = image_meta['id']
39+ if image_meta['status'] != 'active':
40 raise exception.Invalid(
41 _("Cannot build from image %(image_id)s, status not active") %
42 locals())
43
44- if image['disk_format'] != 'ami':
45+ if image_meta['properties']['disk_format'] != 'ami':
46 return None, None
47
48 try:
49- kernel_id = image['properties']['kernel_id']
50+ kernel_id = image_meta['properties']['kernel_id']
51 except KeyError:
52 raise exception.NotFound(
53 _("Kernel not found for image %(image_id)s") % locals())
54
55 try:
56- ramdisk_id = image['properties']['ramdisk_id']
57+ ramdisk_id = image_meta['properties']['ramdisk_id']
58 except KeyError:
59 raise exception.NotFound(
60 _("Ramdisk not found for image %(image_id)s") % locals())
61
62=== modified file 'nova/tests/api/openstack/test_servers.py'
63--- nova/tests/api/openstack/test_servers.py 2011-03-24 20:31:04 +0000
64+++ nova/tests/api/openstack/test_servers.py 2011-03-25 04:54:23 +0000
65@@ -26,6 +26,7 @@
66
67 from nova import context
68 from nova import db
69+from nova import exception
70 from nova import flags
71 from nova import test
72 import nova.api.openstack
73@@ -1260,3 +1261,57 @@
74 server = dom.childNodes[0]
75 self.assertEquals(server.nodeName, 'server')
76 self.assertTrue(server.getAttribute('adminPass').startswith('fake'))
77+
78+
79+class TestGetKernelRamdiskFromImage(test.TestCase):
80+ """
81+ If we're building from an AMI-style image, we need to be able to fetch the
82+ kernel and ramdisk associated with the machine image. This information is
83+ stored with the image metadata and return via the ImageService.
84+
85+ These tests ensure that we parse the metadata return the ImageService
86+ correctly and that we handle failure modes appropriately.
87+ """
88+
89+ def test_status_not_active(self):
90+ """We should only allow fetching of kernel and ramdisk information if
91+ we have a 'fully-formed' image, aka 'active'
92+ """
93+ image_meta = {'id': 1, 'status': 'queued'}
94+ self.assertRaises(exception.Invalid, self._get_k_r, image_meta)
95+
96+ def test_not_ami(self):
97+ """Anything other than ami should return no kernel and no ramdisk"""
98+ image_meta = {'id': 1, 'status': 'active',
99+ 'properties': {'disk_format': 'vhd'}}
100+ kernel_id, ramdisk_id = self._get_k_r(image_meta)
101+ self.assertEqual(kernel_id, None)
102+ self.assertEqual(ramdisk_id, None)
103+
104+ def test_ami_no_kernel(self):
105+ """If an ami is missing a kernel it should raise NotFound"""
106+ image_meta = {'id': 1, 'status': 'active',
107+ 'properties': {'disk_format': 'ami', 'ramdisk_id': 1}}
108+ self.assertRaises(exception.NotFound, self._get_k_r, image_meta)
109+
110+ def test_ami_no_ramdisk(self):
111+ """If an ami is missing a ramdisk it should raise NotFound"""
112+ image_meta = {'id': 1, 'status': 'active',
113+ 'properties': {'disk_format': 'ami', 'kernel_id': 1}}
114+ self.assertRaises(exception.NotFound, self._get_k_r, image_meta)
115+
116+ def test_ami_kernel_ramdisk_present(self):
117+ """Return IDs if both kernel and ramdisk are present"""
118+ image_meta = {'id': 1, 'status': 'active',
119+ 'properties': {'disk_format': 'ami', 'kernel_id': 1,
120+ 'ramdisk_id': 2}}
121+ kernel_id, ramdisk_id = self._get_k_r(image_meta)
122+ self.assertEqual(kernel_id, 1)
123+ self.assertEqual(ramdisk_id, 2)
124+
125+ @staticmethod
126+ def _get_k_r(image_meta):
127+ """Rebinding function to a shorter name for convenience"""
128+ kernel_id, ramdisk_id = \
129+ servers.Controller._do_get_kernel_ramdisk_from_image(image_meta)
130+ return kernel_id, ramdisk_id