Merge "compute: Add 'server volume update' command"
This commit is contained in:
commit
3864ceea26
@ -71,7 +71,7 @@ python-cinderclient==3.3.0
|
|||||||
python-dateutil==2.5.3
|
python-dateutil==2.5.3
|
||||||
python-keystoneclient==3.22.0
|
python-keystoneclient==3.22.0
|
||||||
python-mimeparse==1.6.0
|
python-mimeparse==1.6.0
|
||||||
python-novaclient==15.1.0
|
python-novaclient==17.0.0
|
||||||
python-subunit==1.0.0
|
python-subunit==1.0.0
|
||||||
pytz==2013.6
|
pytz==2013.6
|
||||||
PyYAML==3.13
|
PyYAML==3.13
|
||||||
|
@ -513,27 +513,27 @@ class AddServerVolume(command.Command):
|
|||||||
'--tag',
|
'--tag',
|
||||||
metavar='<tag>',
|
metavar='<tag>',
|
||||||
help=_(
|
help=_(
|
||||||
"Tag for the attached volume. "
|
'Tag for the attached volume '
|
||||||
"(Supported by API versions '2.49' - '2.latest')"
|
'(supported by --os-compute-api-version 2.49 or above)'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
# TODO(stephenfin): These should be called 'delete-on-termination' and
|
||||||
|
# 'preserve-on-termination'
|
||||||
termination_group = parser.add_mutually_exclusive_group()
|
termination_group = parser.add_mutually_exclusive_group()
|
||||||
termination_group.add_argument(
|
termination_group.add_argument(
|
||||||
'--enable-delete-on-termination',
|
'--enable-delete-on-termination',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=_(
|
help=_(
|
||||||
"Specify if the attached volume should be deleted when the "
|
'Delete the volume when the server is destroyed '
|
||||||
"server is destroyed. "
|
'(supported by --os-compute-api-version 2.79 or above)'
|
||||||
"(Supported by API versions '2.79' - '2.latest')"
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
termination_group.add_argument(
|
termination_group.add_argument(
|
||||||
'--disable-delete-on-termination',
|
'--disable-delete-on-termination',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=_(
|
help=_(
|
||||||
"Specify if the attached volume should not be deleted when "
|
'Do not delete the volume when the server is destroyed '
|
||||||
"the server is destroyed. "
|
'(supported by --os-compute-api-version 2.79 or above)'
|
||||||
"(Supported by API versions '2.79' - '2.latest')"
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
from novaclient import api_versions
|
from novaclient import api_versions
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
|
from osc_lib import exceptions
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
|
|
||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
@ -71,3 +72,69 @@ class ListServerVolume(command.Lister):
|
|||||||
) for s in volumes
|
) for s in volumes
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateServerVolume(command.Command):
|
||||||
|
"""Update a volume attachment on the server."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(UpdateServerVolume, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'server',
|
||||||
|
help=_('Server to update volume for (name or ID)'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'volume',
|
||||||
|
help=_('Volume (ID)'),
|
||||||
|
)
|
||||||
|
termination_group = parser.add_mutually_exclusive_group()
|
||||||
|
termination_group.add_argument(
|
||||||
|
'--delete-on-termination',
|
||||||
|
action='store_true',
|
||||||
|
dest='delete_on_termination',
|
||||||
|
default=None,
|
||||||
|
help=_(
|
||||||
|
'Delete the volume when the server is destroyed '
|
||||||
|
'(supported by --os-compute-api-version 2.85 or above)'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
termination_group.add_argument(
|
||||||
|
'--preserve-on-termination',
|
||||||
|
action='store_false',
|
||||||
|
dest='delete_on_termination',
|
||||||
|
help=_(
|
||||||
|
'Preserve the volume when the server is destroyed '
|
||||||
|
'(supported by --os-compute-api-version 2.85 or above)'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
|
||||||
|
compute_client = self.app.client_manager.compute
|
||||||
|
|
||||||
|
if parsed_args.delete_on_termination is not None:
|
||||||
|
if compute_client.api_version < api_versions.APIVersion('2.85'):
|
||||||
|
msg = _(
|
||||||
|
'--os-compute-api-version 2.85 or greater is required to '
|
||||||
|
'support the --(no-)delete-on-termination option'
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
server = utils.find_resource(
|
||||||
|
compute_client.servers,
|
||||||
|
parsed_args.server,
|
||||||
|
)
|
||||||
|
|
||||||
|
# NOTE(stephenfin): This may look silly, and that's because it is.
|
||||||
|
# This API was originally used only for the swapping volumes, which
|
||||||
|
# is an internal operation that should only be done by
|
||||||
|
# orchestration software rather than a human. We're not going to
|
||||||
|
# expose that, but we are going to expose the ability to change the
|
||||||
|
# delete on termination behavior.
|
||||||
|
compute_client.volumes.update_server_volume(
|
||||||
|
server.id,
|
||||||
|
parsed_args.volume,
|
||||||
|
parsed_args.volume,
|
||||||
|
delete_on_termination=parsed_args.delete_on_termination,
|
||||||
|
)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
from novaclient import api_versions
|
from novaclient import api_versions
|
||||||
|
from osc_lib import exceptions
|
||||||
|
|
||||||
from openstackclient.compute.v2 import server_volume
|
from openstackclient.compute.v2 import server_volume
|
||||||
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
|
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
|
||||||
@ -165,3 +166,122 @@ class TestServerVolumeList(TestServerVolume):
|
|||||||
)
|
)
|
||||||
self.servers_volumes_mock.get_server_volumes.assert_called_once_with(
|
self.servers_volumes_mock.get_server_volumes.assert_called_once_with(
|
||||||
self.server.id)
|
self.server.id)
|
||||||
|
|
||||||
|
|
||||||
|
class TestServerVolumeUpdate(TestServerVolume):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.server = compute_fakes.FakeServer.create_one_server()
|
||||||
|
self.servers_mock.get.return_value = self.server
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = server_volume.UpdateServerVolume(self.app, None)
|
||||||
|
|
||||||
|
def test_server_volume_update(self):
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'foo',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('volume', 'foo'),
|
||||||
|
('delete_on_termination', None),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# This is a no-op
|
||||||
|
self.servers_volumes_mock.update_server_volume.assert_not_called()
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_volume_update_with_delete_on_termination(self):
|
||||||
|
self.app.client_manager.compute.api_version = \
|
||||||
|
api_versions.APIVersion('2.85')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'foo',
|
||||||
|
'--delete-on-termination',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('volume', 'foo'),
|
||||||
|
('delete_on_termination', True),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.servers_volumes_mock.update_server_volume.assert_called_once_with(
|
||||||
|
self.server.id, 'foo', 'foo',
|
||||||
|
delete_on_termination=True)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_volume_update_with_preserve_on_termination(self):
|
||||||
|
self.app.client_manager.compute.api_version = \
|
||||||
|
api_versions.APIVersion('2.85')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'foo',
|
||||||
|
'--preserve-on-termination',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('volume', 'foo'),
|
||||||
|
('delete_on_termination', False),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.servers_volumes_mock.update_server_volume.assert_called_once_with(
|
||||||
|
self.server.id, 'foo', 'foo',
|
||||||
|
delete_on_termination=False)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_volume_update_with_delete_on_termination_pre_v285(self):
|
||||||
|
self.app.client_manager.compute.api_version = \
|
||||||
|
api_versions.APIVersion('2.84')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'foo',
|
||||||
|
'--delete-on-termination',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('volume', 'foo'),
|
||||||
|
('delete_on_termination', True),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
def test_server_volume_update_with_preserve_on_termination_pre_v285(self):
|
||||||
|
self.app.client_manager.compute.api_version = \
|
||||||
|
api_versions.APIVersion('2.84')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'foo',
|
||||||
|
'--preserve-on-termination',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('volume', 'foo'),
|
||||||
|
('delete_on_termination', False),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
@ -3,3 +3,6 @@ features:
|
|||||||
- |
|
- |
|
||||||
Add ``server volume list`` command, to list the volumes attached to an
|
Add ``server volume list`` command, to list the volumes attached to an
|
||||||
instance.
|
instance.
|
||||||
|
- |
|
||||||
|
Add ``server volume update`` command, to update the volumes attached to
|
||||||
|
an instance.
|
||||||
|
@ -9,6 +9,6 @@ openstacksdk>=0.52.0 # Apache-2.0
|
|||||||
osc-lib>=2.3.0 # Apache-2.0
|
osc-lib>=2.3.0 # Apache-2.0
|
||||||
oslo.i18n>=3.15.3 # Apache-2.0
|
oslo.i18n>=3.15.3 # Apache-2.0
|
||||||
python-keystoneclient>=3.22.0 # Apache-2.0
|
python-keystoneclient>=3.22.0 # Apache-2.0
|
||||||
python-novaclient>=15.1.0 # Apache-2.0
|
python-novaclient>=17.0.0 # Apache-2.0
|
||||||
python-cinderclient>=3.3.0 # Apache-2.0
|
python-cinderclient>=3.3.0 # Apache-2.0
|
||||||
stevedore>=2.0.1 # Apache-2.0
|
stevedore>=2.0.1 # Apache-2.0
|
||||||
|
@ -154,6 +154,7 @@ openstack.compute.v2 =
|
|||||||
server_image_create = openstackclient.compute.v2.server_image:CreateServerImage
|
server_image_create = openstackclient.compute.v2.server_image:CreateServerImage
|
||||||
|
|
||||||
server_volume_list = openstackclient.compute.v2.server_volume:ListServerVolume
|
server_volume_list = openstackclient.compute.v2.server_volume:ListServerVolume
|
||||||
|
server_volume_update = openstackclient.compute.v2.server_volume:UpdateServerVolume
|
||||||
|
|
||||||
usage_list = openstackclient.compute.v2.usage:ListUsage
|
usage_list = openstackclient.compute.v2.usage:ListUsage
|
||||||
usage_show = openstackclient.compute.v2.usage:ShowUsage
|
usage_show = openstackclient.compute.v2.usage:ShowUsage
|
||||||
|
Loading…
Reference in New Issue
Block a user