diff options
author | Brian Rosmaita <rosmaita.fossdev@gmail.com> | 2020-02-13 11:09:08 -0500 |
---|---|---|
committer | Elod Illes <elod.illes@est.tech> | 2020-07-17 14:03:31 +0200 |
commit | 418b9450e4b9bab15a4a0f92d013e53d18de3342 (patch) | |
tree | c2b16850a9b811b8ff8a8aeb7cc16f74056e885a | |
parent | 8290f746d85918fffbfefbdb50de72e52bec2ada (diff) | |
download | nova-418b9450e4b9bab15a4a0f92d013e53d18de3342.tar.gz |
Reject boot request for unsupported images
Nova has never supported direct booting of an image of an encrypted
volume uploaded to Glance via the Cinder upload-volume-to-image
process, but instead of rejecting such a request, an 'active' but
unusable instance is created. This patch allows Nova to use image
metadata to detect such an image and reject the boot request.
Change-Id: Idf84ccff254d26fa13473fe9741ddac21cbcf321
Related-bug: #1852106
Closes-bug: #1863611
(cherry picked from commit 963fd8c0f956bdf5c6c8987aa5d9f836386fd5ed)
(cherry picked from commit 240d0309023fcaf20df44f819e9b3e14af97f526)
(cherry picked from commit 6e71909b0b8ad8d20d0863e714cad2a7b120f658)
(cherry picked from commit 02551d6d6a3baee49309cffbc3bef2508fcafe72)
-rw-r--r-- | nova/api/openstack/compute/servers.py | 1 | ||||
-rw-r--r-- | nova/compute/api.py | 26 | ||||
-rw-r--r-- | nova/tests/unit/api/openstack/compute/test_serversV21.py | 16 | ||||
-rw-r--r-- | releasenotes/notes/cinder-detect-nonbootable-image-6fad7f865b45f879.yaml | 9 |
4 files changed, 52 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index b056999a4c..f7130669fe 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -582,6 +582,7 @@ class ServersController(wsgi.Controller): exception.ImageNotActive, exception.ImageBadRequest, exception.ImageNotAuthorized, + exception.ImageUnacceptable, exception.FixedIpNotFoundForAddress, exception.FlavorNotFound, exception.FlavorDiskTooSmall, diff --git a/nova/compute/api.py b/nova/compute/api.py index 6bd6a78cd0..6f1ff7c48e 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -557,6 +557,31 @@ class API(base.Base): # reason, we rely on the DB to cast True to a String. return True if bool_val else '' + @staticmethod + def _detect_nonbootable_image_from_properties(image_id, image): + """Check image for a property indicating it's nonbootable. + + This is called from the API service to ensure that there are + no known image properties indicating that this image is of a + type that we do not support booting from. + + Currently the only such property is 'cinder_encryption_key_id'. + + :param image_id: UUID of the image + :param image: a dict representation of the image including properties + :raises: ImageUnacceptable if the image properties indicate + that booting this image is not supported + """ + if not image: + return + + image_properties = image.get('properties', {}) + if image_properties.get('cinder_encryption_key_id'): + reason = _('Direct booting of an image uploaded from an ' + 'encrypted volume is unsupported.') + raise exception.ImageUnacceptable(image_id=image_id, + reason=reason) + def _check_requested_image(self, context, image_id, image, instance_type, root_bdm): if not image: @@ -773,6 +798,7 @@ class API(base.Base): self._check_injected_file_quota(context, files_to_inject) self._check_requested_image(context, image_id, image, instance_type, root_bdm) + self._detect_nonbootable_image_from_properties(image_id, image) def _validate_and_build_base_options(self, context, instance_type, boot_meta, image_href, image_id, diff --git a/nova/tests/unit/api/openstack/compute/test_serversV21.py b/nova/tests/unit/api/openstack/compute/test_serversV21.py index 473188c70a..a76fdc3898 100644 --- a/nova/tests/unit/api/openstack/compute/test_serversV21.py +++ b/nova/tests/unit/api/openstack/compute/test_serversV21.py @@ -3050,6 +3050,22 @@ class ServersControllerCreateTest(test.TestCase): "Flavor's disk is too small for requested image."): self.controller.create(self.req, body=self.body) + @mock.patch.object(fake._FakeImageService, 'show', + return_value=dict( + id='76fa36fc-c930-4bf3-8c8a-ea2a2420deb6', + status='active', + properties=dict( + cinder_encryption_key_id=fakes.FAKE_UUID))) + def test_create_server_image_nonbootable(self, mock_show): + self.req.body = jsonutils.dump_as_bytes(self.body) + + expected_msg = ("Image {} is unacceptable: Direct booting of an image " + "uploaded from an encrypted volume is unsupported.") + with testtools.ExpectedException( + webob.exc.HTTPBadRequest, + expected_msg.format(self.image_uuid)): + self.controller.create(self.req, body=self.body) + def test_create_instance_with_image_non_uuid(self): self.body['server']['imageRef'] = 'not-uuid' self.assertRaises(exception.ValidationError, diff --git a/releasenotes/notes/cinder-detect-nonbootable-image-6fad7f865b45f879.yaml b/releasenotes/notes/cinder-detect-nonbootable-image-6fad7f865b45f879.yaml new file mode 100644 index 0000000000..0746df58f2 --- /dev/null +++ b/releasenotes/notes/cinder-detect-nonbootable-image-6fad7f865b45f879.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + The Compute service has never supported direct booting of an instance from + an image that was created by the Block Storage service from an encrypted + volume. Previously, this operation would result in an ACTIVE instance that + was unusable. Beginning with this release, an attempt to boot from such an + image will result in the Compute API returning a 400 (Bad Request) + response. |