@@ -670,7 +670,7 @@ def take_action(self, parsed_args):
670670
671671
672672class AddServerSecurityGroup (command .Command ):
673- _description = _ ("Add security group to server" )
673+ _description = _ ("Add security group(s) to server" )
674674
675675 def get_parser (self , prog_name ):
676676 parser = super ().get_parser (prog_name )
@@ -680,9 +680,13 @@ def get_parser(self, prog_name):
680680 help = _ ('Server (name or ID)' ),
681681 )
682682 parser .add_argument (
683- 'group' ,
684- metavar = '<group>' ,
685- help = _ ('Security group to add (name or ID)' ),
683+ 'security_groups' ,
684+ metavar = '<security-group>' ,
685+ nargs = '+' ,
686+ help = _ (
687+ 'Security group(s) to add to the server (name or ID) '
688+ '(repeat option to add multiple groups)'
689+ ),
686690 )
687691 return parser
688692
@@ -694,14 +698,43 @@ def take_action(self, parsed_args):
694698 )
695699 if self .app .client_manager .is_network_endpoint_enabled ():
696700 # the server handles both names and IDs for neutron SGs, so just
697- # pass things through
698- security_group = parsed_args .group
701+ # pass things through if using neutron
702+ security_groups = parsed_args .security_groups
699703 else :
700- # however, if using nova-network then it needs a name, not an ID
701- security_group = compute_v2 .find_security_group (
702- compute_client , parsed_args .group
703- )['name' ]
704- compute_client .add_security_group_to_server (server , security_group )
704+ # however, if using nova-network then it needs names, not IDs
705+ security_groups = []
706+ for security_group in parsed_args .security_groups :
707+ security_groups .append (
708+ compute_v2 .find_security_group (
709+ compute_client , security_group
710+ )['name' ]
711+ )
712+
713+ errors = 0
714+ for security_group in security_groups :
715+ try :
716+ compute_client .add_security_group_to_server (
717+ server , security_group
718+ )
719+ except sdk_exceptions .HttpException as e :
720+ errors += 1
721+ LOG .error (
722+ _ (
723+ "Failed to add security group with name or ID "
724+ "'%(security_group)s' to server '%(server)s': %(e)s"
725+ ),
726+ {
727+ 'security_group' : security_group ,
728+ 'server' : server .id ,
729+ 'e' : e ,
730+ },
731+ )
732+
733+ if errors > 0 :
734+ msg = _ (
735+ "%(errors)d of %(total)d security groups were not added."
736+ ) % {'errors' : errors , 'total' : len (security_groups )}
737+ raise exceptions .CommandError (msg )
705738
706739
707740class AddServerVolume (command .ShowOne ):
@@ -1328,6 +1361,7 @@ def get_parser(self, prog_name):
13281361 metavar = '<security-group>' ,
13291362 action = 'append' ,
13301363 default = [],
1364+ dest = 'security_groups' ,
13311365 help = _ (
13321366 'Security group to assign to this server (name or ID) '
13331367 '(repeat option to set multiple groups)'
@@ -1945,21 +1979,22 @@ def _match_image(image_api, wanted_properties):
19451979 # 'auto' to maintain legacy behavior if a nic wasn't specified.
19461980 networks = 'auto'
19471981
1948- # Check security group exist and convert ID to name
1982+ # Check security group(s) exist and convert ID to name
19491983 security_groups = []
19501984 if self .app .client_manager .is_network_endpoint_enabled ():
19511985 network_client = self .app .client_manager .network
1952- for each_sg in parsed_args .security_group :
1986+ for security_group in parsed_args .security_groups :
19531987 sg = network_client .find_security_group (
1954- each_sg , ignore_missing = False
1988+ security_group , ignore_missing = False
19551989 )
19561990 # Use security group ID to avoid multiple security group have
19571991 # same name in neutron networking backend
19581992 security_groups .append ({'name' : sg .id })
1959- else :
1960- # Handle nova-network case
1961- for each_sg in parsed_args .security_group :
1962- sg = compute_v2 .find_security_group (compute_client , each_sg )
1993+ else : # nova-network
1994+ for security_group in parsed_args .security_groups :
1995+ sg = compute_v2 .find_security_group (
1996+ compute_client , security_group
1997+ )
19631998 security_groups .append ({'name' : sg ['name' ]})
19641999
19652000 hints = {}
@@ -4014,9 +4049,13 @@ def get_parser(self, prog_name):
40144049 help = _ ('Server (name or ID)' ),
40154050 )
40164051 parser .add_argument (
4017- 'group' ,
4018- metavar = '<group>' ,
4019- help = _ ('Security group to remove (name or ID)' ),
4052+ 'security_groups' ,
4053+ metavar = '<security-group>' ,
4054+ nargs = '+' ,
4055+ help = _ (
4056+ 'Security group(s) to remove from server (name or ID) '
4057+ '(repeat option to remove multiple groups)'
4058+ ),
40204059 )
40214060 return parser
40224061
@@ -4029,15 +4068,42 @@ def take_action(self, parsed_args):
40294068 if self .app .client_manager .is_network_endpoint_enabled ():
40304069 # the server handles both names and IDs for neutron SGs, so just
40314070 # pass things through
4032- security_group = parsed_args .group
4071+ security_groups = parsed_args .security_groups
40334072 else :
4034- # however, if using nova-network then it needs a name, not an ID
4035- security_group = compute_v2 .find_security_group (
4036- compute_client , parsed_args .group
4037- )['name' ]
4038- compute_client .remove_security_group_from_server (
4039- server , security_group
4040- )
4073+ # however, if using nova-network then it needs names, not IDs
4074+ security_groups = []
4075+ for security_group in parsed_args .security_groups :
4076+ security_groups .append (
4077+ compute_v2 .find_security_group (
4078+ compute_client , security_group
4079+ )['name' ]
4080+ )
4081+
4082+ errors = 0
4083+ for security_group in security_groups :
4084+ try :
4085+ compute_client .remove_security_group_from_server (
4086+ server , security_group
4087+ )
4088+ except sdk_exceptions .HttpException as e :
4089+ errors += 1
4090+ LOG .error (
4091+ _ (
4092+ "Failed to remove security group with name or ID "
4093+ "'%(security_group)s' from server '%(server)s': %(e)s"
4094+ ),
4095+ {
4096+ 'security_group' : security_group ,
4097+ 'server' : server .id ,
4098+ 'e' : e ,
4099+ },
4100+ )
4101+
4102+ if errors > 0 :
4103+ msg = _ (
4104+ "%(errors)d of %(total)d security groups were not removed."
4105+ ) % {'errors' : errors , 'total' : len (security_groups )}
4106+ raise exceptions .CommandError (msg )
40414107
40424108
40434109class RemoveServerVolume (command .Command ):
0 commit comments