Merge "compute: Allow adding, removing multiple SGs"

This commit is contained in:
Zuul 2024-09-17 13:26:47 +00:00 committed by Gerrit Code Review
commit b92291f0aa
4 changed files with 108 additions and 37 deletions

View File

@ -670,7 +670,7 @@ class AddNetwork(command.Command):
class AddServerSecurityGroup(command.Command):
_description = _("Add security group to server")
_description = _("Add security group(s) to server")
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
@ -680,9 +680,13 @@ class AddServerSecurityGroup(command.Command):
help=_('Server (name or ID)'),
)
parser.add_argument(
'group',
metavar='<group>',
help=_('Security group to add (name or ID)'),
'security_groups',
metavar='<security-group>',
nargs='+',
help=_(
'Security group(s) to add to the server (name or ID) '
'(repeat option to add multiple groups)'
),
)
return parser
@ -694,14 +698,43 @@ class AddServerSecurityGroup(command.Command):
)
if self.app.client_manager.is_network_endpoint_enabled():
# the server handles both names and IDs for neutron SGs, so just
# pass things through
security_group = parsed_args.group
# pass things through if using neutron
security_groups = parsed_args.security_groups
else:
# however, if using nova-network then it needs a name, not an ID
security_group = compute_v2.find_security_group(
compute_client, parsed_args.group
)['name']
compute_client.add_security_group_to_server(server, security_group)
# however, if using nova-network then it needs names, not IDs
security_groups = []
for security_group in parsed_args.security_groups:
security_groups.append(
compute_v2.find_security_group(
compute_client, security_group
)['name']
)
errors = 0
for security_group in security_groups:
try:
compute_client.add_security_group_to_server(
server, security_group
)
except sdk_exceptions.HttpException as e:
errors += 1
LOG.error(
_(
"Failed to add security group with name or ID "
"'%(security_group)s' to server '%(server)s': %(e)s"
),
{
'security_group': security_group,
'server': server.id,
'e': e,
},
)
if errors > 0:
msg = _(
"%(errors)d of %(total)d security groups were not added."
) % {'errors': errors, 'total': len(security_groups)}
raise exceptions.CommandError(msg)
class AddServerVolume(command.ShowOne):
@ -1328,6 +1361,7 @@ class CreateServer(command.ShowOne):
metavar='<security-group>',
action='append',
default=[],
dest='security_groups',
help=_(
'Security group to assign to this server (name or ID) '
'(repeat option to set multiple groups)'
@ -1945,21 +1979,22 @@ class CreateServer(command.ShowOne):
# 'auto' to maintain legacy behavior if a nic wasn't specified.
networks = 'auto'
# Check security group exist and convert ID to name
# 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 each_sg in parsed_args.security_group:
for security_group in parsed_args.security_groups:
sg = network_client.find_security_group(
each_sg, ignore_missing=False
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:
# Handle nova-network case
for each_sg in parsed_args.security_group:
sg = compute_v2.find_security_group(compute_client, each_sg)
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 = {}
@ -4014,9 +4049,13 @@ class RemoveServerSecurityGroup(command.Command):
help=_('Server (name or ID)'),
)
parser.add_argument(
'group',
metavar='<group>',
help=_('Security group to remove (name or ID)'),
'security_groups',
metavar='<security-group>',
nargs='+',
help=_(
'Security group(s) to remove from server (name or ID) '
'(repeat option to remove multiple groups)'
),
)
return parser
@ -4029,15 +4068,42 @@ class RemoveServerSecurityGroup(command.Command):
if self.app.client_manager.is_network_endpoint_enabled():
# the server handles both names and IDs for neutron SGs, so just
# pass things through
security_group = parsed_args.group
security_groups = parsed_args.security_groups
else:
# however, if using nova-network then it needs a name, not an ID
security_group = compute_v2.find_security_group(
compute_client, parsed_args.group
)['name']
compute_client.remove_security_group_from_server(
server, security_group
)
# however, if using nova-network then it needs names, not IDs
security_groups = []
for security_group in parsed_args.security_groups:
security_groups.append(
compute_v2.find_security_group(
compute_client, security_group
)['name']
)
errors = 0
for security_group in security_groups:
try:
compute_client.remove_security_group_from_server(
server, security_group
)
except sdk_exceptions.HttpException as e:
errors += 1
LOG.error(
_(
"Failed to remove security group with name or ID "
"'%(security_group)s' from server '%(server)s': %(e)s"
),
{
'security_group': security_group,
'server': server.id,
'e': e,
},
)
if errors > 0:
msg = _(
"%(errors)d of %(total)d security groups were not removed."
) % {'errors': errors, 'total': len(security_groups)}
raise exceptions.CommandError(msg)
class RemoveServerVolume(command.Command):

View File

@ -21,7 +21,7 @@ class HelpTests(base.TestCase):
"""Functional tests for openstackclient help output."""
SERVER_COMMANDS = [
('server add security group', 'Add security group to server'),
('server add security group', 'Add security group(s) to server'),
('server add volume', 'Add volume to server'),
('server backup create', 'Create a server backup image'),
('server create', 'Create a new server'),

View File

@ -1145,7 +1145,7 @@ class TestServerAddSecurityGroup(compute_fakes.TestComputev2):
arglist = [self.server.id, 'fake_sg']
verifylist = [
('server', self.server.id),
('group', 'fake_sg'),
('security_groups', ['fake_sg']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -1176,7 +1176,7 @@ class TestServerAddSecurityGroup(compute_fakes.TestComputev2):
arglist = [self.server.id, 'fake_sg']
verifylist = [
('server', self.server.id),
('group', 'fake_sg'),
('security_groups', ['fake_sg']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -1408,7 +1408,7 @@ class TestServerCreate(TestServer):
('flavor', self.flavor.id),
('key_name', 'keyname'),
('properties', {'Beta': 'b'}),
('security_group', [security_group.id]),
('security_groups', [security_group.id]),
('hints', {'a': ['b', 'c']}),
('server_group', server_group.id),
('config_drive', True),
@ -1478,7 +1478,7 @@ class TestServerCreate(TestServer):
('image', self.image.id),
('flavor', self.flavor.id),
('key_name', 'keyname'),
('security_group', ['not_exist_sg']),
('security_groups', ['not_exist_sg']),
('server_name', self.server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -1504,7 +1504,7 @@ class TestServerCreate(TestServer):
verifylist = [
('image', self.image.id),
('flavor', self.flavor.id),
('security_group', [sg_name]),
('security_groups', [sg_name]),
('server_name', self.server.name),
]
@ -7380,7 +7380,7 @@ class TestServerRemoveSecurityGroup(TestServer):
arglist = [self.server.id, 'fake_sg']
verifylist = [
('server', self.server.id),
('group', 'fake_sg'),
('security_groups', ['fake_sg']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -7411,7 +7411,7 @@ class TestServerRemoveSecurityGroup(TestServer):
arglist = [self.server.id, 'fake_sg']
verifylist = [
('server', self.server.id),
('group', 'fake_sg'),
('security_groups', ['fake_sg']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)

View File

@ -0,0 +1,5 @@
---
features:
- |
The ``server add security group`` and ``server remove security group``
commands now accept multiple security groups.