From 91277e7e51849d197554b633a579c92116a5afc4 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 20 Oct 2022 18:44:27 +0100 Subject: compute: Allow users to manually specify bootable volumes When creating a server with an attached volume, you can specify a block device with a 'boot_index' of '0' and this will become the bootable device. OSC allows users to do this by using either the '--volume' option or a combination of the '--image' and '--boot-from-volume' options, but we should also allow them to do it the "hard way" via the '--block-device' option. For example: openstack server create \ --block-device uuid=0a89ecd8-1fe2-45f0-94da-7789067911c9,boot_index=0 \ --block-device uuid=589266ef-fd88-46e9-b7b2-94503ce8f88f,boot_index=1 \ ... \ my-server Make this possible. Change-Id: Ia48449fecbc590346630807b1c7da40102d53b33 Signed-off-by: Stephen Finucane Story: 2010376 Task: 46617 --- .../tests/unit/compute/v2/test_server.py | 44 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) (limited to 'openstackclient/tests') diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index 27ae3e9b..1fd92e93 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -2455,7 +2455,7 @@ class TestServerCreate(TestServer): 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.volume.id, - 'boot_index': '0', + 'boot_index': 0, 'source_type': 'volume', 'destination_type': 'volume', }], @@ -2506,7 +2506,7 @@ class TestServerCreate(TestServer): 'admin_pass': None, 'block_device_mapping_v2': [{ 'uuid': self.snapshot.id, - 'boot_index': '0', + 'boot_index': 0, 'source_type': 'snapshot', 'destination_type': 'volume', 'delete_on_termination': False, @@ -2529,20 +2529,20 @@ class TestServerCreate(TestServer): self.assertEqual(self.datalist(), data) def test_server_create_with_block_device(self): - block_device = f'uuid={self.volume.id},source_type=volume' + block_device = f'uuid={self.volume.id},source_type=volume,boot_index=0' arglist = [ - '--image', 'image1', '--flavor', self.flavor.id, '--block-device', block_device, self.new_server.name, ] verifylist = [ - ('image', 'image1'), + ('image', None), ('flavor', self.flavor.id), ('block_devices', [ { 'uuid': self.volume.id, 'source_type': 'volume', + 'boot_index': '0', }, ]), ('server_name', self.new_server.name), @@ -2569,6 +2569,7 @@ class TestServerCreate(TestServer): 'uuid': self.volume.id, 'source_type': 'volume', 'destination_type': 'volume', + 'boot_index': 0, }, ], 'nics': [], @@ -2578,7 +2579,7 @@ class TestServerCreate(TestServer): # ServerManager.create(name, image, flavor, **kwargs) self.servers_mock.create.assert_called_with( self.new_server.name, - self.image, + None, self.flavor, **kwargs ) @@ -3506,6 +3507,37 @@ class TestServerCreate(TestServer): self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) + def test_server_create_no_boot_device(self): + block_device = f'uuid={self.volume.id},source_type=volume,boot_index=1' + arglist = [ + '--block-device', block_device, + '--flavor', self.flavor.id, + self.new_server.name, + ] + verifylist = [ + ('image', None), + ('flavor', self.flavor.id), + ('block_devices', [ + { + 'uuid': self.volume.id, + 'source_type': 'volume', + 'boot_index': '1', + }, + ]), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + exc = self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args, + ) + self.assertIn( + 'An image (--image, --image-property) or bootable volume ' + '(--volume, --snapshot, --block-device) is required', + str(exc), + ) + def test_server_create_with_swap(self): arglist = [ '--image', 'image1', -- cgit v1.2.1