Permalink
Browse files

Add missing image to instance booted from volume

When booting an instance from a volume, the image_ref for
the instance will be None. And the API do not get the image
information for the instance also. So when we calling the
related API, we get "" for instance.image.

Change-Id: I3c35ab1d7c8bcec551fb5d67d0b44418266b32a4
Closes-bug: 1317880
  • Loading branch information...
liyingjun committed Jun 24, 2014
1 parent 277c69a commit c3191cf0ba5ad3dc2df8da2a2bf5c9d270fde9d9
@@ -34,6 +34,7 @@
from nova.compute import flavors
from nova import exception
from nova import objects
+from nova.objects import instance as instance_obj
from nova.openstack.common.gettextutils import _
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
@@ -599,6 +600,8 @@ def _get_servers(self, req, is_detail):
limit=limit,
marker=marker,
want_objects=True)
+ for instance in instance_list:
+ instance_obj.add_image_ref(context, instance)
except exception.MarkerNotFound:
msg = _('marker [%s] not found') % marker
raise exc.HTTPBadRequest(explanation=msg)
@@ -766,7 +769,8 @@ def show(self, req, id):
context = req.environ['nova.context']
instance = self.compute_api.get(context, id,
want_objects=True)
- req.cache_db_instance(instance)
+ req.cache_db_instance(instance_obj.add_image_ref(context,
+ instance))
return self._view_builder.show(req, instance)
except exception.NotFound:
msg = _("Instance could not be found")
View
@@ -14,6 +14,7 @@
from nova.cells import opts as cells_opts
from nova.cells import rpcapi as cells_rpcapi
+from nova import compute
from nova.compute import flavors
from nova import db
from nova import exception
@@ -567,6 +568,20 @@ def delete_metadata_key(self, context, key):
self.obj_reset_changes(['metadata'])
+def add_image_ref(context, instance):
+ """Helper method to add image_ref to instance object."""
+ if not instance['image_ref']:
+ compute_api = compute.API()
+ bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
+ context, instance['uuid'])
+ if compute_api.is_volume_backed_instance(context, instance, bdms):
+ props = bdms.root_metadata(
+ context, compute_api.image_api,
+ compute_api.volume_api)
+ instance['image_ref'] = props['image_id']
+ return instance
+
+
def _make_instance_list(context, inst_list, db_inst_list, expected_attrs):
get_fault = expected_attrs and 'fault' in expected_attrs
inst_faults = {}
@@ -196,6 +196,8 @@ class ServersControllerTest(ControllerTest):
def setUp(self):
super(ServersControllerTest, self).setUp()
+ self.compute_api = self.controller.compute_api
+ self.context = context.RequestContext('fake', 'fake')
def test_can_check_loaded_extensions(self):
self.ext_mgr.extensions = {'os-fake': None}
@@ -259,6 +261,25 @@ def test_get_server_by_uuid(self):
res_dict = self.controller.show(req, FAKE_UUID)
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
+ def test_get_server_no_image(self):
+
+ def return_instance(self, *args, **kwargs):
+ return fakes.stub_instance(id=1, uuid=FAKE_UUID,
+ project_id=str(uuid.uuid4()),
+ image_ref='')
+
+ def fake_add_image_ref(context, instance):
+ instance['image_ref'] = 'fake_image'
+ return instance
+
+ self.stubs.Set(db, 'instance_get_by_uuid', return_instance)
+ self.stubs.Set(instance_obj, 'add_image_ref', fake_add_image_ref)
+
+ req = fakes.HTTPRequest.blank('/fake/servers/%s' % FAKE_UUID)
+ server = self.controller.show(req, FAKE_UUID)
+
+ self.assertEqual('fake_image', server['server']['image']['id'])
+
def test_unique_host_id(self):
"""Create two servers with the same host and different
project_ids and check that the hostId's are unique.
@@ -517,6 +538,29 @@ def test_get_server_list(self):
self.assertEqual(s['links'], expected_links)
+ def test_get_servers_no_image(self):
+
+ def fake_get_all(compute_self, context, search_opts=None,
+ sort_key=None, sort_dir='desc',
+ limit=None, marker=None, want_objects=False):
+ db_list = [fakes.stub_instance(100,
+ uuid=FAKE_UUID,
+ image_ref='')]
+ return instance_obj._make_instance_list(
+ context, objects.InstanceList(), db_list, FIELDS)
+
+ def fake_add_image_ref(context, instance):
+ instance['image_ref'] = 'fake_image'
+ return instance
+
+ self.stubs.Set(instance_obj, 'add_image_ref', fake_add_image_ref)
+ self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
+
+ req = fakes.HTTPRequest.blank('/fake/servers/detail')
+ res_dict = self.controller.detail(req)
+ for s in res_dict['servers']:
+ self.assertEqual('fake_image', s['image']['id'])
+
def test_get_servers_with_limit(self):
req = fakes.HTTPRequest.blank('/fake/servers?limit=3')
res_dict = self.controller.index(req)
@@ -21,6 +21,7 @@
from nova.cells import rpcapi as cells_rpcapi
from nova.compute import flavors
+from nova import context
from nova import db
from nova import exception
from nova.network import model as network_model
@@ -1088,3 +1089,14 @@ def test_expected_cols(self):
self.stubs.Set(instance, '_INSTANCE_OPTIONAL_JOINED_FIELDS', ['bar'])
self.assertEqual(['bar'], instance._expected_cols(['foo', 'bar']))
self.assertIsNone(instance._expected_cols(None))
+
+
+class TestAddImageRef(test.TestCase):
+ @mock.patch('nova.objects.BlockDeviceMappingList.root_metadata')
+ def test_add_image_ref(self, mock_root_metadata):
+ mock_root_metadata.return_value = {'image_id': 'fake_image'}
+ fake_instance = fakes.stub_instance(id=1, uuid=fakes.FAKE_UUID,
+ image_ref='')
+ ctx = context.RequestContext('fake-user', 'fake-project')
+ new_instance = instance.add_image_ref(ctx, fake_instance)
+ self.assertEqual('fake_image', new_instance['image_ref'])

0 comments on commit c3191cf

Please sign in to comment.