diff --git a/doc/source/user/block-device-mapping.rst b/doc/source/user/block-device-mapping.rst index 5ecf21658b61..2ad31616638b 100644 --- a/doc/source/user/block-device-mapping.rst +++ b/doc/source/user/block-device-mapping.rst @@ -220,3 +220,21 @@ mapping is valid before accepting a boot request. .. [3] This is a feature that the EC2 API offers as well and has been in Nova for a long time, although it has been broken in several releases. More info can be found on `this bug ` + + +FAQs +---- + +1. Is it possible to configure nova to automatically use cinder to back all + root disks with volumes? + + No, there is nothing automatic within nova that converts a + non-boot-from-volume request to convert the image to a root volume. + Several ideas have been discussed over time which are captured in the + spec for `volume-backed flavors`_. However, if you wish to force users + to always create volume-backed servers, you can configure the API service + by setting :oslo.config:option:`max_local_block_devices` to 0. This will + result in any non-boot-from-volume server create request to fail with a + 400 response. + +.. _volume-backed flavors: https://review.opendev.org/511965/ diff --git a/nova/conf/compute.py b/nova/conf/compute.py index a9dd2e50faa4..f2ca30d58a4c 100644 --- a/nova/conf/compute.py +++ b/nova/conf/compute.py @@ -82,21 +82,20 @@ Possible values: Maximum number of devices that will result in a local image being created on the hypervisor node. -A negative number means unlimited. Setting max_local_block_devices +A negative number means unlimited. Setting ``max_local_block_devices`` to 0 means that any request that attempts to create a local disk will fail. This option is meant to limit the number of local discs -(so root local disc that is the result of --image being used, and -any other ephemeral and swap disks). 0 does not mean that images -will be automatically converted to volumes and boot instances from -volumes - it just means that all requests that attempt to create a -local disk will fail. +(so root local disc that is the result of ``imageRef`` being used when +creating a server, and any other ephemeral and swap disks). 0 does not +mean that images will be automatically converted to volumes and boot +instances from volumes - it just means that all requests that attempt +to create a local disk will fail. Possible values: * 0: Creating a local disk is not allowed. * Negative number: Allows unlimited number of local discs. * Positive number: Allows only these many number of local discs. - (Default value is 3). """), cfg.ListOpt('compute_monitors', default=[], diff --git a/nova/tests/functional/test_boot_from_volume.py b/nova/tests/functional/test_boot_from_volume.py index 834b659e7420..0fae08635808 100644 --- a/nova/tests/functional/test_boot_from_volume.py +++ b/nova/tests/functional/test_boot_from_volume.py @@ -10,9 +10,12 @@ # License for the specific language governing permissions and limitations # under the License. +import six + from nova import context from nova import objects from nova.tests import fixtures as nova_fixtures +from nova.tests.functional.api import client as api_client from nova.tests.functional import integrated_helpers from nova.tests.functional import test_servers @@ -145,3 +148,17 @@ class BootFromVolumeTest(integrated_helpers.InstanceHelperMixin, self._verify_instance_flavor_not_zero(server_id) # Check that request spec has not been saved with 0 root_gb self._verify_request_spec_flavor_not_zero(server_id) + + def test_max_local_block_devices_0_force_bfv(self): + """Tests that when the API is configured with max_local_block_devices=0 + a user cannot boot from image, they must boot from volume. + """ + self.flags(max_local_block_devices=0) + server = self._build_minimal_create_server_request( + self.admin_api, 'test_max_local_block_devices_0_force_bfv') + ex = self.assertRaises(api_client.OpenStackApiException, + self.admin_api.post_server, + {'server': server}) + self.assertEqual(400, ex.response.status_code) + self.assertIn('You specified more local devices than the limit allows', + six.text_type(ex))