summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-10-16 03:37:42 +0000
committerGerrit Code Review <review@openstack.org>2018-10-16 03:37:42 +0000
commitf0c63de21d180994a3635d04b778923a9a2247dc (patch)
tree8cee4cef13fb2681cc1aad92a2584b2821325b47
parent3881e0ba34cb3a088bda81ca825f844b8bbf4785 (diff)
parent4fef02de71d86c1aa0cb1ace74abd0fe19e0a1e9 (diff)
downloadpython-novaclient-f0c63de21d180994a3635d04b778923a9a2247dc.tar.gz
Merge "Add support for microversion 2.67: BDMv2 volume_type"
-rw-r--r--doc/source/cli/nova.rst10
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/utils.py2
-rw-r--r--novaclient/tests/unit/v2/test_servers.py45
-rw-r--r--novaclient/tests/unit/v2/test_shell.py73
-rw-r--r--novaclient/v2/servers.py8
-rw-r--r--novaclient/v2/shell.py42
-rw-r--r--releasenotes/notes/microversion-v2_67-da6d9b12730b8562.yaml10
8 files changed, 187 insertions, 5 deletions
diff --git a/doc/source/cli/nova.rst b/doc/source/cli/nova.rst
index a8ff713c..a444c297 100644
--- a/doc/source/cli/nova.rst
+++ b/doc/source/cli/nova.rst
@@ -1036,9 +1036,13 @@ Boot a new server.
to 0, for others need to be specified),
shutdown=shutdown behaviour (either preserve
or remove, for local destination set to
- remove) and tag=device metadata tag
- (optional). (Supported by API versions '2.42'
- - '2.latest')
+ remove), tag=device metadata tag
+ (optional; supported by API versions '2.42'
+ - '2.latest'), and volume_type=type of volume
+ to create (either ID or name) when source is
+ `blank`, `image` or `snapshot` and dest is `volume`
+ (optional; supported by API versions '2.67'
+ - '2.latest').
``--swap <swap_size>``
Create and attach a local swap block device of
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index 49bd667d..43a8d1a9 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
-API_MAX_VERSION = api_versions.APIVersion("2.66")
+API_MAX_VERSION = api_versions.APIVersion("2.67")
diff --git a/novaclient/tests/unit/utils.py b/novaclient/tests/unit/utils.py
index 49d3631f..0050941b 100644
--- a/novaclient/tests/unit/utils.py
+++ b/novaclient/tests/unit/utils.py
@@ -104,7 +104,7 @@ class FixturedTestCase(testscenarios.TestWithScenarios, TestCase):
if not isinstance(body, six.string_types):
# json load if the input body to match against is not a string
req_data = jsonutils.loads(req_data)
- self.assertEqual(req_data, body)
+ self.assertEqual(body, req_data)
class TestResponse(requests.Response):
diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py
index 540968cf..427a4eff 100644
--- a/novaclient/tests/unit/v2/test_servers.py
+++ b/novaclient/tests/unit/v2/test_servers.py
@@ -1609,3 +1609,48 @@ class ServersV263Test(ServersV257Test):
'1234', fakes.FAKE_IMAGE_UUID_1,
trusted_image_certificates=['id1', 'id2'])
self.assertIn('trusted_image_certificates', six.text_type(ex))
+
+
+class ServersV267Test(ServersV263Test):
+ """Tests for creating a server with a block_device_mapping_v2 entry
+ using volume_type for microversion 2.67.
+ """
+ api_version = '2.67'
+
+ def test_create_server_boot_from_volume_with_volume_type(self):
+ bdm = [{"volume_size": 1,
+ "uuid": "11111111-1111-1111-1111-111111111111",
+ "delete_on_termination": True,
+ "source_type": "snapshot",
+ "destination_type": "volume",
+ "boot_index": 0,
+ "volume_type": "rbd"}]
+ s = self.cs.servers.create(
+ name="bfv server", image='', flavor=1,
+ nics='auto', block_device_mapping_v2=bdm)
+ self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
+ self.assert_called('POST', '/servers', {
+ 'server': {
+ 'flavorRef': '1',
+ 'imageRef': '',
+ 'name': 'bfv server',
+ 'networks': 'auto',
+ 'block_device_mapping_v2': bdm,
+ 'min_count': 1,
+ 'max_count': 1,
+ }})
+
+ def test_create_server_boot_from_volume_with_volume_type_pre_267(self):
+ self.cs.api_version = api_versions.APIVersion('2.66')
+ bdm = [{"volume_size": 1,
+ "uuid": "11111111-1111-1111-1111-111111111111",
+ "delete_on_termination": True,
+ "source_type": "snapshot",
+ "destination_type": "volume",
+ "boot_index": 0,
+ "volume_type": "rbd"}]
+ ex = self.assertRaises(ValueError, self.cs.servers.create,
+ name="bfv server", image='', flavor=1,
+ nics='none', block_device_mapping_v2=bdm)
+ self.assertIn("Block device volume_type is not supported before "
+ "microversion 2.67", six.text_type(ex))
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index 830ce53d..216241ec 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -624,6 +624,78 @@ class ShellTest(utils.TestCase):
'size=1,format=ext4,type=disk,shutdown=foobar '
'some-server' % FAKE_UUID_1))
+ def test_boot_from_volume_with_volume_type_old_microversion(self):
+ ex = self.assertRaises(
+ exceptions.CommandError, self.run_command,
+ 'boot --flavor 1 --block-device id=%s,source=image,dest=volume,'
+ 'size=1,bootindex=0,shutdown=remove,tag=foo,volume_type=lvm '
+ 'bfv-server' % FAKE_UUID_1, api_version='2.66')
+ self.assertIn("'volume_type' in block device mapping is not supported "
+ "in API version", six.text_type(ex))
+
+ def test_boot_from_volume_with_volume_type(self):
+ """Tests creating a volume-backed server from a source image and
+ specifying the type of volume to create with microversion 2.67.
+ """
+ self.run_command(
+ 'boot --flavor 1 --block-device id=%s,source=image,dest=volume,'
+ 'size=1,bootindex=0,shutdown=remove,tag=foo,volume_type=lvm '
+ 'bfv-server' % FAKE_UUID_1, api_version='2.67')
+ self.assert_called_anytime(
+ 'POST', '/servers',
+ {'server': {
+ 'flavorRef': '1',
+ 'name': 'bfv-server',
+ 'block_device_mapping_v2': [
+ {
+ 'uuid': FAKE_UUID_1,
+ 'source_type': 'image',
+ 'destination_type': 'volume',
+ 'volume_size': '1',
+ 'delete_on_termination': True,
+ 'tag': 'foo',
+ 'boot_index': '0',
+ 'volume_type': 'lvm'
+ },
+ ],
+ 'networks': 'auto',
+ 'imageRef': '',
+ 'min_count': 1,
+ 'max_count': 1,
+ }})
+
+ def test_boot_from_volume_without_volume_type_2_67(self):
+ """Tests creating a volume-backed server from a source image but
+ without specifying the type of volume to create with microversion 2.67.
+ The volume_type parameter should be omitted in the request to the
+ API server.
+ """
+ self.run_command(
+ 'boot --flavor 1 --block-device id=%s,source=image,dest=volume,'
+ 'size=1,bootindex=0,shutdown=remove,tag=foo bfv-server' %
+ FAKE_UUID_1, api_version='2.67')
+ self.assert_called_anytime(
+ 'POST', '/servers',
+ {'server': {
+ 'flavorRef': '1',
+ 'name': 'bfv-server',
+ 'block_device_mapping_v2': [
+ {
+ 'uuid': FAKE_UUID_1,
+ 'source_type': 'image',
+ 'destination_type': 'volume',
+ 'volume_size': '1',
+ 'delete_on_termination': True,
+ 'tag': 'foo',
+ 'boot_index': '0',
+ },
+ ],
+ 'networks': 'auto',
+ 'imageRef': '',
+ 'min_count': 1,
+ 'max_count': 1,
+ }})
+
def test_boot_metadata(self):
self.run_command('boot --image %s --flavor 1 --meta foo=bar=pants'
' --meta spam=eggs some-server ' % FAKE_UUID_1)
@@ -3913,6 +3985,7 @@ class ShellTest(utils.TestCase):
62, # There are no version-wrapped shell method changes for this.
63, # There are no version-wrapped shell method changes for this.
65, # There are no version-wrapped shell method changes for this.
+ 67, # There are no version-wrapped shell method changes for this.
])
versions_supported = set(range(0,
novaclient.API_MAX_VERSION.ver_minor + 1))
diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py
index d872fa01..e94f3567 100644
--- a/novaclient/v2/servers.py
+++ b/novaclient/v2/servers.py
@@ -1305,6 +1305,14 @@ class ServerManager(base.BootingManagerWithFind):
raise exceptions.UnsupportedAttribute("trusted_image_certificates",
"2.63")
+ if (block_device_mapping_v2 and
+ self.api_version < api_versions.APIVersion('2.67')):
+ for bdm in block_device_mapping_v2:
+ if bdm.get('volume_type'):
+ raise ValueError(
+ "Block device volume_type is not supported before "
+ "microversion 2.67")
+
boot_kwargs = dict(
meta=meta, files=files, userdata=userdata,
reservation_id=reservation_id, min_count=min_count,
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index ae7344bf..f6704559 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -71,6 +71,7 @@ CLIENT_BDM2_KEYS = {
'type': 'device_type',
'shutdown': 'delete_on_termination',
'tag': 'tag',
+ 'volume_type': 'volume_type' # added in 2.67
}
@@ -145,6 +146,8 @@ def _parse_block_device_mapping_v2(cs, args, image):
'delete_on_termination': False}
bdm.append(bdm_dict)
+ supports_volume_type = cs.api_version == api_versions.APIVersion('2.67')
+
for device_spec in args.block_device:
spec_dict = _parse_device_spec(device_spec)
bdm_dict = {}
@@ -155,6 +158,12 @@ def _parse_block_device_mapping_v2(cs, args, image):
"in API version %(version)s.")
% {'version': cs.api_version.get_string()})
+ if 'volume_type' in spec_dict and not supports_volume_type:
+ raise exceptions.CommandError(
+ _("'volume_type' in block device mapping is not supported "
+ "in API version %(version)s.")
+ % {'version': cs.api_version.get_string()})
+
for key, value in spec_dict.items():
bdm_dict[CLIENT_BDM2_KEYS[key]] = value
@@ -709,6 +718,7 @@ def _boot(cs, args):
action='append',
default=[],
start_version='2.42',
+ end_version='2.66',
help=_("Block device mapping with the keys: "
"id=UUID (image_id, snapshot_id or volume_id only if using source "
"image, snapshot or volume) "
@@ -733,6 +743,38 @@ def _boot(cs, args):
"for local destination set to remove) and "
"tag=device metadata tag (optional)."))
@utils.arg(
+ '--block-device',
+ metavar="key1=value1[,key2=value2...]",
+ action='append',
+ default=[],
+ start_version='2.67',
+ help=_("Block device mapping with the keys: "
+ "id=UUID (image_id, snapshot_id or volume_id only if using source "
+ "image, snapshot or volume) "
+ "source=source type (image, snapshot, volume or blank), "
+ "dest=destination type of the block device (volume or local), "
+ "bus=device's bus (e.g. uml, lxc, virtio, ...; if omitted, "
+ "hypervisor driver chooses a suitable default, "
+ "honoured only if device type is supplied) "
+ "type=device type (e.g. disk, cdrom, ...; defaults to 'disk') "
+ "device=name of the device (e.g. vda, xda, ...; "
+ "if omitted, hypervisor driver chooses suitable device "
+ "depending on selected bus; note the libvirt driver always "
+ "uses default device names), "
+ "size=size of the block device in MB(for swap) and in "
+ "GiB(for other formats) "
+ "(if omitted, hypervisor driver calculates size), "
+ "format=device will be formatted (e.g. swap, ntfs, ...; optional), "
+ "bootindex=integer used for ordering the boot disks "
+ "(for image backed instances it is equal to 0, "
+ "for others need to be specified), "
+ "shutdown=shutdown behaviour (either preserve or remove, "
+ "for local destination set to remove) and "
+ "tag=device metadata tag (optional), "
+ "volume_type=type of volume to create (either ID or name) when "
+ "source is blank, image or snapshot and dest is volume (optional)."
+ ))
+@utils.arg(
'--swap',
metavar="<swap_size>",
default=None,
diff --git a/releasenotes/notes/microversion-v2_67-da6d9b12730b8562.yaml b/releasenotes/notes/microversion-v2_67-da6d9b12730b8562.yaml
new file mode 100644
index 00000000..0c1e360a
--- /dev/null
+++ b/releasenotes/notes/microversion-v2_67-da6d9b12730b8562.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ Support is added for the `2.67 microversion`_ which allows specifying
+ a ``volume_type`` with the ``--block-device`` option on the ``nova boot``
+ command. The ``novaclient.v2.servers.ServerManager.create()`` method now
+ also supports a ``volume_type`` entry in the ``block_device_mapping_v2``
+ parameter.
+
+ .. _2.67 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id60