Skip to content

Commit 28a376b

Browse files
committed
Add --trusted-image-cert option for server create
this already exists for server rebuild, but was missing for server create. This option is supported from Compute API version >= 2.63, and is only available for servers booted directly from images (not from volumes, not from snapshots, and not from images first converted to volumes). Additionally, this patch removes mentions of OS_TRUSTED_IMAGE_CERTIFICATE_IDS env var from similar option help string in server rebuild command as it is not actually implemented yet. Change-Id: I4e9faea05c499bd91034d1d284c44fdcc8e18db5
1 parent ff372ff commit 28a376b

3 files changed

Lines changed: 188 additions & 1 deletion

File tree

openstackclient/compute/v2/server.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,19 @@ def get_parser(self, prog_name):
11711171
action='store_true',
11721172
help=_('Wait for build to complete'),
11731173
)
1174+
parser.add_argument(
1175+
'--trusted-image-cert',
1176+
metavar='<trusted-cert-id>',
1177+
action='append',
1178+
dest='trusted_image_certs',
1179+
help=_(
1180+
'Trusted image certificate IDs used to validate certificates '
1181+
'during the image signature verification process. '
1182+
'May be specified multiple times to pass multiple trusted '
1183+
'image certificate IDs. '
1184+
'(supported by --os-compute-api-version 2.63 or above)'
1185+
),
1186+
)
11741187
return parser
11751188

11761189
def take_action(self, parsed_args):
@@ -1640,6 +1653,24 @@ def _match_image(image_api, wanted_properties):
16401653

16411654
boot_kwargs['hostname'] = parsed_args.hostname
16421655

1656+
# TODO(stephenfin): Handle OS_TRUSTED_IMAGE_CERTIFICATE_IDS
1657+
if parsed_args.trusted_image_certs:
1658+
if not (image and not parsed_args.boot_from_volume):
1659+
msg = _(
1660+
'--trusted-image-cert option is only supported for '
1661+
'servers booted directly from images'
1662+
)
1663+
raise exceptions.CommandError(msg)
1664+
if compute_client.api_version < api_versions.APIVersion('2.63'):
1665+
msg = _(
1666+
'--os-compute-api-version 2.63 or greater is required to '
1667+
'support the --trusted-image-cert option'
1668+
)
1669+
raise exceptions.CommandError(msg)
1670+
1671+
certs = parsed_args.trusted_image_certs
1672+
boot_kwargs['trusted_image_certificates'] = certs
1673+
16431674
LOG.debug('boot_args: %s', boot_args)
16441675
LOG.debug('boot_kwargs: %s', boot_kwargs)
16451676

@@ -3277,7 +3308,6 @@ def get_parser(self, prog_name):
32773308
help=_(
32783309
'Trusted image certificate IDs used to validate certificates '
32793310
'during the image signature verification process. '
3280-
'Defaults to env[OS_TRUSTED_IMAGE_CERTIFICATE_IDS]. '
32813311
'May be specified multiple times to pass multiple trusted '
32823312
'image certificate IDs. '
32833313
'Cannot be specified with the --no-trusted-certs option. '

openstackclient/tests/unit/compute/v2/test_server.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3624,6 +3624,156 @@ def test_server_create_with_hostname_pre_v290(self):
36243624
exceptions.CommandError, self.cmd.take_action,
36253625
parsed_args)
36263626

