compute: Migrate 'server set', 'server unset' commands

Change-Id: I2c249e9ca3952100dcf7f97fcafa879b733d34c6
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2024-05-08 18:36:53 +01:00
parent c8621e5b8b
commit bcaf2ab559
4 changed files with 247 additions and 141 deletions
openstackclient
compute/v2
tests/unit/compute/v2
releasenotes/notes
requirements.txt

@ -4415,14 +4415,13 @@ class SetServer(command.Command):
return parser
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server = utils.find_resource(
compute_client.servers,
parsed_args.server,
compute_client = self.app.client_manager.sdk_connection.compute
server = compute_client.find_server(
parsed_args.server, ignore_missing=False
)
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion("2.19"):
if not sdk_utils.supports_microversion(compute_client, '2.19'):
msg = _(
'--os-compute-api-version 2.19 or greater is required to '
'support the --description option'
@ -4430,7 +4429,7 @@ class SetServer(command.Command):
raise exceptions.CommandError(msg)
if parsed_args.tags:
if compute_client.api_version < api_versions.APIVersion('2.26'):
if not sdk_utils.supports_microversion(compute_client, '2.26'):
msg = _(
'--os-compute-api-version 2.26 or greater is required to '
'support the --tag option'
@ -4438,7 +4437,7 @@ class SetServer(command.Command):
raise exceptions.CommandError(msg)
if parsed_args.hostname:
if compute_client.api_version < api_versions.APIVersion('2.90'):
if not sdk_utils.supports_microversion(compute_client, '2.90'):
msg = _(
'--os-compute-api-version 2.90 or greater is required to '
'support the --hostname option'
@ -4457,30 +4456,32 @@ class SetServer(command.Command):
update_kwargs['hostname'] = parsed_args.hostname
if update_kwargs:
server.update(**update_kwargs)
compute_client.update_server(server, **update_kwargs)
if parsed_args.properties:
compute_client.servers.set_meta(server, parsed_args.properties)
compute_client.set_server_metadata(
server, **parsed_args.properties
)
if parsed_args.state:
server.reset_state(state=parsed_args.state)
compute_client.reset_server_state(server, state=parsed_args.state)
if parsed_args.root_password:
p1 = getpass.getpass(_('New password: '))
p2 = getpass.getpass(_('Retype new password: '))
if p1 == p2:
server.change_password(p1)
compute_client.change_server_password(server, p1)
else:
msg = _("Passwords do not match, password unchanged")
raise exceptions.CommandError(msg)
elif parsed_args.password:
server.change_password(parsed_args.password)
compute_client.change_server_password(server, parsed_args.password)
elif parsed_args.no_password:
server.clear_password()
compute_client.clear_server_password(server)
if parsed_args.tags:
for tag in parsed_args.tags:
server.add_tag(tag=tag)
compute_client.add_tag_to_server(server, tag=tag)
class ShelveServer(command.Command):
@ -4995,7 +4996,8 @@ class UnsetServer(command.Command):
metavar='<server>',
help=_('Server (name or ID)'),
)
parser.add_argument(
property_group = parser.add_mutually_exclusive_group()
property_group.add_argument(
'--property',
metavar='<key>',
action='append',
@ -5006,16 +5008,22 @@ class UnsetServer(command.Command):
'(repeat option to remove multiple values)'
),
)
property_group.add_argument(
'--all-properties',
action='store_true',
help=_('Remove all properties'),
)
parser.add_argument(
'--description',
dest='description',
action='store_true',
help=_(
'Unset server description (supported by '
'--os-compute-api-version 2.19 or above)'
'Unset server description '
'(supported by --os-compute-api-version 2.19 or above)'
),
)
parser.add_argument(
tag_group = parser.add_mutually_exclusive_group()
tag_group.add_argument(
'--tag',
metavar='<tag>',
action='append',
@ -5027,32 +5035,40 @@ class UnsetServer(command.Command):
'(supported by --os-compute-api-version 2.26 or above)'
),
)
tag_group.add_argument(
'--all-tags',
action='store_true',
help=_(
'Remove all tags '
'(supported by --os-compute-api-version 2.26 or above)'
),
)
return parser
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server = utils.find_resource(
compute_client.servers,
parsed_args.server,
compute_client = self.app.client_manager.sdk_connection.compute
server = compute_client.find_server(
parsed_args.server, ignore_missing=False
)
if parsed_args.properties:
compute_client.servers.delete_meta(server, parsed_args.properties)
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion("2.19"):
msg = _(
'--os-compute-api-version 2.19 or greater is '
'required to support the --description option'
)
raise exceptions.CommandError(msg)
compute_client.servers.update(
server,
description="",
if parsed_args.properties or parsed_args.all_properties:
compute_client.delete_server_metadata(
server, parsed_args.properties or None
)
if parsed_args.tags:
if compute_client.api_version < api_versions.APIVersion('2.26'):
if parsed_args.description:
if not sdk_utils.supports_microversion(compute_client, '2.19'):
msg = _(
'--os-compute-api-version 2.19 or greater is required to '
'support the --description option'
)
raise exceptions.CommandError(msg)
compute_client.update_server(server, description="")
if parsed_args.tags or parsed_args.all_tags:
if not sdk_utils.supports_microversion(compute_client, '2.26'):
msg = _(
'--os-compute-api-version 2.26 or greater is required to '
'support the --tag option'
@ -5060,7 +5076,10 @@ class UnsetServer(command.Command):
raise exceptions.CommandError(msg)
for tag in parsed_args.tags:
compute_client.servers.delete_tag(server, tag=tag)
compute_client.remove_tag_from_server(server, tag)
if parsed_args.all_tags:
compute_client.remove_tags_from_server(server)
class UnshelveServer(command.Command):

@ -7843,62 +7843,60 @@ class TestServerSet(TestServer):
def setUp(self):
super().setUp()
self.attrs = {
'api_version': None,
}
self.methods = {
'update': None,
'reset_state': None,
'change_password': None,
'clear_password': None,
'add_tag': None,
'set_tags': None,
}
self.fake_servers = self.setup_servers_mock(2)
self.server = compute_fakes.create_one_sdk_server()
self.compute_sdk_client.find_server.return_value = self.server
# Get the command object to test
self.cmd = server.SetServer(self.app, None)
def test_server_set_no_option(self):
arglist = ['foo_vm']
verifylist = [('server', 'foo_vm')]
arglist = [self.server.id]
verifylist = [('server', self.server.id)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.assertNotCalled(self.fake_servers[0].update)
self.assertNotCalled(self.fake_servers[0].reset_state)
self.assertNotCalled(self.fake_servers[0].change_password)
self.assertNotCalled(self.servers_mock.set_meta)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_state(self):
for index, state in enumerate(['active', 'error']):
arglist = [
'--state',
state,
'foo_vm',
]
verifylist = [
('state', state),
('server', 'foo_vm'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[index].reset_state.assert_called_once_with(
state=state
)
self.assertIsNone(result)
arglist = [
'--state',
'active',
self.server.id,
]
verifylist = [
('state', 'active'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.compute_sdk_client.reset_server_state.assert_called_once_with(
self.server, state='active'
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_invalid_state(self):
arglist = [
'--state',
'foo_state',
'foo_vm',
self.server.id,
]
verifylist = [
('state', 'foo_state'),
('server', 'foo_vm'),
('server', self.server.id),
]
self.assertRaises(
test_utils.ParserException,
@ -7912,15 +7910,24 @@ class TestServerSet(TestServer):
arglist = [
'--name',
'foo_name',
'foo_vm',
self.server.id,
]
verifylist = [
('name', 'foo_name'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[0].update.assert_called_once_with(name='foo_name')
self.compute_sdk_client.update_server.assert_called_once_with(
self.server, name='foo_name'
)
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_property(self):
@ -7929,49 +7936,72 @@ class TestServerSet(TestServer):
'key1=value1',
'--property',
'key2=value2',
'foo_vm',
self.server.id,
]
verifylist = [
('properties', {'key1': 'value1', 'key2': 'value2'}),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.servers_mock.set_meta.assert_called_once_with(
self.fake_servers[0], parsed_args.properties
self.compute_sdk_client.set_server_metadata.assert_called_once_with(
self.server, key1='value1', key2='value2'
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_password(self):
arglist = [
'--password',
'foo',
'foo_vm',
self.server.id,
]
verifylist = [
('password', 'foo'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.cmd.take_action(parsed_args)
self.fake_servers[0].change_password.assert_called_once_with('foo')
self.compute_sdk_client.change_server_password.assert_called_once_with(
self.server, 'foo'
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_no_password(self):
arglist = [
'--no-password',
'foo_vm',
self.server.id,
]
verifylist = [
('no_password', True),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.cmd.take_action(parsed_args)
self.fake_servers[0].clear_password.assert_called_once_with()
self.compute_sdk_client.clear_server_password.assert_called_once_with(
self.server
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
# TODO(stephenfin): Remove this in a future major version
@mock.patch.object(
@ -7980,17 +8010,24 @@ class TestServerSet(TestServer):
def test_server_set_with_root_password(self, mock_getpass):
arglist = [
'--root-password',
'foo_vm',
self.server.id,
]
verifylist = [
('root_password', True),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[0].change_password.assert_called_once_with(
mock.sentinel.fake_pass
self.compute_sdk_client.change_server_password.assert_called_once_with(
self.server, mock.sentinel.fake_pass
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_description(self):
@ -7999,17 +8036,24 @@ class TestServerSet(TestServer):
arglist = [
'--description',
'foo_description',
'foo_vm',
self.server.id,
]
verifylist = [
('description', 'foo_description'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[0].update.assert_called_once_with(
description='foo_description'
self.compute_sdk_client.update_server.assert_called_once_with(
self.server, description='foo_description'
)
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_description_pre_v219(self):
@ -8018,12 +8062,13 @@ class TestServerSet(TestServer):
arglist = [
'--description',
'foo_description',
'foo_vm',
self.server.id,
]
verifylist = [
('description', 'foo_description'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
@ -8037,22 +8082,27 @@ class TestServerSet(TestServer):
'tag1',
'--tag',
'tag2',
'foo_vm',
self.server.id,
]
verifylist = [
('tags', ['tag1', 'tag2']),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[0].add_tag.assert_has_calls(
self.compute_sdk_client.add_tag_to_server.assert_has_calls(
[
mock.call(tag='tag1'),
mock.call(tag='tag2'),
mock.call(self.server, tag='tag1'),
mock.call(self.server, tag='tag2'),
]
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_tag_pre_v226(self):
@ -8063,14 +8113,14 @@ class TestServerSet(TestServer):
'tag1',
'--tag',
'tag2',
'foo_vm',
self.server.id,
]
verifylist = [
('tags', ['tag1', 'tag2']),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
ex = self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -8084,17 +8134,24 @@ class TestServerSet(TestServer):
arglist = [
'--hostname',
'foo-hostname',
'foo_vm',
self.server.id,
]
verifylist = [
('hostname', 'foo-hostname'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.fake_servers[0].update.assert_called_once_with(
hostname='foo-hostname'
self.compute_sdk_client.update_server.assert_called_once_with(
self.server, hostname='foo-hostname'
)
self.compute_sdk_client.set_server_metadata.assert_not_called()
self.compute_sdk_client.reset_server_state.assert_not_called()
self.compute_sdk_client.change_server_password.assert_not_called()
self.compute_sdk_client.clear_server_password.assert_not_called()
self.compute_sdk_client.add_tag_to_server.assert_not_called()
self.assertIsNone(result)
def test_server_set_with_hostname_pre_v290(self):
@ -8103,11 +8160,11 @@ class TestServerSet(TestServer):
arglist = [
'--hostname',
'foo-hostname',
'foo_vm',
self.server.id,
]
verifylist = [
('hostname', 'foo-hostname'),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
@ -8718,21 +8775,29 @@ class TestServerUnset(TestServer):
def setUp(self):
super().setUp()
self.fake_server = self.setup_servers_mock(1)[0]
self.server = compute_fakes.create_one_sdk_server()
self.compute_sdk_client.find_server.return_value = self.server
# Get the command object to test
self.cmd = server.UnsetServer(self.app, None)
def test_server_unset_no_option(self):
arglist = [
'foo_vm',
self.server.id,
]
verifylist = [
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.assertNotCalled(self.servers_mock.delete_meta)
self.compute_sdk_client.find_server(
self.server.id, ignore_missing=False
)
self.compute_sdk_client.delete_server_metadata.assert_not_called()
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.remove_tag_from_server.assert_not_called()
self.assertIsNone(result)
def test_server_unset_with_property(self):
@ -8741,17 +8806,25 @@ class TestServerUnset(TestServer):
'key1',
'--property',
'key2',
'foo_vm',
self.server.id,
]
verifylist = [
('properties', ['key1', 'key2']),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.servers_mock.delete_meta.assert_called_once_with(
self.fake_server, ['key1', 'key2']
self.compute_sdk_client.find_server(
self.server.id, ignore_missing=False
)
self.compute_sdk_client.delete_server_metadata.assert_called_once_with(
self.server,
['key1', 'key2'],
)
self.compute_sdk_client.update_server.assert_not_called()
self.compute_sdk_client.remove_tag_from_server.assert_not_called()
self.assertIsNone(result)
def test_server_unset_with_description(self):
@ -8760,19 +8833,24 @@ class TestServerUnset(TestServer):
arglist = [
'--description',
'foo_vm',
self.server.id,
]
verifylist = [
('description', True),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.servers_mock.update.assert_called_once_with(
self.fake_server, description=""
self.compute_sdk_client.find_server(
self.server.id, ignore_missing=False
)
self.compute_sdk_client.update_server.assert_called_once_with(
self.server, description=''
)
self.compute_sdk_client.delete_server_metadata.assert_not_called()
self.compute_sdk_client.remove_tag_from_server.assert_not_called()
self.assertIsNone(result)
def test_server_unset_with_description_pre_v219(self):
@ -8781,11 +8859,11 @@ class TestServerUnset(TestServer):
arglist = [
'--description',
'foo_vm',
self.server.id,
]
verifylist = [
('description', True),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -8804,23 +8882,28 @@ class TestServerUnset(TestServer):
'tag1',
'--tag',
'tag2',
'foo_vm',
self.server.id,
]
verifylist = [
('tags', ['tag1', 'tag2']),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.assertIsNone(result)
self.servers_mock.delete_tag.assert_has_calls(
self.compute_sdk_client.find_server(
self.server.id, ignore_missing=False
)
self.compute_sdk_client.remove_tag_from_server.assert_has_calls(
[
mock.call(self.fake_server, tag='tag1'),
mock.call(self.fake_server, tag='tag2'),
mock.call(self.server, 'tag1'),
mock.call(self.server, 'tag2'),
]
)
self.compute_sdk_client.delete_server_metadata.assert_not_called()
self.compute_sdk_client.update_server.assert_not_called()
def test_server_unset_with_tag_pre_v226(self):
self.set_compute_api_version('2.25')
@ -8830,11 +8913,11 @@ class TestServerUnset(TestServer):
'tag1',
'--tag',
'tag2',
'foo_vm',
self.server.id,
]
verifylist = [
('tags', ['tag1', 'tag2']),
('server', 'foo_vm'),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)

@ -0,0 +1,4 @@
---
features:
- |
The ``server set`` and ``server unset`` commands have been migrated to SDK.

@ -7,7 +7,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0
cryptography>=2.7 # BSD/Apache-2.0
cliff>=3.5.0 # Apache-2.0
iso8601>=0.1.11 # MIT
openstacksdk>=2.0.0 # Apache-2.0
openstacksdk>=3.2.0 # Apache-2.0
osc-lib>=2.3.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
python-keystoneclient>=3.22.0 # Apache-2.0