compute: Add server create --no-security-group option

To allow users to create servers with no security groups associated with
the ports.

Change-Id: I91b1d9dd5c3fbba838640841d98341cd8ccb1b16
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2023-08-10 19:04:36 +01:00
parent ecc744a4fd
commit 5ef5cc9c82
4 changed files with 103 additions and 22 deletions

View File

@ -1356,14 +1356,26 @@ class CreateServer(command.ShowOne):
'This option requires cloud support.'
),
)
parser.add_argument(
secgroups = parser.add_mutually_exclusive_group()
secgroups.add_argument(
'--no-security-group',
dest='security_groups',
action='store_const',
const=[],
help=_(
'Do not associate a security group with ports attached to '
'this server. This does not affect the security groups '
'associated with pre-existing ports.'
),
)
secgroups.add_argument(
'--security-group',
metavar='<security-group>',
action='append',
default=[],
dest='security_groups',
help=_(
'Security group to assign to this server (name or ID) '
'Security group to associate with ports attached to this '
'server (name or ID) '
'(repeat option to set multiple groups)'
),
)
@ -1980,22 +1992,24 @@ class CreateServer(command.ShowOne):
networks = 'auto'
# Check security group(s) exist and convert ID to name
security_groups = []
if self.app.client_manager.is_network_endpoint_enabled():
network_client = self.app.client_manager.network
for security_group in parsed_args.security_groups:
sg = network_client.find_security_group(
security_group, ignore_missing=False
)
# Use security group ID to avoid multiple security group have
# same name in neutron networking backend
security_groups.append({'name': sg.id})
else: # nova-network
for security_group in parsed_args.security_groups:
sg = compute_v2.find_security_group(
compute_client, security_group
)
security_groups.append({'name': sg['name']})
security_groups = None
if parsed_args.security_groups is not None:
security_groups = []
if self.app.client_manager.is_network_endpoint_enabled():
network_client = self.app.client_manager.network
for security_group in parsed_args.security_groups:
sg = network_client.find_security_group(
security_group, ignore_missing=False
)
# Use security group ID to avoid multiple security group
# have same name in neutron networking backend
security_groups.append({'name': sg.id})
else: # nova-network
for security_group in parsed_args.security_groups:
sg = compute_v2.find_security_group(
compute_client, security_group
)
security_groups.append({'name': sg['name']})
hints = {}
for key, values in parsed_args.hints.items():
@ -2058,7 +2072,7 @@ class CreateServer(command.ShowOne):
if files:
kwargs['personality'] = files
if security_groups:
if security_groups is not None:
kwargs['security_groups'] = security_groups
if block_device_mapping_v2:

View File

@ -1544,6 +1544,60 @@ class TestServerCreate(TestServer):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data)
def test_server_create_with_no_security_group(self):
arglist = [
'--image',
self.image.id,
'--flavor',
self.flavor.id,
'--no-security-group',
self.server.name,
]
verifylist = [
('image', self.image.id),
('flavor', self.flavor.id),
('key_name', None),
('properties', None),
('security_groups', []),
('hints', {}),
('server_group', None),
('config_drive', False),
('password', None),
('server_name', self.server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.compute_sdk_client.find_flavor.assert_has_calls(
[mock.call(self.flavor.id, ignore_missing=False)] * 2
)
self.network_client.find_security_group.assert_not_called()
self.image_client.find_image.assert_called_once_with(
self.image.id, ignore_missing=False
)
self.compute_sdk_client.create_server.assert_called_once_with(
name=self.server.name,
image_id=self.image.id,
flavor_id=self.flavor.id,
min_count=1,
max_count=1,
security_groups=[],
networks=[],
block_device_mapping=[
{
'uuid': self.image.id,
'boot_index': 0,
'source_type': 'image',
'destination_type': 'local',
'delete_on_termination': True,
},
],
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data)
def test_server_create_with_network(self):
network_net1 = network_fakes.create_one_network()
network_net2 = network_fakes.create_one_network()

View File

@ -93,8 +93,14 @@ class TestCommand(TestCase):
f"Argument parse failed: {stderr.getvalue()}"
)
for av in verify_args:
attr, value = av
attr, expected_value = av
if attr:
actual_value = getattr(parsed_args, attr)
self.assertIn(attr, parsed_args)
self.assertEqual(value, getattr(parsed_args, attr))
self.assertEqual(
expected_value,
actual_value,
f'args.{attr}: expected: {expected_value}, got: '
f'{actual_value}',
)
return parsed_args

View File

@ -0,0 +1,7 @@
---
features:
- |
The ``server create`` command now supports a ``--no-security-group``
option. When provided, no security groups will be associated with ports
created and attached to the server during server creation. This does not
affect pre-created ports.