3627+
def test_server_create_with_trusted_image_cert(self):
3628+
self.app.client_manager.compute.api_version = \
3629+
api_versions.APIVersion('2.63')
3630+
3631+
arglist = [
3632+
'--image', 'image1',
3633+
'--flavor', 'flavor1',
3634+
'--trusted-image-cert', 'foo',
3635+
'--trusted-image-cert', 'bar',
3636+
self.new_server.name,
3637+
]
3638+
verifylist = [
3639+
('image', 'image1'),
3640+
('flavor', 'flavor1'),
3641+
('config_drive', False),
3642+
('trusted_image_certs', ['foo', 'bar']),
3643+
('server_name', self.new_server.name),
3644+
]
3645+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3646+
columns, data = self.cmd.take_action(parsed_args)
3647+
3648+
# Set expected values
3649+
kwargs = dict(
3650+
meta=None,
3651+
files={},
3652+
reservation_id=None,
3653+
min_count=1,
3654+
max_count=1,
3655+
security_groups=[],
3656+
userdata=None,
3657+
key_name=None,
3658+
availability_zone=None,
3659+
admin_pass=None,
3660+
block_device_mapping_v2=[],
3661+
nics='auto',
3662+
scheduler_hints={},
3663+
config_drive=None,
3664+
trusted_image_certificates=['foo', 'bar'],
3665+
)
3666+
# ServerManager.create(name, image, flavor, **kwargs)
3667+
self.servers_mock.create.assert_called_with(
3668+
self.new_server.name,
3669+
self.image,
3670+
self.flavor,
3671+
**kwargs
3672+
)
3673+
self.assertEqual(self.columns, columns)
3674+
self.assertEqual(self.datalist(), data)
3675+
self.assertFalse(self.images_mock.called)
3676+
self.assertFalse(self.flavors_mock.called)
3677+
3678+
def test_server_create_with_trusted_image_cert_prev263(self):
3679+
self.app.client_manager.compute.api_version = \
3680+
api_versions.APIVersion('2.62')
3681+
3682+
arglist = [
3683+
'--image', 'image1',
3684+
'--flavor', 'flavor1',
3685+
'--trusted-image-cert', 'foo',
3686+
'--trusted-image-cert', 'bar',
3687+
self.new_server.name,
3688+
]
3689+
verifylist = [
3690+
('image', 'image1'),
3691+
('flavor', 'flavor1'),
3692+
('config_drive', False),
3693+
('trusted_image_certs', ['foo', 'bar']),
3694+
('server_name', self.new_server.name),
3695+
]
3696+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3697+
3698+
self.assertRaises(
3699+
exceptions.CommandError,
3700+
self.cmd.take_action,
3701+
parsed_args)
3702+
3703+
def test_server_create_with_trusted_image_cert_from_volume(self):
3704+
self.app.client_manager.compute.api_version = \
3705+
api_versions.APIVersion('2.63')
3706+
arglist = [
3707+
'--volume', 'volume1',
3708+
'--flavor', 'flavor1',
3709+
'--trusted-image-cert', 'foo',
3710+
'--trusted-image-cert', 'bar',
3711+
self.new_server.name,
3712+
]
3713+
verifylist = [
3714+
('volume', 'volume1'),
3715+
('flavor', 'flavor1'),
3716+
('config_drive', False),
3717+
('trusted_image_certs', ['foo', 'bar']),
3718+
('server_name', self.new_server.name),
3719+
]
3720+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3721+
3722+
self.assertRaises(
3723+
exceptions.CommandError,
3724+
self.cmd.take_action,
3725+
parsed_args)
3726+
3727+
def test_server_create_with_trusted_image_cert_from_snapshot(self):
3728+
self.app.client_manager.compute.api_version = \
3729+
api_versions.APIVersion('2.63')
3730+
arglist = [
3731+
'--snapshot', 'snapshot1',
3732+
'--flavor', 'flavor1',
3733+
'--trusted-image-cert', 'foo',
3734+
'--trusted-image-cert', 'bar',
3735+
self.new_server.name,
3736+
]
3737+
verifylist = [
3738+
('snapshot', 'snapshot1'),
3739+
('flavor', 'flavor1'),
3740+
('config_drive', False),
3741+
('trusted_image_certs', ['foo', 'bar']),
3742+
('server_name', self.new_server.name),
3743+
]
3744+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3745+
3746+
self.assertRaises(
3747+
exceptions.CommandError,
3748+
self.cmd.take_action,
3749+
parsed_args)
3750+
3751+
def test_server_create_with_trusted_image_cert_boot_from_volume(self):
3752+
self.app.client_manager.compute.api_version = \
3753+
api_versions.APIVersion('2.63')
3754+
arglist = [
3755+
'--image', 'image1',
3756+
'--flavor', 'flavor1',
3757+
'--boot-from-volume', '1',
3758+
'--trusted-image-cert', 'foo',
3759+
'--trusted-image-cert', 'bar',
3760+
self.new_server.name,
3761+
]
3762+
verifylist = [
3763+
('image', 'image1'),
3764+
('flavor', 'flavor1'),
3765+
('boot_from_volume', 1),
3766+
('config_drive', False),
3767+
('trusted_image_certs', ['foo', 'bar']),
3768+
('server_name', self.new_server.name),
3769+
]
3770+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3771+
3772+
self.assertRaises(
3773+
exceptions.CommandError,
3774+
self.cmd.take_action,
3775+
parsed_args)
3776+
36273777

36283778
class TestServerDelete(TestServer):
36293779

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
features:
3+
- |
4+
Added ``--trusted-image-cert`` option for server create. It is available
5+
only when directly booting server from image (not from volume, not from
6+
snapshot and not via image converted to volume first).
7+
This option is supported for Compute API version >=2.63

0 commit comments

Comments
 (0)