Skip to content

Commit d79ebc5

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add --trusted-image-cert option for server create"
2 parents 49d2c21 + 28a376b commit d79ebc5

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)