summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhangbailin <zhangbailin@inspur.com>2019-07-30 19:52:00 +0800
committerMatt Riedemann <mriedem.os@gmail.com>2019-09-09 12:43:42 -0400
commitcd396b8b61ed7496f4166a2237b27aa0a138f6e5 (patch)
tree26b72f48c3fd58fa23c139140478c86671cda4e6
parentaae95dcc7a79be019fc304ced76a351c16382ede (diff)
downloadpython-novaclient-cd396b8b61ed7496f4166a2237b27aa0a138f6e5.tar.gz
Microversion 2.79: Add delete_on_termination to volume-attach API15.1.0
Support add 'delete_on_termination' field to the voume attach API to support configuring whether to delete the data volume when the server is destroyed. * Updating the ``nova volume-attachments`` command to show the ``delete_on_termination`` value if 2.79 or greater is used. * The '--delete-on-termination' option is added to the `nova volume-attach` CLI. Depends-On: https://review.opendev.org/#/c/673133/ Part of blueprint support-delete-on-termination-in-server-attach-volume Change-Id: I8dcf2fd21a2fd99ca4e05bd953fbbe026be3a619
-rw-r--r--doc/source/cli/nova.rst8
-rw-r--r--novaclient/__init__.py2
-rw-r--r--novaclient/tests/unit/v2/fakes.py11
-rw-r--r--novaclient/tests/unit/v2/test_shell.py36
-rw-r--r--novaclient/tests/unit/v2/test_volumes.py31
-rw-r--r--novaclient/v2/shell.py13
-rw-r--r--novaclient/v2/volumes.py30
-rw-r--r--releasenotes/notes/microversion-v2_79-f13bc0414743dc16.yaml16
8 files changed, 144 insertions, 3 deletions
diff --git a/doc/source/cli/nova.rst b/doc/source/cli/nova.rst
index ab310758..007e9686 100644
--- a/doc/source/cli/nova.rst
+++ b/doc/source/cli/nova.rst
@@ -3849,7 +3849,8 @@ nova volume-attach
.. code-block:: console
- usage: nova volume-attach [--tag <tag>] <server> <volume> [<device>]
+ usage: nova volume-attach [--delete-on-termination] [--tag <tag>]
+ <server> <volume> [<device>]
Attach a volume to a server.
@@ -3870,6 +3871,11 @@ Attach a volume to a server.
``--tag <tag>``
Tag for the attached volume. (Supported by API versions '2.49' - '2.latest')
+``--delete-on-termination``
+ Specify if the attached volume sholud be deleted when the server is
+ destroyed. By default the attached volume is not deleted when the server is
+ destroyed. (Supported by API versions '2.79' - '2.latest')
+
.. _nova_volume-attachments:
nova volume-attachments
diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index 3e5daf21..a4f9b4ee 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.78")
+API_MAX_VERSION = api_versions.APIVersion("2.79")
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index d6fbf129..dd60d7f4 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -2115,6 +2115,11 @@ class FakeSessionClient(base_client.SessionClient):
if self.api_version >= api_versions.APIVersion('2.70'):
# Include the "tag" field in the response.
attachment['tag'] = 'test-tag'
+
+ if self.api_version >= api_versions.APIVersion('2.79'):
+ # Include the "delete_on_termination" field in the
+ # response.
+ attachment['delete_on_termination'] = True
return (200, FAKE_RESPONSE_HEADERS, {"volumeAttachment": attachment})
def put_servers_1234_os_volume_attachments_Work(self, **kw):
@@ -2139,6 +2144,12 @@ class FakeSessionClient(base_client.SessionClient):
# Include the "tag" field in each attachment.
for attachment in attachments['volumeAttachments']:
attachment['tag'] = 'test-tag'
+
+ if self.api_version >= api_versions.APIVersion('2.79'):
+ # Include the "delete_on_termination" field in each
+ # attachment.
+ for attachment in attachments['volumeAttachments']:
+ attachment['delete_on_termination'] = True
return (200, FAKE_RESPONSE_HEADERS, attachments)
def get_servers_1234_os_volume_attachments_Work(self, **kw):
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index 928a9de4..a57c3794 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -3825,6 +3825,42 @@ class ShellTest(utils.TestCase):
'tag': 'test-tag'}})
self.assertIn('test-tag', out)
+ def test_volume_attachments_pre_v2_79(self):
+ out = self.run_command(
+ 'volume-attachments 1234', api_version='2.78')[0]
+ self.assert_called('GET', '/servers/1234/os-volume_attachments')
+ self.assertNotIn('DELETE ON TERMINATION', out)
+
+ def test_volume_attachments_v2_79(self):
+ out = self.run_command(
+ 'volume-attachments 1234', api_version='2.79')[0]
+ self.assert_called('GET', '/servers/1234/os-volume_attachments')
+ self.assertIn('DELETE ON TERMINATION', out)
+
+ def test_volume_attach_with_delete_on_termination_pre_v2_79(self):
+ self.assertRaises(
+ SystemExit, self.run_command,
+ 'volume-attach --delete-on-termination sample-server '
+ 'Work /dev/vdb', api_version='2.78')
+
+ def test_volume_attach_with_delete_on_termination_v2_79(self):
+ out = self.run_command(
+ 'volume-attach --delete-on-termination sample-server '
+ '2 /dev/vdb', api_version='2.79')[0]
+ self.assert_called('POST', '/servers/1234/os-volume_attachments',
+ {'volumeAttachment':
+ {'device': '/dev/vdb',
+ 'volumeId': '2',
+ 'delete_on_termination': True}})
+ self.assertIn('delete_on_termination', out)
+
+ def test_volume_attach_without_delete_on_termination(self):
+ self.run_command('volume-attach sample-server Work',
+ api_version='2.79')
+ self.assert_called('POST', '/servers/1234/os-volume_attachments',
+ {'volumeAttachment':
+ {'volumeId': 'Work'}})
+
def test_volume_update(self):
self.run_command('volume-update sample-server Work Work')
self.assert_called('PUT', '/servers/1234/os-volume_attachments/Work',
diff --git a/novaclient/tests/unit/v2/test_volumes.py b/novaclient/tests/unit/v2/test_volumes.py
index 932b71d7..fbc55ddf 100644
--- a/novaclient/tests/unit/v2/test_volumes.py
+++ b/novaclient/tests/unit/v2/test_volumes.py
@@ -14,6 +14,7 @@
# under the License.
import mock
+import six
from novaclient import api_versions
from novaclient.tests.unit import utils
@@ -126,3 +127,33 @@ class VolumesV249Test(VolumesTest):
volume_id=None,
attachment_id="Work")
mock_warn.assert_called_once()
+
+
+class VolumesV279Test(VolumesV249Test):
+ api_version = "2.79"
+
+ def test_create_server_volume_with_delete_on_termination(self):
+ v = self.cs.volumes.create_server_volume(
+ server_id=1234,
+ volume_id='15e59938-07d5-11e1-90e3-e3dffe0c5983',
+ device='/dev/vdb',
+ tag='tag1',
+ delete_on_termination=True
+ )
+ self.assert_request_id(v, fakes.FAKE_REQUEST_ID_LIST)
+ self.cs.assert_called(
+ 'POST', '/servers/1234/os-volume_attachments',
+ {'volumeAttachment': {
+ 'volumeId': '15e59938-07d5-11e1-90e3-e3dffe0c5983',
+ 'device': '/dev/vdb',
+ 'tag': 'tag1',
+ 'delete_on_termination': True}})
+ self.assertIsInstance(v, volumes.Volume)
+
+ def test_create_server_volume_with_delete_on_termination_pre_v279(self):
+ self.cs.api_version = api_versions.APIVersion('2.78')
+ ex = self.assertRaises(
+ TypeError, self.cs.volumes.create_server_volume, "1234",
+ volume_id='15e59938-07d5-11e1-90e3-e3dffe0c5983',
+ delete_on_termination=True)
+ self.assertIn('delete_on_termination', six.text_type(ex))
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index acaf1783..2dfd5c92 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -2633,6 +2633,13 @@ def _translate_volume_attachments_keys(collection):
default=None,
help=_('Tag for the attached volume.'),
start_version="2.49")
+@utils.arg(
+ '--delete-on-termination',
+ action='store_true',
+ default=False,
+ help=_('Specify if the attached volume should be deleted '
+ 'when the server is destroyed.'),
+ start_version="2.79")
def do_volume_attach(cs, args):
"""Attach a volume to a server."""
if args.device == 'auto':
@@ -2642,6 +2649,9 @@ def do_volume_attach(cs, args):
if 'tag' in args and args.tag:
update_kwargs['tag'] = args.tag
+ if 'delete_on_termination' in args and args.delete_on_termination:
+ update_kwargs['delete_on_termination'] = args.delete_on_termination
+
volume = cs.volumes.create_server_volume(_find_server(cs, args.server).id,
args.volume,
args.device,
@@ -2699,6 +2709,9 @@ def do_volume_attachments(cs, args):
fields = ['ID', 'DEVICE', 'SERVER ID', 'VOLUME ID']
if cs.api_version >= api_versions.APIVersion('2.70'):
fields.append('TAG')
+ # Microversion >= 2.79 returns the delete_on_termination value.
+ if cs.api_version >= api_versions.APIVersion('2.79'):
+ fields.append('DELETE ON TERMINATION')
utils.print_list(volumes, fields)
diff --git a/novaclient/v2/volumes.py b/novaclient/v2/volumes.py
index d6208cbd..8fc75565 100644
--- a/novaclient/v2/volumes.py
+++ b/novaclient/v2/volumes.py
@@ -55,7 +55,7 @@ class VolumeManager(base.Manager):
return self._create("/servers/%s/os-volume_attachments" % server_id,
body, "volumeAttachment")
- @api_versions.wraps("2.49")
+ @api_versions.wraps("2.49", "2.78")
def create_server_volume(self, server_id, volume_id, device=None,
tag=None):
"""
@@ -75,6 +75,34 @@ class VolumeManager(base.Manager):
return self._create("/servers/%s/os-volume_attachments" % server_id,
body, "volumeAttachment")
+ @api_versions.wraps("2.79")
+ def create_server_volume(self, server_id, volume_id, device=None,
+ tag=None, delete_on_termination=False):
+ """
+ Attach a volume identified by the volume ID to the given server ID
+
+ :param server_id: The ID of the server.
+ :param volume_id: The ID of the volume to attach.
+ :param device: The device name (optional).
+ :param tag: The tag (optional).
+ :param delete_on_termination: Marked whether to delete the attached
+ volume when the server is deleted
+ (optional).
+ :rtype: :class:`Volume`
+ """
+ # TODO(mriedem): Move this body construction into a private common
+ # helper method for all versions of create_server_volume to use.
+ body = {'volumeAttachment': {'volumeId': volume_id}}
+ if device is not None:
+ body['volumeAttachment']['device'] = device
+ if tag is not None:
+ body['volumeAttachment']['tag'] = tag
+ if delete_on_termination:
+ body['volumeAttachment']['delete_on_termination'] = (
+ delete_on_termination)
+ return self._create("/servers/%s/os-volume_attachments" % server_id,
+ body, "volumeAttachment")
+
def update_server_volume(self, server_id, src_volid, dest_volid):
"""
Swaps the existing volume attachment to point to a new volume.
diff --git a/releasenotes/notes/microversion-v2_79-f13bc0414743dc16.yaml b/releasenotes/notes/microversion-v2_79-f13bc0414743dc16.yaml
new file mode 100644
index 00000000..ca81f58d
--- /dev/null
+++ b/releasenotes/notes/microversion-v2_79-f13bc0414743dc16.yaml
@@ -0,0 +1,16 @@
+---
+features:
+ - |
+ Added support for `microversion 2.79`_ which includes the following
+ changes:
+
+ - The ``--delete-on-termination`` option is added to the
+ ``nova volume-attach`` CLI.
+ - A ``DELETE ON TERMINATION`` column is added to the
+ ``nova volume-attachments`` table.
+ - New kwarg called ``delete_on_termination`` added to the python API
+ binding:
+
+ - ``novaclient.v2.volumes.VolumeManager.create_server_volume()``
+
+ .. _microversion 2.79: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id71