// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by the License. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.agent.api; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.DeflaterOutputStream; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.utils.net.NetUtils; public class SecurityGroupRulesCmd extends Command { private static Logger s_logger = Logger.getLogger(SecurityGroupRulesCmd.class); public static class IpPortAndProto { private String proto; private int startPort; private int endPort; @LogLevel(Log4jLevel.Trace) private String [] allowedCidrs; public IpPortAndProto() { } public IpPortAndProto(String proto, int startPort, int endPort, String[] allowedCidrs) { super(); this.proto = proto; this.startPort = startPort; this.endPort = endPort; this.allowedCidrs = allowedCidrs; } public String[] getAllowedCidrs() { return allowedCidrs; } public void setAllowedCidrs(String[] allowedCidrs) { this.allowedCidrs = allowedCidrs; } public String getProto() { return proto; } public int getStartPort() { return startPort; } public int getEndPort() { return endPort; } } String guestIp; String vmName; String guestMac; String signature; Long seqNum; Long vmId; Long msId; IpPortAndProto [] ingressRuleSet; IpPortAndProto [] egressRuleSet; public SecurityGroupRulesCmd() { super(); } public SecurityGroupRulesCmd(String guestIp, String guestMac, String vmName, Long vmId, String signature, Long seqNum, IpPortAndProto[] ingressRuleSet, IpPortAndProto[] egressRuleSet) { super(); this.guestIp = guestIp; this.vmName = vmName; this.ingressRuleSet = ingressRuleSet; this.egressRuleSet = egressRuleSet; this.guestMac = guestMac; this.signature = signature; this.seqNum = seqNum; this.vmId = vmId; if (signature == null) { String stringified = stringifyRules(); this.signature = DigestUtils.md5Hex(stringified); } } @Override public boolean executeInSequence() { return true; } public IpPortAndProto[] getIngressRuleSet() { return ingressRuleSet; } public void setIngressRuleSet(IpPortAndProto[] ingressRuleSet) { this.ingressRuleSet = ingressRuleSet; } public IpPortAndProto[] getEgressRuleSet() { return egressRuleSet; } public void setEgressRuleSet(IpPortAndProto[] egressRuleSet) { this.egressRuleSet = egressRuleSet; } public String getGuestIp() { return guestIp; } public String getVmName() { return vmName; } public String stringifyRules() { StringBuilder ruleBuilder = new StringBuilder(); for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getIngressRuleSet()) { ruleBuilder.append("I:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getEgressRuleSet()) { ruleBuilder.append("E:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } return ruleBuilder.toString(); } //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e" private String compressCidr(String cidr) { String [] toks = cidr.split("/"); long ipnum = NetUtils.ip2Long(toks[0]); return Long.toHexString(ipnum) + "/" + toks[1]; } public String stringifyCompressedRules() { StringBuilder ruleBuilder = new StringBuilder(); for (SecurityGroupRulesCmd.IpPortAndProto ipPandP : getIngressRuleSet()) { ruleBuilder.append("I:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e" ruleBuilder.append(compressCidr(cidr)).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } for (SecurityGroupRulesCmd.IpPortAndProto ipPandP : getEgressRuleSet()) { ruleBuilder.append("E:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { //convert cidrs in the form "a.b.c.d/e" to "hexvalue of 32bit ip/e" ruleBuilder.append(compressCidr(cidr)).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } return ruleBuilder.toString(); } /* * Compress the security group rules using zlib compression to allow the call to the hypervisor * to scale beyond 8k cidrs. */ public String compressStringifiedRules() { StringBuilder ruleBuilder = new StringBuilder(); for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getIngressRuleSet()) { ruleBuilder.append("I:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getEgressRuleSet()) { ruleBuilder.append("E:").append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); } ruleBuilder.append("NEXT"); ruleBuilder.append(" "); } String stringified = ruleBuilder.toString(); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { //Note : not using GZipOutputStream since that is for files //GZipOutputStream gives a different header, although the compression is the same DeflaterOutputStream dzip = new DeflaterOutputStream(out); dzip.write(stringified.getBytes()); dzip.close(); } catch (IOException e) { s_logger.warn("Exception while compressing security group rules"); return null; } return Base64.encodeBase64String(out.toByteArray()); } public String getSignature() { return signature; } public String getGuestMac() { return guestMac; } public Long getSeqNum() { return seqNum; } public Long getVmId() { return vmId; } public int getTotalNumCidrs() { //useful for logging int count = 0; for (IpPortAndProto i: ingressRuleSet) { count += i.allowedCidrs.length; } for (IpPortAndProto i: egressRuleSet) { count += i.allowedCidrs.length; } return count; } public void setMsId(long msId) { this.msId = msId; } public Long getMsId() { return msId; } }