summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-09-01 18:15:52 +0000
committerGerrit Code Review <review@openstack.org>2022-09-01 18:15:52 +0000
commit7df94c9f821aa7fabef09cad9e6ab16ed66d46b6 (patch)
tree5c87a7554739dc42c59c12777fdeedc8f5973352 /openstackclient
parent5cf8f37a93ba60f8928e7bd9ca5572787e499898 (diff)
parent6e0699c1cf3e603850580a6bb5ca2e377fe1bc84 (diff)
downloadpython-openstackclient-7df94c9f821aa7fabef09cad9e6ab16ed66d46b6.tar.gz
Merge "Microversion 2.91: Support specifying destination host to unshelve"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/compute/v2/server.py39
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py179
2 files changed, 215 insertions, 3 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index b02ee6ff..0bcad8fc 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -4564,13 +4564,30 @@ class UnshelveServer(command.Command):
nargs='+',
help=_('Server(s) to unshelve (name or ID)'),
)
- parser.add_argument(
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument(
'--availability-zone',
default=None,
help=_('Name of the availability zone in which to unshelve a '
'SHELVED_OFFLOADED server (supported by '
'--os-compute-api-version 2.77 or above)'),
)
+ group.add_argument(
+ '--no-availability-zone',
+ action='store_true',
+ default=False,
+ help=_('Unpin the availability zone of a SHELVED_OFFLOADED '
+ 'server. Server will be unshelved on a host without '
+ 'availability zone constraint (supported by '
+ '--os-compute-api-version 2.91 or above)'),
+ )
+ parser.add_argument(
+ '--host',
+ default=None,
+ help=_('Name of the destination host in which to unshelve a '
+ 'SHELVED_OFFLOADED server (supported by '
+ '--os-compute-api-version 2.91 or above)'),
+ )
parser.add_argument(
'--wait',
action='store_true',
@@ -4599,6 +4616,26 @@ class UnshelveServer(command.Command):
kwargs['availability_zone'] = parsed_args.availability_zone
+ if parsed_args.host:
+ if compute_client.api_version < api_versions.APIVersion('2.91'):
+ msg = _(
+ '--os-compute-api-version 2.91 or greater is required '
+ 'to support the --host option'
+ )
+ raise exceptions.CommandError(msg)
+
+ kwargs['host'] = parsed_args.host
+
+ if parsed_args.no_availability_zone:
+ if compute_client.api_version < api_versions.APIVersion('2.91'):
+ msg = _(
+ '--os-compute-api-version 2.91 or greater is required '
+ 'to support the --no-availability-zone option'
+ )
+ raise exceptions.CommandError(msg)
+
+ kwargs['availability_zone'] = None
+
for server in parsed_args.server:
server_obj = utils.find_resource(
compute_client.servers,
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 004f3a05..ba86dff3 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -161,6 +161,10 @@ class TestServer(compute_fakes.TestComputev2):
return volumes
def run_method_with_servers(self, method_name, server_count):
+ # Starting with v2.91, the nova api needs to be call with a sentinel
+ # as availability_zone=None will unpin the server az.
+ _sentinel = object()
+
servers = self.setup_servers_mock(server_count)
arglist = []
@@ -183,7 +187,11 @@ class TestServer(compute_fakes.TestComputev2):
method.assert_called_with(reason=None)
elif method_name == 'unshelve':
version = self.app.client_manager.compute.api_version
- if version >= api_versions.APIVersion('2.77'):
+ if version >= api_versions.APIVersion('2.91'):
+ method.assert_called_with(availability_zone=_sentinel,
+ host=None)
+ elif (version >= api_versions.APIVersion('2.77') and
+ version < api_versions.APIVersion('2.91')):
method.assert_called_with(availability_zone=None)
else:
method.assert_called_with()
@@ -8204,7 +8212,23 @@ class TestServerUnshelve(TestServer):
def test_unshelve_multi_servers(self):
self.run_method_with_servers('unshelve', 3)
- def test_unshelve_with_specified_az(self):
+ def test_unshelve_v277(self):
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.77')
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [server.id]
+ verifylist = [('server', [server.id])]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+ server.unshelve.assert_called_with()
+
+ def test_unshelve_with_specified_az_v277(self):
self.app.client_manager.compute.api_version = \
api_versions.APIVersion('2.77')
@@ -8248,6 +8272,157 @@ class TestServerUnshelve(TestServer):
self.assertIn(
'--os-compute-api-version 2.77 or greater is required', str(ex))
+ def test_unshelve_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [server.id]
+ verifylist = [('server', [server.id])]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+ server.unshelve.assert_called_with()
+
+ def test_unshelve_with_specified_az_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [
+ '--availability-zone', "foo-az",
+ server.id,
+ ]
+ verifylist = [
+ ('availability_zone', "foo-az"),
+ ('server', [server.id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+ server.unshelve.assert_called_with(availability_zone="foo-az")
+
+ def test_unshelve_with_specified_host_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [
+ '--host', "server1",
+ server.id,
+ ]
+ verifylist = [
+ ('host', "server1"),
+ ('server', [server.id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+ server.unshelve.assert_called_with(host="server1")
+
+ def test_unshelve_with_unpin_az_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = ['--no-availability-zone', server.id]
+ verifylist = [
+ ('no_availability_zone', True),
+ ('server', [server.id])
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+ server.unshelve.assert_called_with(availability_zone=None)
+
+ def test_unshelve_with_specified_az_and_host_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [
+ '--host', "server1",
+ '--availability-zone', "foo-az",
+ server.id,
+ ]
+ verifylist = [
+ ('host', "server1"),
+ ('availability_zone', "foo-az"),
+ ('server', [server.id])
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+
+ def test_unshelve_with_unpin_az_and_host_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [
+ '--host', "server1",
+ '--no-availability-zone',
+ server.id,
+ ]
+ verifylist = [
+ ('host', "server1"),
+ ('no_availability_zone', True),
+ ('server', [server.id])
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(server.id)
+
+ def test_unshelve_fails_with_unpin_az_and_az_v291(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.91'))
+
+ server = compute_fakes.FakeServer.create_one_server(
+ attrs=self.attrs, methods=self.methods)
+ self.servers_mock.get.return_value = server
+ arglist = [
+ '--availability-zone', "foo-az",
+ '--no-availability-zone',
+ server.id,
+ ]
+ verifylist = [
+ ('availability_zone', "foo-az"),
+ ('no_availability_zone', True),
+ ('server', [server.id])
+ ]
+
+ ex = self.assertRaises(utils.ParserException,
+ self.check_parser,
+ self.cmd, arglist, verifylist)
+ self.assertIn('argument --no-availability-zone: not allowed '
+ 'with argument --availability-zone', str(ex))
+
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_unshelve_with_wait(self, mock_wait_for_status):
server = compute_fakes.FakeServer.create_one_server(