@@ -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)'
@@ -1948,21 +1982,22 @@ def _match_image(image_api, wanted_properties):
19481982 # 'auto' to maintain legacy behavior if a nic wasn't specified.
19491983 networks = 'auto'
19501984
1951- # Check security group exist and convert ID to name
1985+ # Check security group(s) exist and convert ID to name
19521986 security_groups = []
19531987 if self .app .client_manager .is_network_endpoint_enabled ():
19541988 network_client = self .app .client_manager .network
1955- for each_sg in parsed_args .security_group :
1989+ for security_group in parsed_args .security_groups :
19561990 sg = network_client .find_security_group (
1957- each_sg , ignore_missing = False
1991+ security_group , ignore_missing = False
19581992 )
19591993 # Use security group ID to avoid multiple security group have
19601994 # same name in neutron networking backend
19611995 security_groups .append ({'name' : sg .id })
1962- else :
1963- # Handle nova-network case
1964- for each_sg in parsed_args .security_group :
1965- sg = compute_v2 .find_security_group (compute_client , each_sg )
1996+ else : # nova-network
1997+ for security_group in parsed_args .security_groups :
1998+ sg = compute_v2 .find_security_group (
1999+ compute_client , security_group
2000+ )
19662001 security_groups .append ({'name' : sg ['name' ]})
19672002
19682003 hints = {}
@@ -4016,9 +4051,13 @@ def get_parser(self, prog_name):
40164051 help = _ ('Server (name or ID)' ),
40174052 )
40184053 parser .add_argument (
4019- 'group' ,
4020- metavar = '<group>' ,
4021- help = _ ('Security group to remove (name or ID)' ),
4054+ 'security_groups' ,
4055+ metavar = '<security-group>' ,
4056+ nargs = '+' ,
4057+ help = _ (
4058+ 'Security group(s) to remove from server (name or ID) '
4059+ '(repeat option to remove multiple groups)'
4060+ ),
40224061 )
40234062 return parser
40244063
@@ -4031,15 +4070,42 @@ def take_action(self, parsed_args):
40314070 if self .app .client_manager .is_network_endpoint_enabled ():
40324071 # the server handles both names and IDs for neutron SGs, so just
40334072 # pass things through
4034- security_group = parsed_args .group
4073+ security_groups = parsed_args .security_groups
40354074 else :
4036- # however, if using nova-network then it needs a name, not an ID
4037- security_group = compute_v2 .find_security_group (
4038- compute_client , parsed_args .group
4039- )['name' ]
4040- compute_client .remove_security_group_from_server (
4041- server , security_group
4042- )
4075+ # however, if using nova-network then it needs names, not IDs
4076+ security_groups = []
4077+ for security_group in parsed_args .security_groups :
4078+ security_groups .append (
4079+ compute_v2 .find_security_group (
4080+ compute_client , security_group
4081+ )['name' ]
4082+ )
4083+
4084+ errors = 0
4085+ for security_group in security_groups :
4086+ try :
4087+ compute_client .remove_security_group_from_server (
4088+ server , security_group
4089+ )
4090+ except sdk_exceptions .HttpException as e :
4091+ errors += 1
4092+ LOG .error (
4093+ _ (
4094+ "Failed to remove security group with name or ID "
4095+ "'%(security_group)s' from server '%(server)s': %(e)s"
4096+ ),
4097+ {
4098+ 'security_group' : security_group ,
4099+ 'server' : server .id ,
4100+ 'e' : e ,
4101+ },
4102+ )
4103+
4104+ if errors > 0 :
4105+ msg = _ (
4106+ "%(errors)d of %(total)d security groups were not removed."
4107+ ) % {'errors' : errors , 'total' : len (security_groups )}
4108+ raise exceptions .CommandError (msg )
40434109
40444110
40454111class RemoveServerVolume (command .Command ):
0 commit comments