diff options
| author | Rui Chen <chenrui.momo@gmail.com> | 2017-02-24 16:48:05 +0800 |
|---|---|---|
| committer | Rui Chen <chenrui.momo@gmail.com> | 2017-05-17 01:42:12 +0000 |
| commit | 7a7bb06377c96f7bfc2c371aa2ff726ee364a9db (patch) | |
| tree | 518ae86b9137ae6e7921c018f363628316a38ce4 /openstackclient/tests/unit/compute/v2/test_server.py | |
| parent | 0181de38afc8cc4b96f226b00e173fb0c0d2e4dc (diff) | |
| download | python-openstackclient-7a7bb06377c96f7bfc2c371aa2ff726ee364a9db.tar.gz | |
Make block-device-mapping more stable and clear
The patch fix the following issues:
1. ValueError is raised if input don't contain "=". Sometimes the whole
"server create" command is very complex, it's difficult to find out root
reason directly.
2. Don't support to add block device from snapshot, like:
--block-device-mapping
vdb=0c8ae9d8-cadc-4a23-8337-4254614d277e:snapshot:1, it's supported by
novaclient, but not in osc.
3. If input "vdb=", not add any mapping information, the server will be
launched successfully, not raise error message to let use add
volume/snapshot id, just ignore "--block-device-mapping" option.
4. The help message of "block-device-mapping" option is so simple, need
to add some details about how to add <type>, <delete_on_terminate>
contains.
Change-Id: Ib7f7a654c3dc2a8272545f168b4c4ced230ce39e
Depends-On: Ib37913891bbf7a31b570404c4668c490d5ac859b
Closes-Bug: #1667266
Diffstat (limited to 'openstackclient/tests/unit/compute/v2/test_server.py')
| -rw-r--r-- | openstackclient/tests/unit/compute/v2/test_server.py | 339 |
1 files changed, 329 insertions, 10 deletions
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index 9370bf6b..d25cabbb 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. # +import argparse import collections import getpass import mock @@ -49,6 +50,10 @@ class TestServer(compute_fakes.TestComputev2): self.volumes_mock = self.app.client_manager.volume.volumes self.volumes_mock.reset_mock() + # Get a shortcut to the volume client VolumeManager Mock + self.snapshots_mock = self.app.client_manager.volume.volume_snapshots + self.snapshots_mock.reset_mock() + # Set object attributes to be tested. Could be overwritten in subclass. self.attrs = {} @@ -326,7 +331,9 @@ class TestServerCreate(TestServer): self.volume = volume_fakes.FakeVolume.create_one_volume() self.volumes_mock.get.return_value = self.volume - self.block_device_mapping = 'vda=' + self.volume.name + ':::0' + + self.snapshot = volume_fakes.FakeSnapshot.create_one_snapshot() + self.snapshots_mock.get.return_value = self.snapshot # Get the command object to test self.cmd = server.CreateServer(self.app, None) @@ -852,13 +859,13 @@ class TestServerCreate(TestServer): arglist = [ '--image', 'image1', '--flavor', self.flavor.id, - '--block-device-mapping', self.block_device_mapping, + '--block-device-mapping', 'vda=' + self.volume.name + ':::false', self.new_server.name, ] verifylist = [ ('image', 'image1'), ('flavor', self.flavor.id), - ('block_device_mapping', [self.block_device_mapping]), + ('block_device_mapping', {'vda': self.volume.name + ':::false'}), ('config_drive', False), ('server_name', self.new_server.name), ] @@ -867,11 +874,6 @@ class TestServerCreate(TestServer): # CreateServer.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - real_volume_mapping = ( - (self.block_device_mapping.split('=', 1)[1]).replace( - self.volume.name, - self.volume.id)) - # Set expected values kwargs = dict( meta=None, @@ -885,10 +887,167 @@ class TestServerCreate(TestServer): availability_zone=None, block_device_mapping_v2=[{ 'device_name': 'vda', - 'uuid': real_volume_mapping.split(':', 1)[0], + 'uuid': self.volume.id, + 'destination_type': 'volume', + 'source_type': 'volume', + 'delete_on_termination': 'false', + }], + nics=[], + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_block_device_mapping_min_input(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', 'vdf=' + self.volume.name, + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', {'vdf': self.volume.name}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # CreateServer.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[{ + 'device_name': 'vdf', + 'uuid': self.volume.id, + 'destination_type': 'volume', + 'source_type': 'volume', + }], + nics=[], + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_block_device_mapping_default_input(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', 'vdf=' + self.volume.name + ':::', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', {'vdf': self.volume.name + ':::'}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # CreateServer.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[{ + 'device_name': 'vdf', + 'uuid': self.volume.id, + 'destination_type': 'volume', + 'source_type': 'volume', + }], + nics=[], + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_block_device_mapping_full_input(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', + 'vde=' + self.volume.name + ':volume:3:true', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', + {'vde': self.volume.name + ':volume:3:true'}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # CreateServer.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[{ + 'device_name': 'vde', + 'uuid': self.volume.id, 'destination_type': 'volume', 'source_type': 'volume', - 'delete_on_termination': '0' + 'delete_on_termination': 'true', + 'volume_size': '3' }], nics=[], scheduler_hints={}, @@ -905,6 +1064,166 @@ class TestServerCreate(TestServer): self.assertEqual(self.columns, columns) self.assertEqual(self.datalist(), data) + def test_server_create_with_block_device_mapping_snapshot(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', + 'vds=' + self.volume.name + ':snapshot:5:true', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', + {'vds': self.volume.name + ':snapshot:5:true'}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # CreateServer.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[{ + 'device_name': 'vds', + 'uuid': self.snapshot.id, + 'destination_type': 'volume', + 'source_type': 'snapshot', + 'delete_on_termination': 'true', + 'volume_size': '5' + }], + nics=[], + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_block_device_mapping_multiple(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', 'vdb=' + self.volume.name + ':::false', + '--block-device-mapping', 'vdc=' + self.volume.name + ':::true', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', {'vdb': self.volume.name + ':::false', + 'vdc': self.volume.name + ':::true'}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # CreateServer.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = dict( + meta=None, + files={}, + reservation_id=None, + min_count=1, + max_count=1, + security_groups=[], + userdata=None, + key_name=None, + availability_zone=None, + block_device_mapping_v2=[ + { + 'device_name': 'vdb', + 'uuid': self.volume.id, + 'destination_type': 'volume', + 'source_type': 'volume', + 'delete_on_termination': 'false', + }, + { + 'device_name': 'vdc', + 'uuid': self.volume.id, + 'destination_type': 'volume', + 'source_type': 'volume', + 'delete_on_termination': 'true', + } + ], + nics=[], + scheduler_hints={}, + config_drive=None, + ) + # ServerManager.create(name, image, flavor, **kwargs) + self.servers_mock.create.assert_called_with( + self.new_server.name, + self.image, + self.flavor, + **kwargs + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist(), data) + + def test_server_create_with_block_device_mapping_invalid_format(self): + # 1. block device mapping don't contain equal sign "=" + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', 'not_contain_equal_sign', + self.new_server.name, + ] + self.assertRaises(argparse.ArgumentTypeError, + self.check_parser, + self.cmd, arglist, []) + # 2. block device mapping don't contain device name "=uuid:::true" + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', '=uuid:::true', + self.new_server.name, + ] + self.assertRaises(argparse.ArgumentTypeError, + self.check_parser, + self.cmd, arglist, []) + + def test_server_create_with_block_device_mapping_no_uuid(self): + arglist = [ + '--image', 'image1', + '--flavor', self.flavor.id, + '--block-device-mapping', 'vdb=', + self.new_server.name, + ] + verifylist = [ + ('image', 'image1'), + ('flavor', self.flavor.id), + ('block_device_mapping', {'vdb': ''}), + ('config_drive', False), + ('server_name', self.new_server.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, + parsed_args) + class TestServerDelete(TestServer): |
