2121
2222import java .io .ByteArrayOutputStream ;
2323import java .io .IOException ;
24+ import java .util .ArrayList ;
2425import java .util .List ;
2526import java .util .zip .DeflaterOutputStream ;
2627
3233import com .cloud .utils .net .NetUtils ;
3334
3435public class SecurityGroupRulesCmd extends Command {
35- private static Logger s_logger = Logger .getLogger (SecurityGroupRulesCmd .class );
36+ private static final String CIDR_LENGTH_SEPARATOR = "/" ;
37+ private static final char RULE_TARGET_SEPARATOR = ',' ;
38+ private static final char RULE_COMMAND_SEPARATOR = ':' ;
39+ protected static final String EGRESS_RULE = "E:" ;
40+ protected static final String INGRESS_RULE = "I:" ;
41+ private static final Logger LOGGER = Logger .getLogger (SecurityGroupRulesCmd .class );
42+
43+ private final String guestIp ;
44+ private final String vmName ;
45+ private final String guestMac ;
46+ private final String signature ;
47+ private final Long seqNum ;
48+ private final Long vmId ;
49+ private Long msId ;
50+ private List <IpPortAndProto > ingressRuleSet ;
51+ private List <IpPortAndProto > egressRuleSet ;
52+ private final List <String > secIps ;
3653
3754 public static class IpPortAndProto {
38- private String proto ;
39- private int startPort ;
40- private int endPort ;
55+ private final String proto ;
56+ private final int startPort ;
57+ private final int endPort ;
4158 @ LogLevel (Log4jLevel .Trace )
42- private String [] allowedCidrs ;
59+ private List < String > allowedCidrs ;
4360
44- public IpPortAndProto () {
45- }
46-
47- public IpPortAndProto (String proto , int startPort , int endPort , String [] allowedCidrs ) {
61+ public IpPortAndProto (final String proto , final int startPort , final int endPort , final String ... allowedCidrs ) {
4862 super ();
4963 this .proto = proto ;
5064 this .startPort = startPort ;
5165 this .endPort = endPort ;
52- this . allowedCidrs = allowedCidrs ;
66+ setAllowedCidrs ( allowedCidrs ) ;
5367 }
5468
55- public String [] getAllowedCidrs () {
69+ public List < String > getAllowedCidrs () {
5670 return allowedCidrs ;
5771 }
5872
59- public void setAllowedCidrs (String [] allowedCidrs ) {
60- this .allowedCidrs = allowedCidrs ;
73+ public void setAllowedCidrs (final String ... allowedCidrs ) {
74+ this .allowedCidrs = new ArrayList <String >();
75+ for (final String allowedCidr : allowedCidrs ) {
76+ this .allowedCidrs .add (allowedCidr );
77+ }
6178 }
6279
6380 public String getProto () {
@@ -74,52 +91,28 @@ public int getEndPort() {
7491
7592 }
7693
77- String guestIp ;
78- String vmName ;
79- String guestMac ;
80- String signature ;
81- Long seqNum ;
82- Long vmId ;
83- Long msId ;
84- IpPortAndProto [] ingressRuleSet ;
85- IpPortAndProto [] egressRuleSet ;
86- private List <String > secIps ;
87-
88- public SecurityGroupRulesCmd () {
89- super ();
90- }
91-
92- public SecurityGroupRulesCmd (String guestIp , String guestMac , String vmName , Long vmId , String signature , Long seqNum , IpPortAndProto [] ingressRuleSet ,
93- IpPortAndProto [] egressRuleSet ) {
94- super ();
95- this .guestIp = guestIp ;
96- this .vmName = vmName ;
97- this .ingressRuleSet = ingressRuleSet ;
98- this .egressRuleSet = egressRuleSet ;
99- this .guestMac = guestMac ;
100- this .signature = signature ;
101- this .seqNum = seqNum ;
102- this .vmId = vmId ;
103- if (signature == null ) {
104- String stringified = stringifyRules ();
105- this .signature = DigestUtils .md5Hex (stringified );
106- }
107- }
108-
109- public SecurityGroupRulesCmd (String guestIp , String guestMac , String vmName , Long vmId , String signature , Long seqNum , IpPortAndProto [] ingressRuleSet ,
110- IpPortAndProto [] egressRuleSet , List <String > secIps ) {
111- super ();
94+ public SecurityGroupRulesCmd (
95+ final String guestIp ,
96+ final String guestMac ,
97+ final String vmName ,
98+ final Long vmId ,
99+ final String signature ,
100+ final Long seqNum ,
101+ final IpPortAndProto [] ingressRuleSet ,
102+ final IpPortAndProto [] egressRuleSet ,
103+ final List <String > secIps ) {
112104 this .guestIp = guestIp ;
113105 this .vmName = vmName ;
114- this . ingressRuleSet = ingressRuleSet ;
115- this .egressRuleSet = egressRuleSet ;
106+ setIngressRuleSet ( ingressRuleSet ) ;
107+ this .setEgressRuleSet ( egressRuleSet ) ;
116108 this .guestMac = guestMac ;
117- this .signature = signature ;
118109 this .seqNum = seqNum ;
119110 this .vmId = vmId ;
120111 if (signature == null ) {
121- String stringified = stringifyRules ();
112+ final String stringified = stringifyRules ();
122113 this .signature = DigestUtils .md5Hex (stringified );
114+ } else {
115+ this .signature = signature ;
123116 }
124117 this .secIps = secIps ;
125118 }
@@ -129,20 +122,26 @@ public boolean executeInSequence() {
129122 return true ;
130123 }
131124
132- public IpPortAndProto [] getIngressRuleSet () {
125+ public List < IpPortAndProto > getIngressRuleSet () {
133126 return ingressRuleSet ;
134127 }
135128
136- public void setIngressRuleSet (IpPortAndProto [] ingressRuleSet ) {
137- this .ingressRuleSet = ingressRuleSet ;
129+ public void setIngressRuleSet (final IpPortAndProto ... ingressRuleSet ) {
130+ this .ingressRuleSet = new ArrayList <IpPortAndProto >();
131+ for (final IpPortAndProto rule : ingressRuleSet ) {
132+ this .ingressRuleSet .add (rule );
133+ }
138134 }
139135
140- public IpPortAndProto [] getEgressRuleSet () {
136+ public List < IpPortAndProto > getEgressRuleSet () {
141137 return egressRuleSet ;
142138 }
143139
144- public void setEgressRuleSet (IpPortAndProto [] egressRuleSet ) {
145- this .egressRuleSet = egressRuleSet ;
140+ public void setEgressRuleSet (final IpPortAndProto ... egressRuleSet ) {
141+ this .egressRuleSet = new ArrayList <IpPortAndProto >();
142+ for (final IpPortAndProto rule : egressRuleSet ) {
143+ this .egressRuleSet .add (rule );
144+ }
146145 }
147146
148147 public String getGuestIp () {
@@ -157,105 +156,77 @@ public String getVmName() {
157156 return vmName ;
158157 }
159158
160- public String stringifyRules () {
161- StringBuilder ruleBuilder = new StringBuilder ();
162- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getIngressRuleSet ()) {
163- ruleBuilder .append ("I:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
164- for (String cidr : ipPandP .getAllowedCidrs ()) {
165- ruleBuilder .append (cidr ).append ("," );
166- }
167- ruleBuilder .append ("NEXT" );
168- ruleBuilder .append (" " );
169- }
170- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getEgressRuleSet ()) {
171- ruleBuilder .append ("E:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
172- for (String cidr : ipPandP .getAllowedCidrs ()) {
173- ruleBuilder .append (cidr ).append ("," );
174- }
175- ruleBuilder .append ("NEXT" );
176- ruleBuilder .append (" " );
177- }
178- return ruleBuilder .toString ();
179- }
180-
181- //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e"
182- private String compressCidr (String cidr ) {
183- String [] toks = cidr .split ("/" );
184- long ipnum = NetUtils .ip2Long (toks [0 ]);
185- return Long .toHexString (ipnum ) + "/" + toks [1 ];
159+ private String compressCidrToHexRepresentation (final String cidr ) {
160+ final String [] toks = cidr .split (CIDR_LENGTH_SEPARATOR );
161+ final long ipnum = NetUtils .ip2Long (toks [0 ]);
162+ return Long .toHexString (ipnum ) + CIDR_LENGTH_SEPARATOR + toks [1 ];
186163 }
187164
188165 public String getSecIpsString () {
189- StringBuilder sb = new StringBuilder ();
190- List <String > ips = getSecIps ();
166+ final StringBuilder sb = new StringBuilder ();
167+ final List <String > ips = getSecIps ();
191168 if (ips == null ) {
192- return "0:" ;
169+ sb . append ( "0:" ) ;
193170 } else {
194- for (String ip : ips ) {
195- sb .append (ip ).append (":" );
171+ for (final String ip : ips ) {
172+ sb .append (ip ).append (RULE_COMMAND_SEPARATOR );
196173 }
197174 }
198175 return sb .toString ();
199176 }
200177
178+ public String stringifyRules () {
179+ final StringBuilder ruleBuilder = new StringBuilder ();
180+ stringifyRulesFor (getIngressRuleSet (), INGRESS_RULE , false , ruleBuilder );
181+ stringifyRulesFor (getEgressRuleSet (), EGRESS_RULE , false , ruleBuilder );
182+ return ruleBuilder .toString ();
183+ }
184+
201185 public String stringifyCompressedRules () {
202- StringBuilder ruleBuilder = new StringBuilder ();
203- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getIngressRuleSet ()) {
204- ruleBuilder .append ("I:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
205- for (String cidr : ipPandP .getAllowedCidrs ()) {
206- //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e"
207- ruleBuilder .append (compressCidr (cidr )).append ("," );
186+ final StringBuilder ruleBuilder = new StringBuilder ();
187+ stringifyRulesFor (getIngressRuleSet (), INGRESS_RULE , true , ruleBuilder );
188+ stringifyRulesFor (getEgressRuleSet (), EGRESS_RULE , true , ruleBuilder );
189+ return ruleBuilder .toString ();
190+ }
191+
192+ private void stringifyRulesFor (final List <IpPortAndProto > ipPortAndProtocols , final String inOrEgress , final boolean compressed , final StringBuilder ruleBuilder ) {
193+ for (final IpPortAndProto ipPandP : ipPortAndProtocols ) {
194+ ruleBuilder .append (inOrEgress ).append (ipPandP .getProto ()).append (RULE_COMMAND_SEPARATOR ).append (ipPandP .getStartPort ()).append (RULE_COMMAND_SEPARATOR )
195+ .append (ipPandP .getEndPort ()).append (RULE_COMMAND_SEPARATOR );
196+ for (final String cidr : ipPandP .getAllowedCidrs ()) {
197+ ruleBuilder .append (represent (cidr , compressed )).append (RULE_TARGET_SEPARATOR );
208198 }
209- ruleBuilder .append ("NEXT" );
210- ruleBuilder .append (" " );
199+ ruleBuilder .append ("NEXT " );
211200 }
212- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getEgressRuleSet ()) {
213- ruleBuilder .append ("E:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
214- for (String cidr : ipPandP .getAllowedCidrs ()) {
215- //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e"
216- ruleBuilder .append (compressCidr (cidr )).append ("," );
217- }
218- ruleBuilder .append ("NEXT" );
219- ruleBuilder .append (" " );
201+ }
202+
203+ private String represent (final String cidr , final boolean compressed ) {
204+ if (compressed ) {
205+ return compressCidrToHexRepresentation (cidr );
206+ } else {
207+ return cidr ;
220208 }
221- return ruleBuilder .toString ();
222209 }
223210
224- /*
211+ /**
225212 * Compress the security group rules using zlib compression to allow the call to the hypervisor
226213 * to scale beyond 8k cidrs.
214+ * Note : not using {@see GZipOutputStream} since that is for files, using {@see DeflaterOutputStream} instead.
215+ * {@see GZipOutputStream} gives a different header, although the compression is the same
227216 */
228217 public String compressStringifiedRules () {
229- StringBuilder ruleBuilder = new StringBuilder ();
230- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getIngressRuleSet ()) {
231- ruleBuilder .append ("I:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
232- for (String cidr : ipPandP .getAllowedCidrs ()) {
233- ruleBuilder .append (cidr ).append ("," );
234- }
235- ruleBuilder .append ("NEXT" );
236- ruleBuilder .append (" " );
237- }
238- for (SecurityGroupRulesCmd .IpPortAndProto ipPandP : getEgressRuleSet ()) {
239- ruleBuilder .append ("E:" ).append (ipPandP .getProto ()).append (":" ).append (ipPandP .getStartPort ()).append (":" ).append (ipPandP .getEndPort ()).append (":" );
240- for (String cidr : ipPandP .getAllowedCidrs ()) {
241- ruleBuilder .append (cidr ).append ("," );
242- }
243- ruleBuilder .append ("NEXT" );
244- ruleBuilder .append (" " );
245- }
246- String stringified = ruleBuilder .toString ();
247- ByteArrayOutputStream out = new ByteArrayOutputStream ();
218+ final String stringified = stringifyRules ();
219+ final ByteArrayOutputStream out = new ByteArrayOutputStream ();
220+ String encodedResult = null ;
248221 try {
249- //Note : not using GZipOutputStream since that is for files
250- //GZipOutputStream gives a different header, although the compression is the same
251- DeflaterOutputStream dzip = new DeflaterOutputStream (out );
222+ final DeflaterOutputStream dzip = new DeflaterOutputStream (out );
252223 dzip .write (stringified .getBytes ());
253224 dzip .close ();
254- } catch ( IOException e ) {
255- s_logger . warn ( "Exception while compressing security group rules" );
256- return null ;
225+ encodedResult = Base64 . encodeBase64String ( out . toByteArray ());
226+ } catch ( final IOException e ) {
227+ LOGGER . warn ( "Exception while compressing security group rules" ) ;
257228 }
258- return Base64 . encodeBase64String ( out . toByteArray ()) ;
229+ return encodedResult ;
259230 }
260231
261232 public String getSignature () {
@@ -274,19 +245,22 @@ public Long getVmId() {
274245 return vmId ;
275246 }
276247
248+ /**
249+ * used for logging
250+ * @return the number of Cidrs in the in and egress rule sets for this security group rules command.
251+ */
277252 public int getTotalNumCidrs () {
278- //useful for logging
279253 int count = 0 ;
280- for (IpPortAndProto i : ingressRuleSet ) {
281- count += i .allowedCidrs .length ;
254+ for (final IpPortAndProto i : ingressRuleSet ) {
255+ count += i .allowedCidrs .size () ;
282256 }
283- for (IpPortAndProto i : egressRuleSet ) {
284- count += i .allowedCidrs .length ;
257+ for (final IpPortAndProto i : egressRuleSet ) {
258+ count += i .allowedCidrs .size () ;
285259 }
286260 return count ;
287261 }
288262
289- public void setMsId (long msId ) {
263+ public void setMsId (final long msId ) {
290264 this .msId = msId ;
291265 }
292266
0 commit comments