compute: Migrate 'server rebuild' to SDK

Change-Id: Ic7cdb05327a4a74364f08451e531d02c631b7633
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
Depends-on: https://review.opendev.org/c/openstack/openstacksdk/+/918730
This commit is contained in:
Stephen Finucane 2024-05-17 12:24:14 +01:00
parent 2057462120
commit 8d904a9efb
2 changed files with 327 additions and 205 deletions

View File

@ -16,6 +16,7 @@
"""Compute v2 Server action implementations"""
import argparse
import base64
import getpass
import json
import logging
@ -3505,11 +3506,11 @@ class RebuildServer(command.ShowOne):
self.app.stdout.write('\rProgress: %s' % progress)
self.app.stdout.flush()
compute_client = self.app.client_manager.compute
compute_client = self.app.client_manager.sdk_connection.compute
image_client = self.app.client_manager.image
server = utils.find_resource(
compute_client.servers, parsed_args.server
server = compute_client.find_server(
parsed_args.server, ignore_missing=False
)
# If parsed_args.image is not set and if the instance is image backed,
@ -3521,7 +3522,7 @@ class RebuildServer(command.ShowOne):
parsed_args.image, ignore_missing=False
)
else:
if not server.image:
if not server.image or not server.image.id:
msg = _(
'The --image option is required when rebuilding a '
'volume-backed server'
@ -3538,10 +3539,10 @@ class RebuildServer(command.ShowOne):
kwargs['preserve_ephemeral'] = parsed_args.preserve_ephemeral
if parsed_args.properties:
kwargs['meta'] = parsed_args.properties
kwargs['metadata'] = parsed_args.properties
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'
@ -3551,7 +3552,7 @@ class RebuildServer(command.ShowOne):
kwargs['description'] = parsed_args.description
if parsed_args.key_name:
if compute_client.api_version < api_versions.APIVersion('2.54'):
if not sdk_utils.supports_microversion(compute_client, '2.54'):
msg = _(
'--os-compute-api-version 2.54 or greater is required to '
'support the --key-name option'
@ -3560,7 +3561,7 @@ class RebuildServer(command.ShowOne):
kwargs['key_name'] = parsed_args.key_name
elif parsed_args.no_key_name:
if compute_client.api_version < api_versions.APIVersion('2.54'):
if not sdk_utils.supports_microversion(compute_client, '2.54'):
msg = _(
'--os-compute-api-version 2.54 or greater is required to '
'support the --no-key-name option'
@ -3569,9 +3570,8 @@ class RebuildServer(command.ShowOne):
kwargs['key_name'] = None
userdata = None
if parsed_args.user_data:
if compute_client.api_version < api_versions.APIVersion('2.54'):
if not sdk_utils.supports_microversion(compute_client, '2.54'):
msg = _(
'--os-compute-api-version 2.54 or greater is required to '
'support the --user-data option'
@ -3579,27 +3579,29 @@ class RebuildServer(command.ShowOne):
raise exceptions.CommandError(msg)
try:
userdata = open(parsed_args.user_data)
with open(parsed_args.user_data, 'rb') as fh:
# TODO(stephenfin): SDK should do this for us
user_data = base64.b64encode(fh.read()).decode('utf-8')
except OSError as e:
msg = _("Can't open '%(data)s': %(exception)s")
raise exceptions.CommandError(
msg % {'data': parsed_args.user_data, 'exception': e}
)
kwargs['userdata'] = userdata
kwargs['user_data'] = user_data
elif parsed_args.no_user_data:
if compute_client.api_version < api_versions.APIVersion('2.54'):
if not sdk_utils.supports_microversion(compute_client, '2.54'):
msg = _(
'--os-compute-api-version 2.54 or greater is required to '
'support the --no-user-data option'
)
raise exceptions.CommandError(msg)
kwargs['userdata'] = None
kwargs['user_data'] = None
# TODO(stephenfin): Handle OS_TRUSTED_IMAGE_CERTIFICATE_IDS
if parsed_args.trusted_image_certs:
if compute_client.api_version < api_versions.APIVersion('2.63'):
if not sdk_utils.supports_microversion(compute_client, '2.63'):
msg = _(
'--os-compute-api-version 2.63 or greater is required to '
'support the --trusted-certs option'
@ -3609,7 +3611,7 @@ class RebuildServer(command.ShowOne):
certs = parsed_args.trusted_image_certs
kwargs['trusted_image_certificates'] = certs
elif parsed_args.no_trusted_image_certs:
if compute_client.api_version < api_versions.APIVersion('2.63'):
if not sdk_utils.supports_microversion(compute_client, '2.63'):
msg = _(
'--os-compute-api-version 2.63 or greater is required to '
'support the --no-trusted-certs option'
@ -3619,7 +3621,7 @@ class RebuildServer(command.ShowOne):
kwargs['trusted_image_certificates'] = None
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'
@ -3628,9 +3630,8 @@ class RebuildServer(command.ShowOne):
kwargs['hostname'] = parsed_args.hostname
v2_93 = api_versions.APIVersion('2.93')
if parsed_args.reimage_boot_volume:
if compute_client.api_version < v2_93:
if not sdk_utils.supports_microversion(compute_client, '2.93'):
msg = _(
'--os-compute-api-version 2.93 or greater is required to '
'support the --reimage-boot-volume option'
@ -3639,8 +3640,8 @@ class RebuildServer(command.ShowOne):
else:
# force user to explicitly request reimaging of volume-backed
# server
if not server.image:
if compute_client.api_version >= v2_93:
if not server.image or not server.image.id:
if sdk_utils.supports_microversion(compute_client, '2.93'):
msg = (
'--reimage-boot-volume is required to rebuild a '
'volume-backed server'
@ -3672,15 +3673,13 @@ class RebuildServer(command.ShowOne):
msg = _("The server status is not ACTIVE, SHUTOFF or ERROR.")
raise exceptions.CommandError(msg)
try:
server = server.rebuild(image, parsed_args.password, **kwargs)
finally:
if userdata and hasattr(userdata, 'close'):
userdata.close()
server = compute_client.rebuild_server(
server, image, admin_password=parsed_args.password, **kwargs
)
if parsed_args.wait:
if utils.wait_for_status(
compute_client.servers.get,
compute_client.get_server,
server.id,
callback=_show_progress,
success_status=success_status,
@ -3690,8 +3689,6 @@ class RebuildServer(command.ShowOne):
msg = _('Error rebuilding server: %s') % server.id
raise exceptions.CommandError(msg)
# TODO(stephenfin): Remove when the whole command is using SDK
compute_client = self.app.client_manager.sdk_connection.compute
data = _prep_server_detail(
compute_client, image_client, server, refresh=False
)

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import base64
import collections
import copy
import getpass
@ -6227,59 +6228,47 @@ class TestServerRebuild(TestServer):
def setUp(self):
super().setUp()
# Return value for utils.find_resource for image
self.image = image_fakes.create_one_image()
self.image_client.get_image.return_value = self.image
# Fake the rebuilt new server.
attrs = {
'status': 'ACTIVE',
'image': {'id': self.image.id},
'networks': {},
'adminPass': 'passw0rd',
}
new_server = compute_fakes.create_one_server(attrs=attrs)
# Fake the server to be rebuilt. The IDs of them should be the same.
attrs['id'] = new_server.id
attrs['status'] = 'ACTIVE'
methods = {
'rebuild': new_server,
}
self.server = compute_fakes.create_one_server(
attrs=attrs, methods=methods
)
# Return value for utils.find_resource for server.
self.servers_mock.get.return_value = self.server
self.server = compute_fakes.create_one_sdk_server(attrs=attrs)
self.compute_sdk_client.find_server.return_value = self.server
self.compute_sdk_client.rebuild_server.return_value = self.server
self.cmd = server.RebuildServer(self.app, None)
def test_rebuild_with_image_name(self):
image_name = 'my-custom-image'
user_image = image_fakes.create_one_image(attrs={'name': image_name})
self.image_client.find_image.return_value = user_image
image = image_fakes.create_one_image(attrs={'name': image_name})
self.image_client.find_image.return_value = image
attrs = {
'image': {'id': user_image.id},
'networks': {},
'adminPass': 'passw0rd',
}
new_server = compute_fakes.create_one_server(attrs=attrs)
self.server.rebuild.return_value = new_server
arglist = [
self.server.id,
'--image',
image_name,
]
verifylist = [
('server', self.server.id),
('image', image_name),
]
arglist = [self.server.id, '--image', image_name]
verifylist = [('server', self.server.id), ('image', image_name)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test.
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_called_with(
image_name, ignore_missing=False
)
self.image_client.get_image.assert_called_with(user_image.id)
self.server.rebuild.assert_called_with(user_image, None)
self.image_client.get_image.assert_called_with(self.image.id)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server, image, admin_password=None
)
def test_rebuild_with_current_image(self):
arglist = [
@ -6291,10 +6280,16 @@ class TestServerRebuild(TestServer):
# Get the command object to test.
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None)
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server, self.image, admin_password=None
)
def test_rebuild_with_volume_backed_server_no_image(self):
# the volume-backed server will have the image attribute set to an
@ -6307,8 +6302,8 @@ class TestServerRebuild(TestServer):
verifylist = [
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
exc = self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -6325,14 +6320,20 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('name', name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None, name=name)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server, self.image, admin_password=None, name=name
)
def test_rebuild_with_preserve_ephemeral(self):
arglist = [
@ -6343,15 +6344,22 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('preserve_ephemeral', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, preserve_ephemeral=True
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
preserve_ephemeral=True,
)
def test_rebuild_with_no_preserve_ephemeral(self):
@ -6368,24 +6376,40 @@ class TestServerRebuild(TestServer):
# Get the command object to test
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, preserve_ephemeral=False
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
preserve_ephemeral=False,
)
def test_rebuild_with_password(self):
password = 'password-xxx'
arglist = [self.server.id, '--password', password]
verifylist = [('server', self.server.id), ('password', password)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, password)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=password,
)
def test_rebuild_with_description(self):
self.set_compute_api_version('2.19')
@ -6393,14 +6417,22 @@ class TestServerRebuild(TestServer):
description = 'description1'
arglist = [self.server.id, '--description', description]
verifylist = [('server', self.server.id), ('description', description)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, description=description
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
description=description,
)
def test_rebuild_with_description_pre_v219(self):
@ -6409,8 +6441,8 @@ class TestServerRebuild(TestServer):
description = 'description1'
arglist = [self.server.id, '--description', description]
verifylist = [('server', self.server.id), ('description', description)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -6425,25 +6457,30 @@ class TestServerRebuild(TestServer):
('wait', True),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test.
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
# kwargs = dict(success_status=['active', 'verify_resize'],)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
)
mock_wait_for_status.assert_called_once_with(
self.servers_mock.get,
self.compute_sdk_client.get_server,
self.server.id,
callback=mock.ANY,
success_status=['active'],
# **kwargs
)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None)
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
def test_rebuild_with_wait_fails(self, mock_wait_for_status):
arglist = [
@ -6454,23 +6491,30 @@ class TestServerRebuild(TestServer):
('wait', True),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_called_once_with(self.image.id)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
)
mock_wait_for_status.assert_called_once_with(
self.servers_mock.get,
self.compute_sdk_client.get_server,
self.server.id,
callback=mock.ANY,
success_status=['active'],
)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None)
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_rebuild_with_wait_shutoff_status(self, mock_wait_for_status):
self.server.status = 'SHUTOFF'
@ -6482,25 +6526,30 @@ class TestServerRebuild(TestServer):
('wait', True),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test.
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
# kwargs = dict(success_status=['active', 'verify_resize'],)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
)
mock_wait_for_status.assert_called_once_with(
self.servers_mock.get,
self.compute_sdk_client.get_server,
self.server.id,
callback=mock.ANY,
success_status=['shutoff'],
# **kwargs
)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None)
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_rebuild_with_wait_error_status(self, mock_wait_for_status):
self.server.status = 'ERROR'
@ -6512,25 +6561,30 @@ class TestServerRebuild(TestServer):
('wait', True),
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test.
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
# kwargs = dict(success_status=['active', 'verify_resize'],)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
)
mock_wait_for_status.assert_called_once_with(
self.servers_mock.get,
self.compute_sdk_client.get_server,
self.server.id,
callback=mock.ANY,
success_status=['active'],
# **kwargs
)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None)
def test_rebuild_wrong_status_fails(self):
self.server.status = 'SHELVED'
arglist = [
@ -6539,15 +6593,18 @@ class TestServerRebuild(TestServer):
verifylist = [
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_not_called()
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_called_once_with(self.image.id)
self.compute_sdk_client.rebuild_server.assert_not_called()
def test_rebuild_with_property(self):
arglist = [
@ -6562,15 +6619,22 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('properties', expected_properties),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# Get the command object to test
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, meta=expected_properties
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
metadata=expected_properties,
)
def test_rebuild_with_keypair_name(self):
@ -6586,14 +6650,22 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('key_name', self.server.key_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, key_name=self.server.key_name
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
key_name=self.server.key_name,
)
def test_rebuild_with_keypair_name_pre_v254(self):
@ -6626,12 +6698,23 @@ class TestServerRebuild(TestServer):
verifylist = [
('server', self.server.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None, key_name=None)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
key_name=None,
)
def test_rebuild_with_keypair_name_and_unset(self):
self.server.key_name = 'mykey'
@ -6653,14 +6736,10 @@ class TestServerRebuild(TestServer):
verifylist,
)
@mock.patch('openstackclient.compute.v2.server.open')
def test_rebuild_with_user_data(self, mock_open):
def test_rebuild_with_user_data(self):
self.set_compute_api_version('2.57')
mock_file = mock.Mock(name='File')
mock_open.return_value = mock_file
mock_open.read.return_value = '#!/bin/sh'
user_data = b'#!/bin/sh'
arglist = [
self.server.id,
'--user-data',
@ -6670,22 +6749,29 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('user_data', 'userdata.sh'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch(
'openstackclient.compute.v2.server.open',
mock.mock_open(read_data=user_data),
) as mock_file:
self.cmd.take_action(parsed_args)
# Ensure the userdata file is opened
mock_open.assert_called_with('userdata.sh')
mock_file.assert_called_with('userdata.sh', 'rb')
# Ensure the userdata file is closed
mock_file.close.assert_called_with()
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
None,
userdata=mock_file,
admin_password=None,
user_data=base64.b64encode(user_data).decode('utf-8'),
)
def test_rebuild_with_user_data_pre_v257(self):
@ -6700,8 +6786,8 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('user_data', 'userdata.sh'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -6718,12 +6804,23 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('no_user_data', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, None, userdata=None)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
user_data=None,
)
def test_rebuild_with_no_user_data_pre_v254(self):
self.set_compute_api_version('2.53')
@ -6736,8 +6833,8 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('no_user_data', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -6771,14 +6868,22 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('trusted_image_certs', ['foo', 'bar']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, trusted_image_certificates=['foo', 'bar']
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
trusted_image_certificates=['foo', 'bar'],
)
def test_rebuild_with_trusted_image_cert_pre_v263(self):
@ -6795,8 +6900,8 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('trusted_image_certs', ['foo', 'bar']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
)
@ -6812,13 +6917,22 @@ class TestServerRebuild(TestServer):
('server', self.server.id),
('no_trusted_image_certs', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, trusted_image_certificates=None
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
trusted_image_certificates=None,
)
def test_rebuild_with_no_trusted_image_cert_pre_v263(self):
@ -6841,16 +6955,31 @@ class TestServerRebuild(TestServer):
def test_rebuild_with_hostname(self):
self.set_compute_api_version('2.90')
arglist = [self.server.id, '--hostname', 'new-hostname']
verifylist = [('server', self.server.id), ('hostname', 'new-hostname')]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
arglist = [
self.server.id,
'--hostname',
'new-hostname',
]
verifylist = [
('server', self.server.id),
('hostname', 'new-hostname'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.image_client.get_image.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(
self.image, None, hostname='new-hostname'
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_not_called()
self.image_client.get_image.assert_has_calls(
[mock.call(self.image.id), mock.call(self.image.id)]
)
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server,
self.image,
admin_password=None,
hostname='new-hostname',
)
def test_rebuild_with_hostname_pre_v290(self):
@ -6877,24 +7006,12 @@ class TestServerRebuildVolumeBacked(TestServer):
self.image_client.find_image.return_value = self.new_image
attrs = {
'status': 'ACTIVE',
'image': '',
'networks': {},
'adminPass': 'passw0rd',
}
new_server = compute_fakes.create_one_server(attrs=attrs)
# Fake the server to be rebuilt. The IDs of them should be the same.
attrs['id'] = new_server.id
attrs['status'] = 'ACTIVE'
methods = {
'rebuild': new_server,
}
self.server = compute_fakes.create_one_server(
attrs=attrs, methods=methods
)
# Return value for utils.find_resource for server.
self.servers_mock.get.return_value = self.server
self.server = compute_fakes.create_one_sdk_server(attrs=attrs)
self.compute_sdk_client.find_server.return_value = self.server
self.compute_sdk_client.rebuild_server.return_value = self.server
self.cmd = server.RebuildServer(self.app, None)
@ -6912,12 +7029,20 @@ class TestServerRebuildVolumeBacked(TestServer):
('reimage_boot_volume', True),
('image', self.new_image.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.server.rebuild.assert_called_with(self.new_image, None)
self.compute_sdk_client.find_server.assert_called_once_with(
self.server.id, ignore_missing=False
)
self.image_client.find_image.assert_called_with(
self.new_image.id, ignore_missing=False
)
self.image_client.get_image.assert_not_called()
self.compute_sdk_client.rebuild_server.assert_called_once_with(
self.server, self.new_image, admin_password=None
)
def test_rebuild_with_no_reimage_boot_volume(self):
self.set_compute_api_version('2.93')