diff --git a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java index e6a4ea4646a..4b34f3a7e89 100644 --- a/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/FakeComputingResource.java @@ -63,8 +63,8 @@ import com.cloud.agent.api.ReadyAnswer; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; -import com.cloud.agent.api.SecurityIngressRuleAnswer; -import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; @@ -234,8 +234,8 @@ public class FakeComputingResource extends ServerResourceBase implements ServerR return execute((GetStorageStatsCommand) cmd); } else if (cmd instanceof ModifyStoragePoolCommand) { return execute((ModifyStoragePoolCommand) cmd); - } else if (cmd instanceof SecurityIngressRulesCmd) { - return execute((SecurityIngressRulesCmd) cmd); + } else if (cmd instanceof SecurityGroupRulesCmd) { + return execute((SecurityGroupRulesCmd) cmd); } else if (cmd instanceof StartCommand ) { return execute((StartCommand) cmd); } else if (cmd instanceof CleanupNetworkRulesCmd) { @@ -257,9 +257,9 @@ public class FakeComputingResource extends ServerResourceBase implements ServerR return new Answer(cmd); } - private Answer execute(SecurityIngressRulesCmd cmd) { + private Answer execute(SecurityGroupRulesCmd cmd) { s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); - return new SecurityIngressRuleAnswer(cmd); + return new SecurityGroupRuleAnswer(cmd); } private Answer execute(ModifyStoragePoolCommand cmd) { diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index d434f1181ef..2be00e6aef9 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -120,8 +120,8 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; -import com.cloud.agent.api.SecurityIngressRuleAnswer; -import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; @@ -913,8 +913,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return execute((CreateStoragePoolCommand) cmd); } else if (cmd instanceof ModifyStoragePoolCommand) { return execute((ModifyStoragePoolCommand) cmd); - } else if (cmd instanceof SecurityIngressRulesCmd) { - return execute((SecurityIngressRulesCmd) cmd); + } else if (cmd instanceof SecurityGroupRulesCmd) { + return execute((SecurityGroupRulesCmd) cmd); } else if (cmd instanceof DeleteStoragePoolCommand) { return execute((DeleteStoragePoolCommand) cmd); } else if (cmd instanceof FenceCommand ) { @@ -1568,7 +1568,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return answer; } - private Answer execute(SecurityIngressRulesCmd cmd) { + private Answer execute(SecurityGroupRulesCmd cmd) { String vif = null; String brname = null; try { @@ -1577,10 +1577,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv vif = nics.get(0).getDevName(); brname = nics.get(0).getBrName(); } catch (LibvirtException e) { - return new SecurityIngressRuleAnswer(cmd, false, e.toString()); + return new SecurityGroupRuleAnswer(cmd, false, e.toString()); } - boolean result = add_network_rules(cmd.getVmName(), + boolean result = add_network_rules(cmd.getRuleType(), cmd.getVmName(), Long.toString(cmd.getVmId()), cmd.getGuestIp(),cmd.getSignature(), Long.toString(cmd.getSeqNum()), @@ -1589,10 +1589,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (!result) { s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); - return new SecurityIngressRuleAnswer(cmd, false, "programming network rules failed"); + return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed"); } else { s_logger.debug("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); - return new SecurityIngressRuleAnswer(cmd); + return new SecurityGroupRuleAnswer(cmd); } } @@ -3540,7 +3540,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return true; } - private boolean add_network_rules(String vmName, String vmId, String guestIP, String sig, String seq, String mac, String rules, String vif, String brname) { + private boolean add_network_rules(String ruleType, String vmName, String vmId, String guestIP, String sig, String seq, String mac, String rules, String vif, String brname) { if (!_can_bridge_firewall) { return false; } @@ -3551,6 +3551,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.add("--vmname", vmName); cmd.add("--vmid", vmId); cmd.add("--vmip", guestIP); + cmd.add("--ruletype", ruleType); cmd.add("--sig", sig); cmd.add("--seq", seq); cmd.add("--vmmac", mac); diff --git a/api/src/com/cloud/agent/api/SecurityEgressRuleAnswer.java b/api/src/com/cloud/agent/api/SecurityEgressRuleAnswer.java deleted file mode 100644 index 1b0d33326c1..00000000000 --- a/api/src/com/cloud/agent/api/SecurityEgressRuleAnswer.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.cloud.agent.api; - -public class SecurityEgressRuleAnswer extends Answer { - Long logSequenceNumber = null; - Long vmId = null; - - protected SecurityEgressRuleAnswer() { - } - - public SecurityEgressRuleAnswer(SecurityEgressRulesCmd cmd) { - super(cmd); - this.logSequenceNumber = cmd.getSeqNum(); - this.vmId = cmd.getVmId(); - } - - public SecurityEgressRuleAnswer(SecurityEgressRulesCmd cmd, boolean result, String detail) { - super(cmd, result, detail); - this.logSequenceNumber = cmd.getSeqNum(); - this.vmId = cmd.getVmId(); - } - - public Long getLogSequenceNumber() { - return logSequenceNumber; - } - - public Long getVmId() { - return vmId; - } - -} diff --git a/api/src/com/cloud/agent/api/SecurityEgressRulesCmd.java b/api/src/com/cloud/agent/api/SecurityEgressRulesCmd.java deleted file mode 100644 index f9c096d7768..00000000000 --- a/api/src/com/cloud/agent/api/SecurityEgressRulesCmd.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.cloud.agent.api; - - -public class SecurityEgressRulesCmd extends Command { - public static class EgressIpPortAndProto { - String proto; - int startPort; - int endPort; - String [] allowedCidrs; - - public EgressIpPortAndProto() { } - - public EgressIpPortAndProto(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; - EgressIpPortAndProto [] ruleSet; - - public SecurityEgressRulesCmd() { - super(); - } - - - public SecurityEgressRulesCmd(String guestIp, String guestMac, String vmName, Long vmId, String signature, Long seqNum, EgressIpPortAndProto[] ruleSet) { - super(); - this.guestIp = guestIp; - this.vmName = vmName; - this.ruleSet = ruleSet; - this.guestMac = guestMac; - this.signature = signature; - this.seqNum = seqNum; - this.vmId = vmId; - } - - - @Override - public boolean executeInSequence() { - return true; - } - - - public EgressIpPortAndProto[] getRuleSet() { - return ruleSet; - } - - - public void setRuleSet(EgressIpPortAndProto[] ruleSet) { - this.ruleSet = ruleSet; - } - - - public String getGuestIp() { - return guestIp; - } - - - public String getVmName() { - return vmName; - } - - public String stringifyRules() { - StringBuilder ruleBuilder = new StringBuilder(); - for (SecurityEgressRulesCmd.EgressIpPortAndProto ipPandP: getRuleSet()) { - ruleBuilder.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(); - } - - public String getSignature() { - return signature; - } - - - public String getGuestMac() { - return guestMac; - } - - - public Long getSeqNum() { - return seqNum; - } - - - public Long getVmId() { - return vmId; - } - -} diff --git a/api/src/com/cloud/agent/api/SecurityIngressRuleAnswer.java b/api/src/com/cloud/agent/api/SecurityGroupRuleAnswer.java similarity index 82% rename from api/src/com/cloud/agent/api/SecurityIngressRuleAnswer.java rename to api/src/com/cloud/agent/api/SecurityGroupRuleAnswer.java index caaf00006ce..9c81bfb77d2 100644 --- a/api/src/com/cloud/agent/api/SecurityIngressRuleAnswer.java +++ b/api/src/com/cloud/agent/api/SecurityGroupRuleAnswer.java @@ -17,7 +17,7 @@ */ package com.cloud.agent.api; -public class SecurityIngressRuleAnswer extends Answer { +public class SecurityGroupRuleAnswer extends Answer { public static enum FailureReason { NONE, UNKNOWN, @@ -29,23 +29,23 @@ public class SecurityIngressRuleAnswer extends Answer { FailureReason reason = FailureReason.NONE; - protected SecurityIngressRuleAnswer() { + protected SecurityGroupRuleAnswer() { } - public SecurityIngressRuleAnswer(SecurityIngressRulesCmd cmd) { + public SecurityGroupRuleAnswer(SecurityGroupRulesCmd cmd) { super(cmd); this.logSequenceNumber = cmd.getSeqNum(); this.vmId = cmd.getVmId(); } - public SecurityIngressRuleAnswer(SecurityIngressRulesCmd cmd, boolean result, String detail) { + public SecurityGroupRuleAnswer(SecurityGroupRulesCmd cmd, boolean result, String detail) { super(cmd, result, detail); this.logSequenceNumber = cmd.getSeqNum(); this.vmId = cmd.getVmId(); reason = FailureReason.PROGRAMMING_FAILED; } - public SecurityIngressRuleAnswer(SecurityIngressRulesCmd cmd, boolean result, String detail, FailureReason r) { + public SecurityGroupRuleAnswer(SecurityGroupRulesCmd cmd, boolean result, String detail, FailureReason r) { super(cmd, result, detail); this.logSequenceNumber = cmd.getSeqNum(); this.vmId = cmd.getVmId(); diff --git a/api/src/com/cloud/agent/api/SecurityIngressRulesCmd.java b/api/src/com/cloud/agent/api/SecurityGroupRulesCmd.java similarity index 85% rename from api/src/com/cloud/agent/api/SecurityIngressRulesCmd.java rename to api/src/com/cloud/agent/api/SecurityGroupRulesCmd.java index 439598e1299..27c044eb03e 100644 --- a/api/src/com/cloud/agent/api/SecurityIngressRulesCmd.java +++ b/api/src/com/cloud/agent/api/SecurityGroupRulesCmd.java @@ -26,11 +26,12 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.utils.net.NetUtils; -public class SecurityIngressRulesCmd extends Command { - private static Logger s_logger = Logger.getLogger(SecurityIngressRulesCmd.class); +public class SecurityGroupRulesCmd extends Command { + private static Logger s_logger = Logger.getLogger(SecurityGroupRulesCmd.class); public static class IpPortAndProto { String proto; int startPort; @@ -80,13 +81,14 @@ public class SecurityIngressRulesCmd extends Command { Long vmId; Long msId; IpPortAndProto [] ruleSet; + SecurityRuleType ruleType; - public SecurityIngressRulesCmd() { + public SecurityGroupRulesCmd() { super(); } - public SecurityIngressRulesCmd(String guestIp, String guestMac, String vmName, Long vmId, String signature, Long seqNum, IpPortAndProto[] ruleSet) { + public SecurityGroupRulesCmd(SecurityRuleType ruleType, String guestIp, String guestMac, String vmName, Long vmId, String signature, Long seqNum, IpPortAndProto[] ruleSet) { super(); this.guestIp = guestIp; this.vmName = vmName; @@ -95,12 +97,17 @@ public class SecurityIngressRulesCmd extends Command { this.signature = signature; this.seqNum = seqNum; this.vmId = vmId; + this.ruleType = ruleType; if (signature == null) { String stringified = stringifyRules(); this.signature = DigestUtils.md5Hex(stringified); } } + public String getRuleType(){ + if (this.ruleType == SecurityRuleType.EgressRule) return SecurityRuleType.EgressRule.getType(); + return SecurityRuleType.IngressRule.getType(); + } @Override public boolean executeInSequence() { @@ -129,7 +136,7 @@ public class SecurityIngressRulesCmd extends Command { public String stringifyRules() { StringBuilder ruleBuilder = new StringBuilder(); - for (SecurityIngressRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { + for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { ruleBuilder.append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); @@ -150,7 +157,7 @@ public class SecurityIngressRulesCmd extends Command { public String stringifyCompressedRules() { StringBuilder ruleBuilder = new StringBuilder(); - for (SecurityIngressRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { + for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { ruleBuilder.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" @@ -162,12 +169,12 @@ public class SecurityIngressRulesCmd extends Command { return ruleBuilder.toString(); } /* - * Compress the ingress rules using zlib compression to allow the call to the hypervisor + * 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 (SecurityIngressRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { + for (SecurityGroupRulesCmd.IpPortAndProto ipPandP: getRuleSet()) { ruleBuilder.append(ipPandP.getProto()).append(":").append(ipPandP.getStartPort()).append(":").append(ipPandP.getEndPort()).append(":"); for (String cidr: ipPandP.getAllowedCidrs()) { ruleBuilder.append(cidr).append(","); @@ -184,7 +191,7 @@ public class SecurityIngressRulesCmd extends Command { dzip.write(stringified.getBytes()); dzip.close(); } catch (IOException e) { - s_logger.warn("Exception while compressing ingress rules"); + s_logger.warn("Exception while compressing security group rules"); return null; } return Base64.encodeBase64String(out.toByteArray()); diff --git a/api/src/com/cloud/api/ResponseGenerator.java b/api/src/com/cloud/api/ResponseGenerator.java index 200f4bcc934..6869b2c2138 100755 --- a/api/src/com/cloud/api/ResponseGenerator.java +++ b/api/src/com/cloud/api/ResponseGenerator.java @@ -96,8 +96,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.security.EgressRule; -import com.cloud.network.security.IngressRule; +import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupRules; import com.cloud.offering.DiskOffering; @@ -196,9 +195,7 @@ public interface ResponseGenerator { ListResponse createSecurityGroupResponses(List networkGroups); - SecurityGroupResponse createSecurityGroupResponseFromIngressRule(List ingressRules); - - SecurityGroupResponse createSecurityGroupResponseFromEgressRule(List egressRules); + SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List SecurityRules); SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group); diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java new file mode 100644 index 00000000000..467d1540323 --- /dev/null +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java @@ -0,0 +1,233 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.BaseCmd; +import com.cloud.api.IdentityMapper; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; + +import com.cloud.api.response.SecurityGroupRuleResponse; +import com.cloud.api.response.SecurityGroupResponse; +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.security.SecurityRule; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.utils.StringUtils; + +@Implementation(responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group") +@SuppressWarnings("rawtypes") +public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName()); + + private static final String s_name = "authorizesecuritygroupegressresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "TCP is default. UDP is the other supported protocol") + private String protocol; + + @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "start port for this egress rule") + private Integer startPort; + + @Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "end port for this egress rule") + private Integer endPort; + + @Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent") + private Integer icmpType; + + @Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message") + private Integer icmpCode; + + @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.LIST, collectionType=CommandType.STRING, description="the cidr list associated") + private List cidrList; + + @Parameter(name = ApiConstants.USER_SECURITY_GROUP_LIST, type = CommandType.MAP, description = "user to security group mapping") + private Map userSecurityGroupList; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="an optional domainId for the security group. If the account parameter is used, domainId must also be used.") + private Long domainId; + + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the security group. Must be used with domainId.") + private String accountName; + + @IdentityMapper(entityTableName="projects") + @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="an optional project of the security group") + private Long projectId; + + @IdentityMapper(entityTableName="security_group") + @Parameter(name=ApiConstants.SECURITY_GROUP_ID, type=CommandType.LONG, description="The ID of the security group. Mutually exclusive with securityGroupName parameter") + private Long securityGroupId; + + @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="The name of the security group. Mutually exclusive with securityGroupName parameter") + private String securityGroupName; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public List getCidrList() { + return cidrList; + } + + public Integer getEndPort() { + return endPort; + } + + public Integer getIcmpCode() { + return icmpCode; + } + + public Integer getIcmpType() { + return icmpType; + } + + public Long getSecurityGroupId() { + if (securityGroupId != null && securityGroupName != null) { + throw new InvalidParameterValueException("securityGroupId and securityGroupName parameters are mutually exclusive"); + } + + if (securityGroupName != null) { + securityGroupId = _responseGenerator.getSecurityGroupId(securityGroupName, getEntityOwnerId()); + if (securityGroupId == null) { + throw new InvalidParameterValueException("Unable to find security group " + securityGroupName + " for account id=" + getEntityOwnerId()); + } + securityGroupName = null; + } + + if (securityGroupId == null) { + throw new InvalidParameterValueException("Either securityGroupId or securityGroupName is required by authorizeSecurityGroupIngress command"); + } + + return securityGroupId; + } + + public String getProtocol() { + if (protocol == null) { + return "all"; + } + return protocol; + } + + public Integer getStartPort() { + return startPort; + } + + public Map getUserSecurityGroupList() { + return userSecurityGroupList; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public static String getResultObjectName() { + return "securitygroup"; + } + + @Override + public long getEntityOwnerId() { + Long accountId = getAccountId(accountName, domainId, projectId); + if (accountId == null) { + return UserContext.current().getCaller().getId(); + } + + return accountId; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS; + } + + @Override + public String getEventDescription() { + StringBuilder sb = new StringBuilder(); + if (getUserSecurityGroupList() != null) { + sb.append("group list(group/account): "); + Collection userGroupCollection = getUserSecurityGroupList().values(); + Iterator iter = userGroupCollection.iterator(); + + HashMap userGroup = (HashMap) iter.next(); + String group = (String) userGroup.get("group"); + String authorizedAccountName = (String) userGroup.get("account"); + sb.append(group + "/" + authorizedAccountName); + + while (iter.hasNext()) { + userGroup = (HashMap) iter.next(); + group = (String) userGroup.get("group"); + authorizedAccountName = (String) userGroup.get("account"); + sb.append(", " + group + "/" + authorizedAccountName); + } + } else if (getCidrList() != null) { + sb.append("cidr list: "); + sb.append(StringUtils.join(getCidrList(), ", ")); + } else { + sb.append(""); + } + + return "authorizing egress to group: " + getSecurityGroupId() + " to " + sb.toString(); + } + + @Override + public void execute() { + List egressRules = _securityGroupService.authorizeSecurityGroupEgress(this); + if (egressRules != null && !egressRules.isEmpty()) { + SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponseFromSecurityGroupRule(egressRules); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to authorize security group egress rule(s)"); + } + + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.SecurityGroup; + } + + @Override + public Long getInstanceId() { + return getSecurityGroupId(); + } +} diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java index 5150f381c77..2a4465c6de0 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java @@ -33,18 +33,16 @@ import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; -import com.cloud.api.BaseCmd.CommandType; -import com.cloud.api.response.IngressRuleResponse; +import com.cloud.api.response.SecurityGroupRuleResponse; import com.cloud.api.response.SecurityGroupResponse; import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.security.IngressRule; -import com.cloud.user.Account; +import com.cloud.network.security.SecurityRule; import com.cloud.user.UserContext; import com.cloud.utils.StringUtils; -@Implementation(responseObject = IngressRuleResponse.class, description = "Authorizes a particular ingress rule for this security group") +@Implementation(responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group") @SuppressWarnings("rawtypes") public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName()); @@ -212,9 +210,9 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { @Override public void execute() { - List ingressRules = _securityGroupService.authorizeSecurityGroupIngress(this); + List ingressRules = _securityGroupService.authorizeSecurityGroupIngress(this); if (ingressRules != null && !ingressRules.isEmpty()) { - SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponseFromIngressRule(ingressRules); + SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponseFromSecurityGroupRule(ingressRules); this.setResponseObject(response); } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to authorize security group ingress rule(s)"); diff --git a/api/src/com/cloud/api/commands/RevokeSecurityGroupEgressCmd.java b/api/src/com/cloud/api/commands/RevokeSecurityGroupEgressCmd.java new file mode 100644 index 00000000000..f9038314e9d --- /dev/null +++ b/api/src/com/cloud/api/commands/RevokeSecurityGroupEgressCmd.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.BaseCmd; +import com.cloud.api.IdentityMapper; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.SuccessResponse; +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.network.security.SecurityGroup; +import com.cloud.user.Account; + +@Implementation(responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group") +public class RevokeSecurityGroupEgressCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupEgressCmd.class.getName()); + + private static final String s_name = "revokesecuritygroupegress"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="security_group_rule") + @Parameter(name = ApiConstants.ID, type = CommandType.LONG, required = true, description = "The ID of the egress rule") + private Long id; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public static String getResultObjectName() { + return "revokesecuritygroupegress"; + } + + @Override + public long getEntityOwnerId() { + SecurityGroup group = _entityMgr.findById(SecurityGroup.class, getId()); + if (group != null) { + return group.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_SECURITY_GROUP_REVOKE_EGRESS; + } + + @Override + public String getEventDescription() { + return "revoking egress rule id: " + getId(); + } + + @Override + public void execute() { + boolean result = _securityGroupService.revokeSecurityGroupEgress(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to revoke security group egress rule"); + } + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.SecurityGroup; + } + + @Override + public Long getInstanceId() { + return getId(); + } +} diff --git a/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java index ed3da11015b..ef10852696a 100644 --- a/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/RevokeSecurityGroupIngressCmd.java @@ -43,7 +43,7 @@ public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// - @IdentityMapper(entityTableName="security_ingress_rule") + @IdentityMapper(entityTableName="security_group_rule") @Parameter(name = ApiConstants.ID, type = CommandType.LONG, required = true, description = "The ID of the ingress rule") private Long id; diff --git a/api/src/com/cloud/api/response/IngressRuleResponse.java b/api/src/com/cloud/api/response/IngressRuleResponse.java deleted file mode 100644 index 2a29e5b18f7..00000000000 --- a/api/src/com/cloud/api/response/IngressRuleResponse.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.cloud.api.response; - -import com.cloud.api.ApiConstants; -import com.cloud.api.IdentityProxy; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; - -public class IngressRuleResponse extends BaseResponse { - @SerializedName("ruleid") @Param(description="the id of the ingress rule") - private IdentityProxy ruleId = new IdentityProxy("security_ingress_rule"); - - @SerializedName("protocol") @Param(description="the protocol of the ingress rule") - private String protocol; - - @SerializedName(ApiConstants.ICMP_TYPE) @Param(description="the type of the ICMP message response") - private Integer icmpType; - - @SerializedName(ApiConstants.ICMP_CODE) @Param(description="the code for the ICMP message response") - private Integer icmpCode; - - @SerializedName(ApiConstants.START_PORT) @Param(description="the starting IP of the ingress rule") - private Integer startPort; - - @SerializedName(ApiConstants.END_PORT) @Param(description="the ending IP of the ingress rule ") - private Integer endPort; - - @SerializedName(ApiConstants.SECURITY_GROUP_NAME) @Param(description="security group name") - private String securityGroupName; - - @SerializedName(ApiConstants.ACCOUNT) @Param(description="account owning the ingress rule") - private String accountName; - - @SerializedName(ApiConstants.CIDR) @Param(description="the CIDR notation for the base IP address of the ingress rule") - private String cidr; - - public Long getRuleId() { - return ruleId.getValue(); - } - - public void setRuleId(Long ruleId) { - this.ruleId.setValue(ruleId); - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public Integer getIcmpType() { - return icmpType; - } - - public void setIcmpType(Integer icmpType) { - this.icmpType = icmpType; - } - - public Integer getIcmpCode() { - return icmpCode; - } - - public void setIcmpCode(Integer icmpCode) { - this.icmpCode = icmpCode; - } - - public Integer getStartPort() { - return startPort; - } - - public void setStartPort(Integer startPort) { - this.startPort = startPort; - } - - public Integer getEndPort() { - return endPort; - } - - public void setEndPort(Integer endPort) { - this.endPort = endPort; - } - - public String getSecurityGroupName() { - return securityGroupName; - } - - public void setSecurityGroupName(String securityGroupName) { - this.securityGroupName = securityGroupName; - } - - public String getAccountName() { - return accountName; - } - - public void setAccountName(String accountName) { - this.accountName = accountName; - } - - public String getCidr() { - return cidr; - } - - public void setCidr(String cidr) { - this.cidr = cidr; - } -} diff --git a/api/src/com/cloud/api/response/SecurityGroupResponse.java b/api/src/com/cloud/api/response/SecurityGroupResponse.java index 99a7f44d042..b7e00617813 100644 --- a/api/src/com/cloud/api/response/SecurityGroupResponse.java +++ b/api/src/com/cloud/api/response/SecurityGroupResponse.java @@ -50,12 +50,12 @@ public class SecurityGroupResponse extends BaseResponse implements ControlledEnt @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the security group") private String domainName; - @SerializedName("ingressrule") @Param(description="the list of ingress rules associated with the security group", responseObject = IngressRuleResponse.class) - private List ingressRules; - - @SerializedName("egressrule") @Param(description="the list of ingress rules associated with the security group", responseObject = EgressRuleResponse.class) - private List egressRules; + @SerializedName("ingressrule") @Param(description="the list of ingress rules associated with the security group", responseObject = SecurityGroupRuleResponse.class) + private List ingressRules; + @SerializedName("egressrule") @Param(description="the list of egress rules associated with the security group", responseObject = SecurityGroupRuleResponse.class) + private List egressRules; + public void setId(Long id) { this.id.setValue(id); } @@ -84,14 +84,14 @@ public class SecurityGroupResponse extends BaseResponse implements ControlledEnt this.domainName = domainName; } - public void setIngressRules(List ingressRules) { - this.ingressRules = ingressRules; - } - - public void setEgressRules(List egressRules) { - this.egressRules = egressRules; + public void setSecurityGroupIngressRules(List securityGroupRules) { + this.ingressRules = securityGroupRules; } + public void setSecurityGroupEgressRules(List securityGroupRules) { + this.egressRules = securityGroupRules; + } + @Override public Long getObjectId() { return getId(); diff --git a/api/src/com/cloud/api/response/EgressRuleResponse.java b/api/src/com/cloud/api/response/SecurityGroupRuleResponse.java similarity index 89% rename from api/src/com/cloud/api/response/EgressRuleResponse.java rename to api/src/com/cloud/api/response/SecurityGroupRuleResponse.java index 94ec20b7159..319a4b561c8 100644 --- a/api/src/com/cloud/api/response/EgressRuleResponse.java +++ b/api/src/com/cloud/api/response/SecurityGroupRuleResponse.java @@ -22,11 +22,11 @@ import com.cloud.api.IdentityProxy; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; -public class EgressRuleResponse extends BaseResponse { - @SerializedName("ruleid") @Param(description="the id of the ingress rule") - private IdentityProxy ruleId = new IdentityProxy("security_egress_rule"); +public class SecurityGroupRuleResponse extends BaseResponse { + @SerializedName("ruleid") @Param(description="the id of the security group rule") + private IdentityProxy ruleId = new IdentityProxy("security_group_rule"); - @SerializedName("protocol") @Param(description="the protocol of the ingress rule") + @SerializedName("protocol") @Param(description="the protocol of the security group rule") private String protocol; @SerializedName(ApiConstants.ICMP_TYPE) @Param(description="the type of the ICMP message response") @@ -35,19 +35,19 @@ public class EgressRuleResponse extends BaseResponse { @SerializedName(ApiConstants.ICMP_CODE) @Param(description="the code for the ICMP message response") private Integer icmpCode; - @SerializedName(ApiConstants.START_PORT) @Param(description="the starting IP of the ingress rule") + @SerializedName(ApiConstants.START_PORT) @Param(description="the starting IP of the security group rule") private Integer startPort; - @SerializedName(ApiConstants.END_PORT) @Param(description="the ending IP of the ingress rule ") + @SerializedName(ApiConstants.END_PORT) @Param(description="the ending IP of the security group rule ") private Integer endPort; @SerializedName(ApiConstants.SECURITY_GROUP_NAME) @Param(description="security group name") private String securityGroupName; - @SerializedName(ApiConstants.ACCOUNT) @Param(description="account owning the ingress rule") + @SerializedName(ApiConstants.ACCOUNT) @Param(description="account owning the security group rule") private String accountName; - @SerializedName(ApiConstants.CIDR) @Param(description="the CIDR notation for the base IP address of the ingress rule") + @SerializedName(ApiConstants.CIDR) @Param(description="the CIDR notation for the base IP address of the security group rule") private String cidr; public Long getRuleId() { diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index e55f4441de3..1d190e33667 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -174,6 +174,8 @@ public class EventTypes { // Security Groups public static final String EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS = "SG.AUTH.INGRESS"; public static final String EVENT_SECURITY_GROUP_REVOKE_INGRESS = "SG.REVOKE.INGRESS"; + public static final String EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS = "SG.AUTH.EGRESS"; + public static final String EVENT_SECURITY_GROUP_REVOKE_EGRESS = "SG.REVOKE.EGRESS"; public static final String EVENT_SECURITY_GROUP_CREATE = "SG.CREATE"; public static final String EVENT_SECURITY_GROUP_DELETE = "SG.DELETE"; diff --git a/api/src/com/cloud/network/security/EgressRule.java b/api/src/com/cloud/network/security/EgressRule.java deleted file mode 100644 index 005e91d61d5..00000000000 --- a/api/src/com/cloud/network/security/EgressRule.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -package com.cloud.network.security; - -import com.cloud.async.AsyncInstanceCreateStatus; - -public interface EgressRule { - long getId(); - - long getSecurityGroupId(); - - int getStartPort(); - - int getEndPort(); - - String getProtocol(); - - AsyncInstanceCreateStatus getCreateStatus(); - - Long getAllowedNetworkId(); - - String getAllowedDestinationIpCidr(); - -} diff --git a/api/src/com/cloud/network/security/SecurityGroupRules.java b/api/src/com/cloud/network/security/SecurityGroupRules.java index 92ad02db00f..5bec8d58bb0 100644 --- a/api/src/com/cloud/network/security/SecurityGroupRules.java +++ b/api/src/com/cloud/network/security/SecurityGroupRules.java @@ -16,6 +16,7 @@ * */ package com.cloud.network.security; +import com.cloud.network.security.SecurityRule.SecurityRuleType; public interface SecurityGroupRules { long getId(); @@ -39,4 +40,6 @@ public interface SecurityGroupRules { Long getAllowedNetworkId(); String getAllowedSourceIpCidr(); + + SecurityRuleType getRuleType(); } diff --git a/api/src/com/cloud/network/security/SecurityGroupService.java b/api/src/com/cloud/network/security/SecurityGroupService.java index 8d90a205ee4..4b9c0ee54f2 100644 --- a/api/src/com/cloud/network/security/SecurityGroupService.java +++ b/api/src/com/cloud/network/security/SecurityGroupService.java @@ -20,10 +20,12 @@ package com.cloud.network.security; import java.util.List; import com.cloud.api.commands.AuthorizeSecurityGroupIngressCmd; +import com.cloud.api.commands.AuthorizeSecurityGroupEgressCmd; import com.cloud.api.commands.CreateSecurityGroupCmd; import com.cloud.api.commands.DeleteSecurityGroupCmd; import com.cloud.api.commands.ListSecurityGroupsCmd; import com.cloud.api.commands.RevokeSecurityGroupIngressCmd; +import com.cloud.api.commands.RevokeSecurityGroupEgressCmd; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; @@ -36,6 +38,7 @@ public interface SecurityGroupService { */ public SecurityGroup createSecurityGroup(CreateSecurityGroupCmd command) throws PermissionDeniedException, InvalidParameterValueException; boolean revokeSecurityGroupIngress(RevokeSecurityGroupIngressCmd cmd); + boolean revokeSecurityGroupEgress(RevokeSecurityGroupEgressCmd cmd); boolean deleteSecurityGroup(DeleteSecurityGroupCmd cmd) throws ResourceInUseException; @@ -46,6 +49,8 @@ public interface SecurityGroupService { */ public List searchForSecurityGroupRules(ListSecurityGroupsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException; - public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd); + public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd); + + public List authorizeSecurityGroupEgress(AuthorizeSecurityGroupEgressCmd cmd); } diff --git a/api/src/com/cloud/network/security/IngressRule.java b/api/src/com/cloud/network/security/SecurityRule.java similarity index 66% rename from api/src/com/cloud/network/security/IngressRule.java rename to api/src/com/cloud/network/security/SecurityRule.java index 6eaeabbcbb1..2d011f6bfab 100644 --- a/api/src/com/cloud/network/security/IngressRule.java +++ b/api/src/com/cloud/network/security/SecurityRule.java @@ -23,7 +23,21 @@ import com.cloud.async.AsyncInstanceCreateStatus; * @author ahuang * */ -public interface IngressRule { +public interface SecurityRule { + + public static class SecurityRuleType { + public static final SecurityRuleType IngressRule = new SecurityRuleType("ingress"); + public static final SecurityRuleType EgressRule = new SecurityRuleType("egress"); + + public SecurityRuleType(String type) { + this._type = type; + } + + public String getType(){ + return _type; + } + private String _type; + } long getId(); long getSecurityGroupId(); @@ -31,9 +45,15 @@ public interface IngressRule { int getStartPort(); int getEndPort(); - + + String getType(); + + SecurityRuleType getRuleType(); + String getProtocol(); + String getUuid(); + AsyncInstanceCreateStatus getCreateStatus(); Long getAllowedNetworkId(); diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index fdfb63ea81b..c4379fbdb95 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -224,6 +224,8 @@ createSecurityGroup=com.cloud.api.commands.CreateSecurityGroupCmd;15 deleteSecurityGroup=com.cloud.api.commands.DeleteSecurityGroupCmd;15 authorizeSecurityGroupIngress=com.cloud.api.commands.AuthorizeSecurityGroupIngressCmd;15 revokeSecurityGroupIngress=com.cloud.api.commands.RevokeSecurityGroupIngressCmd;15 +authorizeSecurityGroupEgress=com.cloud.api.commands.AuthorizeSecurityGroupEgressCmd;15 +revokeSecurityGroupEgress=com.cloud.api.commands.RevokeSecurityGroupEgressCmd;15 listSecurityGroups=com.cloud.api.commands.ListSecurityGroupsCmd;15 #### vm group commands diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 2c01472b06b..553f4980aaa 100755 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -115,10 +115,8 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; -import com.cloud.agent.api.SecurityEgressRuleAnswer; -import com.cloud.agent.api.SecurityEgressRulesCmd; -import com.cloud.agent.api.SecurityIngressRuleAnswer; -import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.SetupAnswer; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.StartAnswer; @@ -480,8 +478,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((VpnUsersCfgCommand)cmd); } else if (clazz == CheckSshCommand.class) { return execute((CheckSshCommand)cmd); - } else if (clazz == SecurityIngressRulesCmd.class) { - return execute((SecurityIngressRulesCmd) cmd); + } else if (clazz == SecurityGroupRulesCmd.class) { + return execute((SecurityGroupRulesCmd) cmd); } else if (clazz == OvsCreateGreTunnelCommand.class) { return execute((OvsCreateGreTunnelCommand)cmd); } else if (clazz == OvsSetTagAndFlowCommand.class) { @@ -4747,38 +4745,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge); } - - private Answer execute(SecurityEgressRulesCmd cmd) { - Connection conn = getConnection(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Sending network rules command to " + _host.ip); - } - - if (!_canBridgeFirewall) { - s_logger.info("Host " + _host.ip + " cannot do bridge firewalling"); - return new SecurityEgressRuleAnswer(cmd, false, "Host " + _host.ip + " cannot do bridge firewalling"); - } - - String result = callHostPlugin(conn, "vmops", "network_rules", - "vmName", cmd.getVmName(), - "vmIP", cmd.getGuestIp(), - "vmMAC", cmd.getGuestMac(), - "type", "egress", - "vmID", Long.toString(cmd.getVmId()), - "signature", cmd.getSignature(), - "seqno", Long.toString(cmd.getSeqNum()), - "rules", cmd.stringifyRules()); - - if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { - s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); - return new SecurityEgressRuleAnswer(cmd, false, "programming network rules failed"); - } else { - s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); - return new SecurityEgressRuleAnswer(cmd); - } - } - - private Answer execute(SecurityIngressRulesCmd cmd) { + + private Answer execute(SecurityGroupRulesCmd cmd) { Connection conn = getConnection(); if (s_logger.isTraceEnabled()) { s_logger.trace("Sending network rules command to " + _host.ip); @@ -4786,16 +4754,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (!_canBridgeFirewall) { s_logger.warn("Host " + _host.ip + " cannot do bridge firewalling"); - return new SecurityIngressRuleAnswer(cmd, false, + return new SecurityGroupRuleAnswer(cmd, false, "Host " + _host.ip + " cannot do bridge firewalling", - SecurityIngressRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); + SecurityGroupRuleAnswer.FailureReason.CANNOT_BRIDGE_FIREWALL); } - + String result = callHostPlugin(conn, "vmops", "network_rules", "vmName", cmd.getVmName(), "vmIP", cmd.getGuestIp(), "vmMAC", cmd.getGuestMac(), - "type", "ingress", + "type", cmd.getRuleType(), "vmID", Long.toString(cmd.getVmId()), "signature", cmd.getSignature(), "seqno", Long.toString(cmd.getSeqNum()), @@ -4804,10 +4772,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); - return new SecurityIngressRuleAnswer(cmd, false, "programming network rules failed"); + return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed"); } else { s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); - return new SecurityIngressRuleAnswer(cmd); + return new SecurityGroupRuleAnswer(cmd); } } diff --git a/core/src/com/cloud/network/security/EgressRuleVO.java b/core/src/com/cloud/network/security/EgressRuleVO.java deleted file mode 100644 index ef329b2f96b..00000000000 --- a/core/src/com/cloud/network/security/EgressRuleVO.java +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package com.cloud.network.security; - -import java.util.UUID; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; - -import com.cloud.api.Identity; -import com.cloud.async.AsyncInstanceCreateStatus; -import com.google.gson.annotations.Expose; - -@Entity -@Table(name = ("security_egress_rule")) -public class EgressRuleVO implements EgressRule, Identity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id") - private long id; - - @Column(name = "security_group_id") - private long securityGroupId; - - @Column(name = "start_port") - private int startPort; - - @Column(name = "end_port") - private int endPort; - - @Column(name = "protocol") - private String protocol; - - @Column(name = "allowed_network_id", nullable = true) - private Long allowedNetworkId = null; - - @Column(name = "allowed_ip_cidr", nullable = true) - private String allowedDestinationIpCidr = null; - - @Expose - @Column(name = "create_status", updatable = true, nullable = false) - @Enumerated(value = EnumType.STRING) - private AsyncInstanceCreateStatus createStatus; - - @Column(name = "uuid") - private String uuid = UUID.randomUUID().toString(); - - public EgressRuleVO() { - } - - public EgressRuleVO(long securityGroupId, int fromPort, int toPort, String protocol, long allowedNetworkId) { - this.securityGroupId = securityGroupId; - this.startPort = fromPort; - this.endPort = toPort; - this.protocol = protocol; - this.allowedNetworkId = allowedNetworkId; - } - - public EgressRuleVO(long securityGroupId, int fromPort, int toPort, String protocol, String allowedIpCidr) { - this.securityGroupId = securityGroupId; - this.startPort = fromPort; - this.endPort = toPort; - this.protocol = protocol; - this.allowedDestinationIpCidr = allowedIpCidr; - } - - @Override - public long getId() { - return id; - } - - @Override - public long getSecurityGroupId() { - return securityGroupId; - } - - @Override - public int getStartPort() { - return startPort; - } - - @Override - public int getEndPort() { - return endPort; - } - - @Override - public String getProtocol() { - return protocol; - } - - @Override - public AsyncInstanceCreateStatus getCreateStatus() { - return createStatus; - } - - public void setCreateStatus(AsyncInstanceCreateStatus createStatus) { - this.createStatus = createStatus; - } - - @Override - public Long getAllowedNetworkId() { - return allowedNetworkId; - } - - @Override - public String getAllowedDestinationIpCidr() { - return allowedDestinationIpCidr; - } - - @Override - public String getUuid() { - return this.uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } -} diff --git a/core/src/com/cloud/network/security/IngressRuleVO.java b/core/src/com/cloud/network/security/SecurityGroupRuleVO.java similarity index 75% rename from core/src/com/cloud/network/security/IngressRuleVO.java rename to core/src/com/cloud/network/security/SecurityGroupRuleVO.java index 4931a26f3a8..a6117223e97 100644 --- a/core/src/com/cloud/network/security/IngressRuleVO.java +++ b/core/src/com/cloud/network/security/SecurityGroupRuleVO.java @@ -34,8 +34,8 @@ import com.cloud.async.AsyncInstanceCreateStatus; import com.google.gson.annotations.Expose; @Entity -@Table(name = ("security_ingress_rule")) -public class IngressRuleVO implements IngressRule, Identity { +@Table(name = ("security_group_rule")) +public class SecurityGroupRuleVO implements SecurityRule { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @@ -50,6 +50,9 @@ public class IngressRuleVO implements IngressRule, Identity { @Column(name = "end_port") private int endPort; + @Column(name = "type") + private String type; + @Column(name = "protocol") private String protocol; @@ -67,38 +70,62 @@ public class IngressRuleVO implements IngressRule, Identity { @Column(name = "uuid") private String uuid; - public IngressRuleVO() { + public SecurityGroupRuleVO() { this.uuid = UUID.randomUUID().toString(); } - public IngressRuleVO(long securityGroupId, int fromPort, int toPort, String protocol, long allowedNetworkId) { + public SecurityGroupRuleVO(SecurityRuleType type,long securityGroupId, int fromPort, int toPort, String protocol, long allowedNetworkId ) { this.securityGroupId = securityGroupId; this.startPort = fromPort; this.endPort = toPort; this.protocol = protocol; this.allowedNetworkId = allowedNetworkId; this.uuid = UUID.randomUUID().toString(); + if (type == SecurityRuleType.IngressRule) + { + this.type = SecurityRuleType.IngressRule.getType(); + }else{ + this.type = SecurityRuleType.EgressRule.getType(); + } } - public IngressRuleVO(long securityGroupId, int fromPort, int toPort, String protocol, String allowedIpCidr) { + public SecurityGroupRuleVO(SecurityRuleType type,long securityGroupId, int fromPort, int toPort, String protocol, String allowedIpCidr) { this.securityGroupId = securityGroupId; this.startPort = fromPort; this.endPort = toPort; this.protocol = protocol; this.allowedSourceIpCidr = allowedIpCidr; this.uuid = UUID.randomUUID().toString(); + if (type == SecurityRuleType.IngressRule) + { + this.type = SecurityRuleType.IngressRule.getType(); + }else{ + this.type = SecurityRuleType.EgressRule.getType(); + } } @Override public long getId() { return id; } + + @Override + public String getType() { + return type; + } @Override public long getSecurityGroupId() { return securityGroupId; } - + + public SecurityRuleType getRuleType() { + if ("ingress".equalsIgnoreCase(this.type)) + return SecurityRuleType.IngressRule; + else + return SecurityRuleType.EgressRule; + } + @Override public int getStartPort() { return startPort; diff --git a/core/src/com/cloud/network/security/SecurityGroupRulesVO.java b/core/src/com/cloud/network/security/SecurityGroupRulesVO.java index 7485711ff94..fc2b4d6f56c 100644 --- a/core/src/com/cloud/network/security/SecurityGroupRulesVO.java +++ b/core/src/com/cloud/network/security/SecurityGroupRulesVO.java @@ -26,10 +26,11 @@ import javax.persistence.Id; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.SecondaryTable; import javax.persistence.Table; +import com.cloud.network.security.SecurityRule.SecurityRuleType; @Entity @Table(name = ("security_group")) -@SecondaryTable(name = "security_ingress_rule", join = "left", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "id", referencedColumnName = "security_group_id") }) +@SecondaryTable(name = "security_group_rule", join = "left", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "id", referencedColumnName = "security_group_id") }) public class SecurityGroupRulesVO implements SecurityGroupRules { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -48,22 +49,25 @@ public class SecurityGroupRulesVO implements SecurityGroupRules { @Column(name = "account_id") private Long accountId; - @Column(name = "id", table = "security_ingress_rule", insertable = false, updatable = false) + @Column(name = "id", table = "security_group_rule", insertable = false, updatable = false) private Long ruleId; - @Column(name = "start_port", table = "security_ingress_rule", insertable = false, updatable = false) + @Column(name = "start_port", table = "security_group_rule", insertable = false, updatable = false) private int startPort; - @Column(name = "end_port", table = "security_ingress_rule", insertable = false, updatable = false) + @Column(name = "end_port", table = "security_group_rule", insertable = false, updatable = false) private int endPort; - @Column(name = "protocol", table = "security_ingress_rule", insertable = false, updatable = false) + @Column(name = "protocol", table = "security_group_rule", insertable = false, updatable = false) private String protocol; + + @Column(name = "type", table = "security_group_rule", insertable = false, updatable = false) + private String type; - @Column(name = "allowed_network_id", table = "security_ingress_rule", insertable = false, updatable = false, nullable = true) + @Column(name = "allowed_network_id", table = "security_group_rule", insertable = false, updatable = false, nullable = true) private Long allowedNetworkId = null; - @Column(name = "allowed_ip_cidr", table = "security_ingress_rule", insertable = false, updatable = false, nullable = true) + @Column(name = "allowed_ip_cidr", table = "security_group_rule", insertable = false, updatable = false, nullable = true) private String allowedSourceIpCidr = null; public SecurityGroupRulesVO() { @@ -128,6 +132,15 @@ public class SecurityGroupRulesVO implements SecurityGroupRules { public String getProtocol() { return protocol; } + + @Override + public SecurityRuleType getRuleType() { + if ("ingress".equalsIgnoreCase(this.type)) { + return SecurityRuleType.IngressRule; + } else { + return SecurityRuleType.EgressRule; + } + } @Override public Long getAllowedNetworkId() { diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py index 511d8d30a53..ff99390a4d5 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py @@ -13,7 +13,8 @@ from OvmObjectModule import * import types import logging import popen2 -from OvmFaultConstants import toErrCode, dispatchErrCode, NoVmFoundException +import subprocess +from OvmFaultConstants import toErrCode, dispatchErrCode, NoVmFoundException, ShellExceutedFailedException from xmlrpclib import Fault as XmlRpcFault from OVSCommons import * from OvmLoggerModule import OvmLogger @@ -26,6 +27,7 @@ HEARTBEAT_DIR='heart_beat' ETC_HOSTS='/etc/hosts' HOSTNAME_FILE='/etc/sysconfig/network' OWNER_FILE_PREFIX='host_' +OCFS2_CONF='/etc/ocfs2/cluster.conf' logger = OvmLogger('OvmCommon') @@ -93,10 +95,18 @@ def BytesToM(bytes): def BytesToG(bytes): return bytes/(1024*1024*1024) +def runCmd(cmds): + process = subprocess.Popen(cmds, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if process.returncode != 0: + raise ShellExceutedFailedException(stderr, process.returncode) + return stdout + def doCmd(lst): cmds = [str(i) for i in lst] - logger.debug(doCmd, ' '.join(cmds)) - res = run_cmd(cmds) + cmdStr = ' '.join(cmds) + logger.debug(doCmd, cmdStr) + res = runCmd(cmdStr) logger.debug(doCmd, 'result:' + res) return res diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py index 09d2b15f5b8..3a5f9b84ef8 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmFaultConstants.py @@ -4,10 +4,20 @@ OvmVmErrCodeStub = 2000 OvmStoragePoolErrCodeStub = 3000 OvmNetworkErrCodeStub = 4000 OvmVolumeErrCodeStub = 5000 +OvmOCFS2ErrCodeStub = 6000 class NoVmFoundException(Exception): pass +class ShellExceutedFailedException(Exception): + stderr = '' + errCode = -1000 + + def __init__(self, err, code): + Exception.__init__(self, "%s, return code:%s"%(err, code)) + self.stderr = err + self.errCode = code + errCode = { # OvmDispatch is not class, these error codes are reserved "OvmDispatch.InvalidCallMethodFormat":OvmDispatcherStub+1, @@ -55,6 +65,8 @@ errCode = { "OvmVolume.createDataDisk":OvmVolumeErrCodeStub+1, "OvmVolume.createFromTemplate":OvmVolumeErrCodeStub+2, "OvmVolume.destroy":OvmVolumeErrCodeStub+3, + + "OvmOCFS2._addNode":OvmOCFS2ErrCodeStub+1, } diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py b/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py new file mode 100755 index 00000000000..ea2edd801da --- /dev/null +++ b/ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py @@ -0,0 +1,62 @@ +from OvmCommonModule import * + +logger = OvmLogger('OvmOCFS2') +class OvmOCFS2(OvmObject): + def _prepareConf(self, cluster): + conf = '''cluster: + node_count = 0 + name = %s + '''%cluster + dir = dirname(OCFS2_CONF) + if not isdir(dir): + os.makedirs(dir) + + fd = open(OCFS2_CONF, 'w') + fd.write(conf) + fd.close() + + def _addNode(self, name, nodeNum, ip, port, cluster, isOnline=True): + nodePath = '/sys/kernel/config/cluster/%s/node/%s'%(cluster, name) + if exists(nodePath): + logger.debug(OvmOCFS2._addNode, "node %s already exists, skip it(%s)"%(name, nodePath)) + return + + if not isOnline: + cmds = ['o2cb_ctl -C -n', name, '-t node', '-a number=%s'%nodeNum, '-a ip_address=%s'%ip, '-a ip_port=%s'%port, '-a cluster=%s'%cluster] + else: + cmds = ['o2cb_ctl -C -i -n', name, '-t node', '-a number=%s'%nodeNum, '-a ip_address=%s'%ip, '-a ip_port=%s'%port, '-a cluster=%s'%cluster] + + try: + doCmd(cmds) + except ShellExceutedFailedException, e: + if e.errCode == 239 or "already exists" in e.stderr: + logger.debug(OvmOCFS2._addNode, "node %s already exists, skip it(%s)"%(name, e.stderr)) + else: + raise e + + def _isClusterOnline(self, cluster): + cmds = ['service o2cb status', cluster] + res = doCmd(cmds) + for line in res.split('\n'): + if not 'Checking O2CB cluster' in line: continue + return not 'Offline' in line + + def _start(self, cluster): + #blank line are answer by clicking enter + cmd = ['service o2cb load'] + doCmd(cmd) + config=''' +y +o2cb +%s + + + + +EOF +'''%cluster + cmd = ['service o2cb configure', '< 255: raise Exception("%s nodes beyond maximum 255 allowed by OCFS2"%len(nodes)) - if compareClusterConfig(nodes): - logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Nodes configure are the same, return") - rs = SUCC() - return rs - - lines = [] - for n in nodes: - lines.append("node:\n") - lines.append("\tip_port = %s\n" % "7777") - lines.append("\tip_address = %s\n" % n["ip_address"]) - lines.append("\tnumber = %s\n" % n["number"]) - lines.append("\tname = %s\n" % n["name"]) - lines.append("\tcluster = %s\n" % clusterName) - lines.append("\n") - lines.append("cluster:\n") - lines.append("\tnode_count = %d\n" % len(nodes)) - lines.append("\tname = %s\n" % clusterName) - lines.append("\n") - conf = "".join(lines) - configureHostName(nodes) configureEtcHosts(nodes) - clusterm_set_ocfs2_cluster_conf(conf) - clusterm_start_o2cb_service() - logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure cluster.conf to:\n%s"%conf) + addNodes(nodes, clusterName) + OvmOCFS2()._start(clusterName) + fd = open(OCFS2_CONF, 'r') + conf = fd.readlines() + fd.close() + logger.debug(OvmStoragePool.prepareOCFS2Nodes, "Configure cluster.conf to:\n%s"%' '.join(conf)) rs = SUCC() return rs diff --git a/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index 304fad3a1e2..6b3695f4337 100755 --- a/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -55,8 +55,8 @@ import com.cloud.agent.api.ReadyAnswer; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; -import com.cloud.agent.api.SecurityIngressRuleAnswer; -import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; @@ -1045,7 +1045,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { } } - private Answer execute(SecurityIngressRulesCmd cmd) { + private Answer execute(SecurityGroupRulesCmd cmd) { boolean result = false; try { OvmVif.Details vif = getVifFromVm(cmd.getVmName(), null); @@ -1059,10 +1059,10 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { if (!result) { s_logger.warn("Failed to program network rules for vm " + cmd.getVmName()); - return new SecurityIngressRuleAnswer(cmd, false, "programming network rules failed"); + return new SecurityGroupRuleAnswer(cmd, false, "programming network rules failed"); } else { s_logger.info("Programmed network rules for vm " + cmd.getVmName() + " guestIp=" + cmd.getGuestIp() + ", numrules=" + cmd.getRuleSet().length); - return new SecurityIngressRuleAnswer(cmd); + return new SecurityGroupRuleAnswer(cmd); } } @@ -1270,8 +1270,8 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { return execute((FenceCommand)cmd); } else if (clazz == AttachIsoCommand.class) { return execute((AttachIsoCommand)cmd); - } else if (clazz == SecurityIngressRulesCmd.class) { - return execute((SecurityIngressRulesCmd) cmd); + } else if (clazz == SecurityGroupRulesCmd.class) { + return execute((SecurityGroupRulesCmd) cmd); } else if (clazz == CleanupNetworkRulesCmd.class) { return execute((CleanupNetworkRulesCmd) cmd); } else if (clazz == PrepareOCFS2NodesCommand.class) { diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 72733f617d7..1d855f20327 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -476,6 +476,7 @@ def ipset(ipsetname, proto, start, end, ips): def destroy_network_rules_for_vm(session, args): vm_name = args.pop('vmName') vmchain = chain_name(vm_name) + vmchain_egress = chain_name(vm_name) + "-eg" vmchain_default = chain_name_def(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vm_name) @@ -492,9 +493,14 @@ def destroy_network_rules_for_vm(session, args): util.pread2(['iptables', '-F', vmchain]) util.pread2(['iptables', '-X', vmchain]) except: - util.SMlog("Ignoring failure to delete chain " + vmchain) + util.SMlog("Ignoring failure to delete ingress chain " + vmchain) + try: + util.pread2(['iptables', '-F', vmchain_egress]) + util.pread2(['iptables', '-X', vmchain_egress]) + except: + util.SMlog("Ignoring failure to delete egress chain " + vmchain_egress) remove_rule_log_for_vm(vm_name) @@ -671,6 +677,7 @@ def default_network_rules(session, args): vmchain = chain_name(vm_name) + vmchain_egress = chain_name(vm_name) +"-eg" vmchain_default = chain_name_def(vm_name) destroy_ebtables_rules(vmchain) @@ -680,6 +687,11 @@ def default_network_rules(session, args): util.pread2(['iptables', '-N', vmchain]) except: util.pread2(['iptables', '-F', vmchain]) + + try: + util.pread2(['iptables', '-N', vmchain_egress]) + except: + util.pread2(['iptables', '-F', vmchain_egress]) try: util.pread2(['iptables', '-N', vmchain_default]) @@ -698,7 +710,8 @@ def default_network_rules(session, args): #don't let vm spoof its ip address for v in vifs: - util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip, '-j', 'RETURN']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip,'-p', 'udp', '--dport', '53', '-j', 'RETURN']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip, '-j', vmchain_egress]) util.pread2(['iptables', '-A', vmchain_default, '-j', vmchain]) except: util.SMlog("Failed to program default rules for vm " + vm_name) @@ -900,7 +913,7 @@ def cleanup_rules(session, args): instance = 'VM' try: - chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2 | sed 's/-def/-%s/'|sort|uniq" % instance + chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2 | sed 's/-def/-%s/' | sed 's/-eg//' |sort|uniq" % instance chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') cleaned = 0 cleanup = [] @@ -1026,6 +1039,7 @@ def network_rules(session, args): vm_name = args.get('vmName') vm_ip = args.get('vmIP') vm_id = args.get('vmID') + type = args.get('type') signature = args.pop('signature') seqno = args.pop('seqno') deflated = 'false' @@ -1055,7 +1069,14 @@ def network_rules(session, args): except: pass - vmchain = chain_name(vm_name) + if type == 'egress': + vmchain = chain_name(vm_name) + "-eg" + direction = "dst" + action = "RETURN" + else: + vmchain = chain_name(vm_name) + direction = "src" + action = "ACCEPT" reason = 'seqno_change_or_sig_change' [reprogramDefault, reprogramChain, rewriteLog] = \ check_rule_log_for_vm (vm_name, vm_id, vm_ip, domid, signature, seqno) @@ -1114,32 +1135,39 @@ def network_rules(session, args): util.SMlog(" failed to create ipset for rule " + str(tokens)) if protocol == 'all': - iptables = ['iptables', '-I', vmchain, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] + iptables = ['iptables', '-I', vmchain, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, direction, '-j', action] elif protocol != 'icmp': - iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, direction, '-j', action] else: range = start + "/" + end if start == "-1": range = "any" - iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-m', 'set', '--match-set', ipsetname, direction, '-j', action] cmds.append(iptables) util.SMlog(iptables) if allow_any and protocol != 'all': if protocol != 'icmp': - iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-j', 'ACCEPT'] + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-j', action] else: range = start + "/" + end if start == "-1": range = "any" - iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-j', 'ACCEPT'] + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-j', action] cmds.append(iptables) util.SMlog(iptables) util.pread2(['iptables', '-F', vmchain]) for cmd in cmds: util.pread2(cmd) - util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) + + if type == 'egress': + if len(cmds) == 0 : + util.pread2(['iptables', '-A', vmchain, '-j', 'RETURN']) + else: + util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) + else: + util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno) == False: return 'false' diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index de59df698c6..0378cc8bc2d 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -82,6 +82,7 @@ def ipset(ipsetname, proto, start, end, ips): def destroy_network_rules_for_vm(vm_name, vif=None): vmchain = vm_name + vmchain_egress = vm_name + "-eg" vmchain_default = None delete_rules_for_vm_in_bridge_firewall_chain(vm_name) @@ -111,7 +112,19 @@ def destroy_network_rules_for_vm(vm_name, vif=None): execute("iptables -X " + vmchain) except: logging.debug("Ignoring failure to delete chain " + vmchain) + + + try: + execute("iptables -F " + vmchain_egress) + except: + logging.debug("Ignoring failure to delete chain " + vmchain_egress) + try: + execute("iptables -X " + vmchain_egress) + except: + logging.debug("Ignoring failure to delete chain " + vmchain_egress) + + if vif is not None: try: dnats = execute("iptables -t nat -S | grep " + vif + " | sed 's/-A/-D/'").split("\n") @@ -246,6 +259,7 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): domID = getvmId(vm_name) delete_rules_for_vm_in_bridge_firewall_chain(vmName) vmchain = vm_name + vmchain_egress = vm_name +"-eg" vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def" destroy_ebtables_rules(vmName, vif) @@ -254,7 +268,12 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): execute("iptables -N " + vmchain) except: execute("iptables -F " + vmchain) - + + try: + execute("iptables -N " + vmchain_egress) + except: + execute("iptables -F " + vmchain_egress) + try: execute("iptables -N " + vmchain_default) except: @@ -270,7 +289,8 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname): #don't let vm spoof its ip address if vm_ip is not None: - execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -p udp --dport 57 -j RETURN ") + execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j " + vmchain_egress) execute("iptables -A " + vmchain_default + " -j " + vmchain) execute("iptables -A " + vmchain + " -j DROP") except: @@ -468,7 +488,7 @@ def cleanup_rules_for_dead_vms(): def cleanup_rules(): try: - chainscmd = "iptables-save | grep '^:' | grep -v '.*-def' | awk '{print $1}' | cut -d':' -f2" + chainscmd = "iptables-save | grep '^:' | grep -v '.*-def' | grep -v '.*-eg' | awk '{print $1}' | cut -d':' -f2" chains = execute(chainscmd).split('\n') cleaned = 0 cleanup = [] @@ -552,12 +572,21 @@ def remove_rule_log_for_vm(vmName): return result -def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif, brname): +def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif, brname,ruletype): try: vmName = vm_name domId = getvmId(vmName) - vmchain = vm_name + if ruletype == 'egress': + vmchain = vm_name + "-eg" + direction = "-d" + action = "RETURN" + else: + vmchain = vm_name + direction = "-s" + action = "ACCEPT" + + changes = [] changes = check_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) @@ -596,28 +625,35 @@ def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif if ips: if protocol == 'all': for ip in ips: - execute("iptables -I " + vmchain + " -m state --state NEW -s " + ip + " -j ACCEPT") + execute("iptables -I " + vmchain + " -m state --state NEW " + direction + " " + ip + " -j "+action) elif protocol != 'icmp': for ip in ips: - execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW -s " + ip + " -j ACCEPT") + execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW " + direction + " " + ip + " -j "+action) else: range = start + "/" + end if start == "-1": range = "any" for ip in ips: - execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " -s " + ip + " -j ACCEPT") + execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " " + direction + " " + ip + " -j "+action) if allow_any and protocol != 'all': if protocol != 'icmp': - execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW -j ACCEPT") + execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW -j "+action) else: range = start + "/" + end if start == "-1": range = "any" - execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " -j ACCEPT") - - iptables = "iptables -A " + vmchain + " -j DROP" - execute(iptables) + execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " -j "+action) + if ruletype == 'egress': + if len(lines) == 0 : + iptables = "iptables -A " + vmchain + " -j RETURN" + execute(iptables) + else: + iptables = "iptables -A " + vmchain + " -j DROP" + execute(iptables) + else: + iptables = "iptables -A " + vmchain + " -j DROP" + execute(iptables) if write_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) == False: return 'false' @@ -704,6 +740,7 @@ if __name__ == '__main__': parser.add_option("--vmid", dest="vmID") parser.add_option("--vmmac", dest="vmMAC") parser.add_option("--vif", dest="vif") + parser.add_option("--ruletype", dest="ruletype") parser.add_option("--sig", dest="sig") parser.add_option("--seq", dest="seq") parser.add_option("--rules", dest="rules") @@ -724,7 +761,7 @@ if __name__ == '__main__': elif cmd == "get_rule_logs_for_vms": get_rule_logs_for_vms() elif cmd == "add_network_rules": - add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname) + add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname,option.ruletype) elif cmd == "cleanup_rules": cleanup_rules() elif cmd == "post_default_network_rules": diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index f202d6d8053..9cc09276306 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -45,7 +45,6 @@ import com.cloud.api.response.CreateCmdResponse; import com.cloud.api.response.DiskOfferingResponse; import com.cloud.api.response.DomainResponse; import com.cloud.api.response.DomainRouterResponse; -import com.cloud.api.response.EgressRuleResponse; import com.cloud.api.response.EventResponse; import com.cloud.api.response.ExtractResponse; import com.cloud.api.response.FirewallResponse; @@ -53,8 +52,8 @@ import com.cloud.api.response.FirewallRuleResponse; import com.cloud.api.response.HostResponse; import com.cloud.api.response.HypervisorCapabilitiesResponse; import com.cloud.api.response.IPAddressResponse; -import com.cloud.api.response.IngressRuleResponse; -import com.cloud.api.response.IngressRuleResultObject; +import com.cloud.api.response.SecurityGroupResponse; +import com.cloud.api.response.SecurityGroupResultObject; import com.cloud.api.response.InstanceGroupResponse; import com.cloud.api.response.IpForwardingRuleResponse; import com.cloud.api.response.ListResponse; @@ -133,8 +132,8 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.security.EgressRule; -import com.cloud.network.security.IngressRule; +import com.cloud.network.security.SecurityRule; +import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupRules; import com.cloud.offering.DiskOffering; @@ -186,6 +185,8 @@ import com.cloud.vm.VmStats; import com.cloud.vm.dao.UserVmData; import com.cloud.vm.dao.UserVmData.NicData; import com.cloud.vm.dao.UserVmData.SecurityGroupData; +import com.cloud.api.response.SecurityGroupRuleResponse; +import com.cloud.api.response.SecurityGroupRuleResultObject; public class ApiResponseHelper implements ResponseGenerator { @@ -1775,8 +1776,10 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public ListResponse createSecurityGroupResponses(List networkGroups) { - List groupResultObjs = SecurityGroupResultObject.transposeNetworkGroups(networkGroups); + public ListResponse createSecurityGroupResponses( + List networkGroups) { + List groupResultObjs = SecurityGroupResultObject + .transposeNetworkGroups(networkGroups); ListResponse response = new ListResponse(); List netGrpResponses = new ArrayList(); @@ -1785,37 +1788,49 @@ public class ApiResponseHelper implements ResponseGenerator { netGrpResponse.setId(networkGroup.getId()); netGrpResponse.setName(networkGroup.getName()); netGrpResponse.setDescription(networkGroup.getDescription()); - + populateOwner(netGrpResponse, networkGroup); - List ingressRules = networkGroup.getIngressRules(); - if ((ingressRules != null) && !ingressRules.isEmpty()) { - List ingressRulesResponse = new ArrayList(); + List securityGroupRules = networkGroup + .getSecurityGroupRules(); + if ((securityGroupRules != null) && !securityGroupRules.isEmpty()) { + List ingressRulesResponse = new ArrayList(); + List egressRulesResponse = new ArrayList(); + for (SecurityGroupRuleResultObject securityGroupRule : securityGroupRules) { + SecurityGroupRuleResponse ruleData = new SecurityGroupRuleResponse(); + ruleData.setRuleId(securityGroupRule.getId()); + ruleData.setProtocol(securityGroupRule.getProtocol()); - for (IngressRuleResultObject ingressRule : ingressRules) { - IngressRuleResponse ingressData = new IngressRuleResponse(); - - ingressData.setRuleId(ingressRule.getId()); - ingressData.setProtocol(ingressRule.getProtocol()); - if ("icmp".equalsIgnoreCase(ingressRule.getProtocol())) { - ingressData.setIcmpType(ingressRule.getStartPort()); - ingressData.setIcmpCode(ingressRule.getEndPort()); + if ("icmp" + .equalsIgnoreCase(securityGroupRule.getProtocol())) { + ruleData.setIcmpType(securityGroupRule.getStartPort()); + ruleData.setIcmpCode(securityGroupRule.getEndPort()); } else { - ingressData.setStartPort(ingressRule.getStartPort()); - ingressData.setEndPort(ingressRule.getEndPort()); + ruleData.setStartPort(securityGroupRule.getStartPort()); + ruleData.setEndPort(securityGroupRule.getEndPort()); } - if (ingressRule.getAllowedSecurityGroup() != null) { - ingressData.setSecurityGroupName(ingressRule.getAllowedSecurityGroup()); - ingressData.setAccountName(ingressRule.getAllowedSecGroupAcct()); + if (securityGroupRule.getAllowedSecurityGroup() != null) { + ruleData.setSecurityGroupName(securityGroupRule + .getAllowedSecurityGroup()); + ruleData.setAccountName(securityGroupRule + .getAllowedSecGroupAcct()); } else { - ingressData.setCidr(ingressRule.getAllowedSourceIpCidr()); + ruleData.setCidr(securityGroupRule + .getAllowedSourceIpCidr()); } - ingressData.setObjectName("ingressrule"); - ingressRulesResponse.add(ingressData); + if (securityGroupRule.getRuleType() == SecurityRuleType.IngressRule) { + ruleData.setObjectName("ingressrule"); + ingressRulesResponse.add(ruleData); + } else { + ruleData.setObjectName("egressrule"); + egressRulesResponse.add(ruleData); + } } - netGrpResponse.setIngressRules(ingressRulesResponse); + netGrpResponse + .setSecurityGroupIngressRules(ingressRulesResponse); + netGrpResponse.setSecurityGroupEgressRules(egressRulesResponse); } netGrpResponse.setObjectName("securitygroup"); netGrpResponses.add(netGrpResponse); @@ -2184,14 +2199,14 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public SecurityGroupResponse createSecurityGroupResponseFromIngressRule(List ingressRules) { + public SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List securityRules) { SecurityGroupResponse response = new SecurityGroupResponse(); Map securiytGroupAccounts = new HashMap(); Map allowedSecurityGroups = new HashMap(); Map allowedSecuriytGroupAccounts = new HashMap(); - if ((ingressRules != null) && !ingressRules.isEmpty()) { - SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(ingressRules.get(0).getSecurityGroupId()); + if ((securityRules != null) && !securityRules.isEmpty()) { + SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(securityRules.get(0).getSecurityGroupId()); response.setId(securityGroup.getId()); response.setName(securityGroup.getName()); response.setDescription(securityGroup.getDescription()); @@ -2206,21 +2221,22 @@ public class ApiResponseHelper implements ResponseGenerator { populateAccount(response, account.getId()); populateDomain(response, account.getDomainId()); - List responses = new ArrayList(); - for (IngressRule ingressRule : ingressRules) { - IngressRuleResponse ingressData = new IngressRuleResponse(); + List egressResponses = new ArrayList(); + List ingressResponses = new ArrayList(); + for (SecurityRule securityRule : securityRules) { + SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse(); - ingressData.setRuleId(ingressRule.getId()); - ingressData.setProtocol(ingressRule.getProtocol()); - if ("icmp".equalsIgnoreCase(ingressRule.getProtocol())) { - ingressData.setIcmpType(ingressRule.getStartPort()); - ingressData.setIcmpCode(ingressRule.getEndPort()); + securityGroupData.setRuleId(securityRule.getId()); + securityGroupData.setProtocol(securityRule.getProtocol()); + if ("icmp".equalsIgnoreCase(securityRule.getProtocol())) { + securityGroupData.setIcmpType(securityRule.getStartPort()); + securityGroupData.setIcmpCode(securityRule.getEndPort()); } else { - ingressData.setStartPort(ingressRule.getStartPort()); - ingressData.setEndPort(ingressRule.getEndPort()); + securityGroupData.setStartPort(securityRule.getStartPort()); + securityGroupData.setEndPort(securityRule.getEndPort()); } - Long allowedSecurityGroupId = ingressRule.getAllowedNetworkId(); + Long allowedSecurityGroupId = securityRule.getAllowedNetworkId(); if (allowedSecurityGroupId != null) { SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId); if (allowedSecurityGroup == null) { @@ -2228,7 +2244,7 @@ public class ApiResponseHelper implements ResponseGenerator { allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup); } - ingressData.setSecurityGroupName(allowedSecurityGroup.getName()); + securityGroupData.setSecurityGroupName(allowedSecurityGroup.getName()); Account allowedAccount = allowedSecuriytGroupAccounts.get(allowedSecurityGroup.getAccountId()); if (allowedAccount == null) { @@ -2236,90 +2252,27 @@ public class ApiResponseHelper implements ResponseGenerator { allowedSecuriytGroupAccounts.put(allowedAccount.getId(), allowedAccount); } - ingressData.setAccountName(allowedAccount.getAccountName()); + securityGroupData.setAccountName(allowedAccount.getAccountName()); } else { - ingressData.setCidr(ingressRule.getAllowedSourceIpCidr()); + securityGroupData.setCidr(securityRule.getAllowedSourceIpCidr()); + } + if (securityRule.getRuleType() == SecurityRuleType.IngressRule) { + securityGroupData.setObjectName("ingressrule"); + ingressResponses.add(securityGroupData); + } else { + securityGroupData.setObjectName("egressrule"); + egressResponses.add(securityGroupData); } - ingressData.setObjectName("ingressrule"); - responses.add(ingressData); } - response.setIngressRules(responses); + response.setSecurityGroupIngressRules(ingressResponses); + response.setSecurityGroupEgressRules(egressResponses); response.setObjectName("securitygroup"); } return response; } - - @Override - public SecurityGroupResponse createSecurityGroupResponseFromEgressRule(List egressRules) { - SecurityGroupResponse response = new SecurityGroupResponse(); - Map securiytGroupAccounts = new HashMap(); - Map allowedSecurityGroups = new HashMap(); - Map allowedSecuriytGroupAccounts = new HashMap(); - - if ((egressRules != null) && !egressRules.isEmpty()) { - SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(egressRules.get(0).getSecurityGroupId()); - response.setId(securityGroup.getId()); - response.setName(securityGroup.getName()); - response.setDescription(securityGroup.getDescription()); - - Account account = securiytGroupAccounts.get(securityGroup.getAccountId()); - - if (account == null) { - account = ApiDBUtils.findAccountById(securityGroup.getAccountId()); - securiytGroupAccounts.put(securityGroup.getAccountId(), account); - } - - populateAccount(response, account.getId()); - populateDomain(response, account.getDomainId()); - - - List responses = new ArrayList(); - for (EgressRule egressRule : egressRules) { - EgressRuleResponse egressData = new EgressRuleResponse(); - - egressData.setRuleId(egressRule.getId()); - egressData.setProtocol(egressRule.getProtocol()); - if ("icmp".equalsIgnoreCase(egressRule.getProtocol())) { - egressData.setIcmpType(egressRule.getStartPort()); - egressData.setIcmpCode(egressRule.getEndPort()); - } else { - egressData.setStartPort(egressRule.getStartPort()); - egressData.setEndPort(egressRule.getEndPort()); - } - - Long allowedSecurityGroupId = egressRule.getAllowedNetworkId(); - if (allowedSecurityGroupId != null) { - SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId); - if (allowedSecurityGroup == null) { - allowedSecurityGroup = ApiDBUtils.findSecurityGroupById(allowedSecurityGroupId); - allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup); - } - - egressData.setSecurityGroupName(allowedSecurityGroup.getName()); - - Account allowedAccount = allowedSecuriytGroupAccounts.get(allowedSecurityGroup.getAccountId()); - if (allowedAccount == null) { - allowedAccount = ApiDBUtils.findAccountById(allowedSecurityGroup.getAccountId()); - allowedSecuriytGroupAccounts.put(allowedAccount.getId(), allowedAccount); - } - - egressData.setAccountName(allowedAccount.getAccountName()); - } else { - egressData.setCidr(egressRule.getAllowedDestinationIpCidr()); - } - - egressData.setObjectName("egressrule"); - responses.add(egressData); - } - response.setEgressRules(responses); - response.setObjectName("securitygroup"); - - } - return response; - } - + @Override public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering offering) { NetworkOfferingResponse response = new NetworkOfferingResponse(); @@ -2855,3 +2808,4 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } } + diff --git a/server/src/com/cloud/api/response/EgressRuleResultObject.java b/server/src/com/cloud/api/response/EgressRuleResultObject.java deleted file mode 100644 index 85313c7cad2..00000000000 --- a/server/src/com/cloud/api/response/EgressRuleResultObject.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package com.cloud.api.response; - -import com.cloud.serializer.Param; - -public class EgressRuleResultObject { - @Param(name="id") - private Long id; - - @Param(name="startport") - private int startPort; - - @Param(name="endport") - private int endPort; - - @Param(name="protocol") - private String protocol; - - @Param(name="securitygroup") - private String allowedSecurityGroup = null; - - @Param(name="account") - private String allowedSecGroupAcct = null; - - @Param(name="cidr") - private String allowedDestinationIpCidr = null; - - public EgressRuleResultObject() { } - - public EgressRuleResultObject(Long id, int startPort, int endPort, String protocol, String allowedSecurityGroup, String allowedSecGroupAcct, String allowedSourceIpCidr) { - this.id = id; - this.startPort = startPort; - this.endPort = endPort; - this.protocol = protocol; - this.allowedSecurityGroup = allowedSecurityGroup; - this.allowedSecGroupAcct = allowedSecGroupAcct; - this.allowedDestinationIpCidr = allowedSourceIpCidr; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public int getStartPort() { - return startPort; - } - - public void setStartPort(int startPort) { - this.startPort = startPort; - } - - public int getEndPort() { - return endPort; - } - - public void setEndPort(int endPort) { - this.endPort = endPort; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getAllowedSecurityGroup() { - return allowedSecurityGroup; - } - - public void setAllowedSecurityGroup(String allowedSecurityGroup) { - this.allowedSecurityGroup = allowedSecurityGroup; - } - - public String getAllowedSecGroupAcct() { - return allowedSecGroupAcct; - } - - public void setAllowedSecGroupAcct(String allowedSecGroupAcct) { - this.allowedSecGroupAcct = allowedSecGroupAcct; - } - - public String getAllowedDestinationIpCidr() { - return allowedDestinationIpCidr; - } - - public void setAllowedDestinationIpCidr(String allowedDestinationIpCidr) { - this.allowedDestinationIpCidr = allowedDestinationIpCidr; - } -} diff --git a/server/src/com/cloud/api/response/SecurityGroupResultObject.java b/server/src/com/cloud/api/response/SecurityGroupResultObject.java index 454f8a2ffc2..4b3b44d61a1 100644 --- a/server/src/com/cloud/api/response/SecurityGroupResultObject.java +++ b/server/src/com/cloud/api/response/SecurityGroupResultObject.java @@ -49,20 +49,20 @@ public class SecurityGroupResultObject implements ControlledEntity{ @Param(name = "accountname") private String accountName = null; - @Param(name = "ingressrules") - private List ingressRules = null; + @Param(name = "securitygrouprules") + private List securityGroupRules = null; public SecurityGroupResultObject() { } - public SecurityGroupResultObject(Long id, String name, String description, long domainId, long accountId, String accountName, List ingressRules) { + public SecurityGroupResultObject(Long id, String name, String description, long domainId, long accountId, String accountName, List ingressRules) { this.id = id; this.name = name; this.description = description; this.domainId = domainId; this.accountId = accountId; this.accountName = accountName; - this.ingressRules = ingressRules; + this.securityGroupRules = ingressRules; } public Long getId() { @@ -113,21 +113,22 @@ public class SecurityGroupResultObject implements ControlledEntity{ this.accountName = accountName; } - public List getIngressRules() { - return ingressRules; + public List getSecurityGroupRules() { + return securityGroupRules; } - public void setIngressRules(List ingressRules) { - this.ingressRules = ingressRules; + public void setSecurityGroupRules(List securityGroupRules) { + this.securityGroupRules = securityGroupRules; } - public static List transposeNetworkGroups(List groups) { + public static List transposeNetworkGroups( + List groups) { List resultObjects = new ArrayList(); Map allowedSecurityGroups = new HashMap(); Map accounts = new HashMap(); if ((groups != null) && !groups.isEmpty()) { - List ingressDataList = new ArrayList(); + List securityGroupRuleDataList = new ArrayList(); SecurityGroupResultObject currentGroup = null; List processedGroups = new ArrayList(); @@ -137,9 +138,10 @@ public class SecurityGroupResultObject implements ControlledEntity{ processedGroups.add(groupId); if (currentGroup != null) { - if (!ingressDataList.isEmpty()) { - currentGroup.setIngressRules(ingressDataList); - ingressDataList = new ArrayList(); + if (!securityGroupRuleDataList.isEmpty()) { + currentGroup + .setSecurityGroupRules(securityGroupRuleDataList); + securityGroupRuleDataList = new ArrayList(); } resultObjects.add(currentGroup); } @@ -153,7 +155,8 @@ public class SecurityGroupResultObject implements ControlledEntity{ Account account = accounts.get(netGroupRule.getAccountId()); if (account == null) { - account = ApiDBUtils.findAccountById(netGroupRule.getAccountId()); + account = ApiDBUtils.findAccountById(netGroupRule + .getAccountId()); accounts.put(account.getId(), account); } @@ -164,41 +167,60 @@ public class SecurityGroupResultObject implements ControlledEntity{ } if (netGroupRule.getRuleId() != null) { - // there's at least one ingress rule for this network group, add the ingress rule data - IngressRuleResultObject ingressData = new IngressRuleResultObject(); - ingressData.setEndPort(netGroupRule.getEndPort()); - ingressData.setStartPort(netGroupRule.getStartPort()); - ingressData.setId(netGroupRule.getRuleId()); - ingressData.setProtocol(netGroupRule.getProtocol()); + // there's at least one securitygroup rule for this network + // group, add the securitygroup rule data + SecurityGroupRuleResultObject securityGroupRuleData = new SecurityGroupRuleResultObject(); + securityGroupRuleData.setEndPort(netGroupRule.getEndPort()); + securityGroupRuleData.setStartPort(netGroupRule + .getStartPort()); + securityGroupRuleData.setId(netGroupRule.getRuleId()); + securityGroupRuleData.setProtocol(netGroupRule + .getProtocol()); + securityGroupRuleData.setRuleType(netGroupRule + .getRuleType()); - Long allowedSecurityGroupId = netGroupRule.getAllowedNetworkId(); + Long allowedSecurityGroupId = netGroupRule + .getAllowedNetworkId(); if (allowedSecurityGroupId != null) { - SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId); + SecurityGroup allowedSecurityGroup = allowedSecurityGroups + .get(allowedSecurityGroupId); if (allowedSecurityGroup == null) { - allowedSecurityGroup = ApiDBUtils.findSecurityGroupById(allowedSecurityGroupId); - allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup); + allowedSecurityGroup = ApiDBUtils + .findSecurityGroupById(allowedSecurityGroupId); + allowedSecurityGroups.put(allowedSecurityGroupId, + allowedSecurityGroup); } - ingressData.setAllowedSecurityGroup(allowedSecurityGroup.getName()); + securityGroupRuleData + .setAllowedSecurityGroup(allowedSecurityGroup + .getName()); - Account allowedAccount = accounts.get(allowedSecurityGroup.getAccountId()); + Account allowedAccount = accounts + .get(allowedSecurityGroup.getAccountId()); if (allowedAccount == null) { - allowedAccount = ApiDBUtils.findAccountById(allowedSecurityGroup.getAccountId()); + allowedAccount = ApiDBUtils + .findAccountById(allowedSecurityGroup + .getAccountId()); accounts.put(allowedAccount.getId(), allowedAccount); } - ingressData.setAllowedSecGroupAcct(allowedAccount.getAccountName()); + securityGroupRuleData + .setAllowedSecGroupAcct(allowedAccount + .getAccountName()); } else if (netGroupRule.getAllowedSourceIpCidr() != null) { - ingressData.setAllowedSourceIpCidr(netGroupRule.getAllowedSourceIpCidr()); + securityGroupRuleData + .setAllowedSourceIpCidr(netGroupRule + .getAllowedSourceIpCidr()); } - ingressDataList.add(ingressData); + securityGroupRuleDataList.add(securityGroupRuleData); } } // all rules have been processed, add the final data into the list if (currentGroup != null) { - if (!ingressDataList.isEmpty()) { - currentGroup.setIngressRules(ingressDataList); + if (!securityGroupRuleDataList.isEmpty()) { + currentGroup + .setSecurityGroupRules(securityGroupRuleDataList); } resultObjects.add(currentGroup); } diff --git a/server/src/com/cloud/api/response/IngressRuleResultObject.java b/server/src/com/cloud/api/response/SecurityGroupRuleResultObject.java similarity index 81% rename from server/src/com/cloud/api/response/IngressRuleResultObject.java rename to server/src/com/cloud/api/response/SecurityGroupRuleResultObject.java index 12d2c054b8d..022e02fe707 100644 --- a/server/src/com/cloud/api/response/IngressRuleResultObject.java +++ b/server/src/com/cloud/api/response/SecurityGroupRuleResultObject.java @@ -17,10 +17,11 @@ */ package com.cloud.api.response; - + +import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.serializer.Param; -public class IngressRuleResultObject { +public class SecurityGroupRuleResultObject { @Param(name="id") private Long id; @@ -40,11 +41,13 @@ public class IngressRuleResultObject { private String allowedSecGroupAcct = null; @Param(name="cidr") - private String allowedSourceIpCidr = null; + private String allowedSourceIpCidr = null; + + private SecurityRuleType type; - public IngressRuleResultObject() { } + public SecurityGroupRuleResultObject() { } - public IngressRuleResultObject(Long id, int startPort, int endPort, String protocol, String allowedSecurityGroup, String allowedSecGroupAcct, String allowedSourceIpCidr) { + public SecurityGroupRuleResultObject(Long id, int startPort, int endPort, String protocol, String allowedSecurityGroup, String allowedSecGroupAcct, String allowedSourceIpCidr) { this.id = id; this.startPort = startPort; this.endPort = endPort; @@ -65,7 +68,16 @@ public class IngressRuleResultObject { public int getStartPort() { return startPort; } - + + public void setRuleType(SecurityRuleType type) { + this.type = type; + } + + + public SecurityRuleType getRuleType() { + return type; + } + public void setStartPort(int startPort) { this.startPort = startPort; } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index a25f9230141..a55a4542824 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -113,7 +113,7 @@ import com.cloud.network.router.VirtualNetworkApplianceManagerImpl; import com.cloud.network.rules.RulesManagerImpl; import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl; import com.cloud.network.security.SecurityGroupManagerImpl2; -import com.cloud.network.security.dao.IngressRuleDaoImpl; +import com.cloud.network.security.dao.SecurityGroupRuleDaoImpl; import com.cloud.network.security.dao.SecurityGroupDaoImpl; import com.cloud.network.security.dao.SecurityGroupRulesDaoImpl; import com.cloud.network.security.dao.SecurityGroupVMMapDaoImpl; @@ -225,7 +225,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com addDao("LoadBalancerVMMapDao", LoadBalancerVMMapDaoImpl.class); addDao("DataCenterIpAddressDao", DataCenterIpAddressDaoImpl.class); addDao("SecurityGroupDao", SecurityGroupDaoImpl.class); - addDao("IngressRuleDao", IngressRuleDaoImpl.class); + addDao("SecurityGroupRuleDao", SecurityGroupRuleDaoImpl.class); addDao("SecurityGroupVMMapDao", SecurityGroupVMMapDaoImpl.class); addDao("SecurityGroupRulesDao", SecurityGroupRulesDaoImpl.class); addDao("SecurityGroupWorkDao", SecurityGroupWorkDaoImpl.class); diff --git a/server/src/com/cloud/network/security/SecurityGroupListener.java b/server/src/com/cloud/network/security/SecurityGroupListener.java index 9742bbe03b6..e29f5be84bf 100755 --- a/server/src/com/cloud/network/security/SecurityGroupListener.java +++ b/server/src/com/cloud/network/security/SecurityGroupListener.java @@ -33,10 +33,10 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; -import com.cloud.agent.api.SecurityIngressRuleAnswer; +import com.cloud.agent.api.SecurityGroupRuleAnswer; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; -import com.cloud.agent.api.SecurityIngressRuleAnswer.FailureReason; +import com.cloud.agent.api.SecurityGroupRuleAnswer.FailureReason; import com.cloud.agent.manager.Commands; import com.cloud.exception.AgentUnavailableException; import com.cloud.host.HostVO; @@ -89,8 +89,8 @@ public class SecurityGroupListener implements Listener { List affectedVms = new ArrayList(); int commandNum = 0; for (Answer ans: answers) { - if (ans instanceof SecurityIngressRuleAnswer) { - SecurityIngressRuleAnswer ruleAnswer = (SecurityIngressRuleAnswer) ans; + if (ans instanceof SecurityGroupRuleAnswer) { + SecurityGroupRuleAnswer ruleAnswer = (SecurityGroupRuleAnswer) ans; if (ans.getResult()) { s_logger.debug("Successfully programmed rule " + ruleAnswer.toString() + " into host " + agentId); _workDao.updateStep(ruleAnswer.getVmId(), ruleAnswer.getLogSequenceNumber(), Step.Done); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 688d09918d5..28928e11b25 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -42,14 +42,16 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.NetworkRulesSystemVmCommand; -import com.cloud.agent.api.SecurityIngressRulesCmd; -import com.cloud.agent.api.SecurityIngressRulesCmd.IpPortAndProto; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto; import com.cloud.agent.manager.Commands; import com.cloud.api.commands.AuthorizeSecurityGroupIngressCmd; +import com.cloud.api.commands.AuthorizeSecurityGroupEgressCmd; import com.cloud.api.commands.CreateSecurityGroupCmd; import com.cloud.api.commands.DeleteSecurityGroupCmd; import com.cloud.api.commands.ListSecurityGroupsCmd; import com.cloud.api.commands.RevokeSecurityGroupIngressCmd; +import com.cloud.api.commands.RevokeSecurityGroupEgressCmd; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.domain.Domain; @@ -67,7 +69,7 @@ import com.cloud.network.Network; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; import com.cloud.network.security.SecurityGroupWork.Step; -import com.cloud.network.security.dao.IngressRuleDao; +import com.cloud.network.security.dao.SecurityGroupRuleDao; import com.cloud.network.security.dao.SecurityGroupDao; import com.cloud.network.security.dao.SecurityGroupRulesDao; import com.cloud.network.security.dao.SecurityGroupVMMapDao; @@ -109,6 +111,7 @@ import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.network.security.SecurityRule.SecurityRuleType; import edu.emory.mathcs.backport.java.util.Collections; @@ -119,7 +122,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Inject SecurityGroupDao _securityGroupDao; @Inject - IngressRuleDao _ingressRuleDao; + SecurityGroupRuleDao _securityGroupRuleDao; @Inject SecurityGroupVMMapDao _securityGroupVMMapDao; @Inject @@ -328,14 +331,14 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } - protected Map> generateRulesForVM(Long userVmId) { + protected Map> generateRulesForVM(Long userVmId, SecurityRuleType type) { Map> allowed = new TreeMap>(); List groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVmId); for (SecurityGroupVMMapVO mapVO : groupsForVm) { - List rules = _ingressRuleDao.listBySecurityGroupId(mapVO.getSecurityGroupId()); - for (IngressRuleVO rule : rules) { + List rules = _securityGroupRuleDao.listBySecurityGroupId(mapVO.getSecurityGroupId(), type); + for (SecurityGroupRuleVO rule : rules) { PortAndProto portAndProto = new PortAndProto(rule.getProtocol(), rule.getStartPort(), rule.getEndPort()); Set cidrs = allowed.get(portAndProto); if (cidrs == null) { @@ -448,9 +451,9 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG List groupsForVm = _securityGroupVMMapDao.listByInstanceId(vm.getId()); // For each group, find the ingress rules that allow the group for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao - List allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); + List allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); // For each ingress rule that allows a group that the vm belongs to, find the group it belongs to - affectedVms.addAll(getAffectedVmsForIngressRules(allowingRules)); + affectedVms.addAll(getAffectedVmsForSecurityRules(allowingRules)); } return affectedVms; } @@ -460,18 +463,18 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG List groupsForVm = _securityGroupVMMapDao.listByInstanceId(vm.getId()); // For each group, find the ingress rules that allow the group for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao - List allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); + List allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); // For each ingress rule that allows a group that the vm belongs to, find the group it belongs to - affectedVms.addAll(getAffectedVmsForIngressRules(allowingRules)); + affectedVms.addAll(getAffectedVmsForSecurityRules(allowingRules)); } return affectedVms; } - protected List getAffectedVmsForIngressRules(List allowingRules) { + protected List getAffectedVmsForSecurityRules(List allowingRules) { Set distinctGroups = new HashSet(); List affectedVms = new ArrayList(); - for (IngressRuleVO allowingRule : allowingRules) { + for (SecurityGroupRuleVO allowingRule : allowingRules) { distinctGroups.add(allowingRule.getSecurityGroupId()); } for (Long groupId : distinctGroups) { @@ -481,16 +484,16 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return affectedVms; } - protected SecurityIngressRulesCmd generateRulesetCmd(String vmName, String guestIp, String guestMac, Long vmId, String signature, long seqnum, Map> rules) { + protected SecurityGroupRulesCmd generateRulesetCmd(SecurityRuleType ruleType, String vmName, String guestIp, String guestMac, Long vmId, String signature, long seqnum, Map> rules) { List result = new ArrayList(); for (PortAndProto pAp : rules.keySet()) { Set cidrs = rules.get(pAp); if (cidrs.size() > 0) { - IpPortAndProto ipPortAndProto = new SecurityIngressRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs.size()])); + IpPortAndProto ipPortAndProto = new SecurityGroupRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs.size()])); result.add(ipPortAndProto); } } - return new SecurityIngressRulesCmd(guestIp, guestMac, vmName, vmId, signature, seqnum, result.toArray(new IpPortAndProto[result.size()])); + return new SecurityGroupRulesCmd(ruleType,guestIp, guestMac, vmName, vmId, signature, seqnum, result.toArray(new IpPortAndProto[result.size()])); } protected void handleVmStopped(VMInstanceVO vm) { @@ -521,11 +524,11 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG scheduleRulesetUpdateToHosts(affectedVms, true, null); } } - @Override @DB @SuppressWarnings("rawtypes") - public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd) { + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS, eventDescription = "Adding Egress Rule ", async = true) + public List authorizeSecurityGroupEgress(AuthorizeSecurityGroupEgressCmd cmd) { Long securityGroupId = cmd.getSecurityGroupId(); String protocol = cmd.getProtocol(); Integer startPort = cmd.getStartPort(); @@ -534,10 +537,30 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG Integer icmpCode = cmd.getIcmpCode(); List cidrList = cmd.getCidrList(); Map groupList = cmd.getUserSecurityGroupList(); + return authorizeSecurityGroupRule(securityGroupId,protocol,startPort,endPort,icmpType,icmpCode,cidrList,groupList,SecurityRuleType.EgressRule); + } + + @Override + @DB + @SuppressWarnings("rawtypes") + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS, eventDescription = "Adding Ingress Rule ", async = true) + public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd) { + Long securityGroupId = cmd.getSecurityGroupId(); + String protocol = cmd.getProtocol(); + Integer startPort = cmd.getStartPort(); + Integer endPort = cmd.getEndPort(); + Integer icmpType = cmd.getIcmpType(); + Integer icmpCode = cmd.getIcmpCode(); + List cidrList = cmd.getCidrList(); + Map groupList = cmd.getUserSecurityGroupList(); + return authorizeSecurityGroupRule(securityGroupId,protocol,startPort,endPort,icmpType,icmpCode,cidrList,groupList,SecurityRuleType.IngressRule); + } + + private List authorizeSecurityGroupRule(Long securityGroupId,String protocol,Integer startPort,Integer endPort,Integer icmpType,Integer icmpCode,List cidrList,Map groupList,SecurityRuleType ruleType) { Integer startPortOrType = null; Integer endPortOrCode = null; - - // Validate parameters + + // Validate parameters SecurityGroup securityGroup = _securityGroupDao.findById(securityGroupId); if (securityGroup == null) { throw new InvalidParameterValueException("Unable to find security group by id " + securityGroupId); @@ -622,13 +645,13 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG Account authorizedAccount = _accountDao.findActiveAccount(authorizedAccountName, domainId); if (authorizedAccount == null) { - throw new InvalidParameterValueException("Nonexistent account: " + authorizedAccountName + " when trying to authorize ingress for " + securityGroupId + ":" + protocol + ":" + throw new InvalidParameterValueException("Nonexistent account: " + authorizedAccountName + " when trying to authorize security group rule for " + securityGroupId + ":" + protocol + ":" + startPortOrType + ":" + endPortOrCode); } SecurityGroupVO groupVO = _securityGroupDao.findByAccountAndName(authorizedAccount.getId(), group); if (groupVO == null) { - throw new InvalidParameterValueException("Nonexistent group " + group + " for account " + authorizedAccountName + "/" + domainId + " is given, unable to authorize ingress."); + throw new InvalidParameterValueException("Nonexistent group " + group + " for account " + authorizedAccountName + "/" + domainId + " is given, unable to authorize security group rule."); } // Check permissions @@ -652,7 +675,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG s_logger.warn("Could not acquire lock on network security group: id= " + securityGroupId); return null; } - List newRules = new ArrayList(); + List newRules = new ArrayList(); try { for (final SecurityGroupVO ngVO : authorizedGroups2) { final Long ngId = ngVO.getId(); @@ -665,23 +688,23 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return null; } } - IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocol, startPortOrType, endPortOrCode, ngVO.getId()); - if (ingressRule != null) { + SecurityGroupRuleVO securityGroupRule = _securityGroupRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocol, startPortOrType, endPortOrCode, ngVO.getId()); + if ((securityGroupRule != null) && (securityGroupRule.getRuleType() == ruleType)) { continue; // rule already exists. } - ingressRule = new IngressRuleVO(securityGroup.getId(), startPortOrType, endPortOrCode, protocol, ngVO.getId()); - ingressRule = _ingressRuleDao.persist(ingressRule); - newRules.add(ingressRule); + securityGroupRule = new SecurityGroupRuleVO(ruleType,securityGroup.getId(), startPortOrType, endPortOrCode, protocol, ngVO.getId()); + securityGroupRule = _securityGroupRuleDao.persist(securityGroupRule); + newRules.add(securityGroupRule); } if (cidrList != null) { for (String cidr : cidrList) { - IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndCidr(securityGroup.getId(), protocol, startPortOrType, endPortOrCode, cidr); - if (ingressRule != null) { + SecurityGroupRuleVO securityGroupRule = _securityGroupRuleDao.findByProtoPortsAndCidr(securityGroup.getId(), protocol, startPortOrType, endPortOrCode, cidr); + if ((securityGroupRule != null) && (securityGroupRule.getRuleType() == ruleType)) { continue; } - ingressRule = new IngressRuleVO(securityGroup.getId(), startPortOrType, endPortOrCode, protocol, cidr); - ingressRule = _ingressRuleDao.persist(ingressRule); - newRules.add(ingressRule); + securityGroupRule = new SecurityGroupRuleVO(ruleType,securityGroup.getId(), startPortOrType, endPortOrCode, protocol, cidr); + securityGroupRule = _securityGroupRuleDao.persist(securityGroupRule); + newRules.add(securityGroupRule); } } if (s_logger.isDebugEnabled()) { @@ -693,28 +716,48 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG scheduleRulesetUpdateToHosts(affectedVms, true, null); return newRules; } catch (Exception e) { - s_logger.warn("Exception caught when adding ingress rules ", e); - throw new CloudRuntimeException("Exception caught when adding ingress rules", e); + s_logger.warn("Exception caught when adding security group rules ", e); + throw new CloudRuntimeException("Exception caught when adding security group rules", e); } finally { if (securityGroup != null) { _securityGroupDao.releaseFromLockTable(securityGroup.getId()); } } } - + @Override @DB + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_REVOKE_EGRESS, eventDescription = "Revoking Egress Rule ", async = true) + public boolean revokeSecurityGroupEgress(RevokeSecurityGroupEgressCmd cmd) { + Long id = cmd.getId(); + return revokeSecurityGroupRule(id, SecurityRuleType.EgressRule); + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_REVOKE_INGRESS, eventDescription = "Revoking Ingress Rule ", async = true) public boolean revokeSecurityGroupIngress(RevokeSecurityGroupIngressCmd cmd) { + + Long id = cmd.getId(); + return revokeSecurityGroupRule(id, SecurityRuleType.IngressRule); + } + + private boolean revokeSecurityGroupRule(Long id, SecurityRuleType type) { // input validation Account caller = UserContext.current().getCaller(); - Long id = cmd.getId(); - - IngressRuleVO rule = _ingressRuleDao.findById(id); + + SecurityGroupRuleVO rule = _securityGroupRuleDao.findById(id); if (rule == null) { - s_logger.debug("Unable to find ingress rule with id " + id); - throw new InvalidParameterValueException("Unable to find ingress rule with id " + id); + s_logger.debug("Unable to find security rule with id " + id); + throw new InvalidParameterValueException("Unable to find security rule with id " + id); } + // check type + if (type != rule.getRuleType()) { + s_logger.debug("Mismatch in rule type for security rule with id " + id ); + throw new InvalidParameterValueException("Mismatch in rule type for security rule with id " + id); + } + // Check permissions SecurityGroup securityGroup = _securityGroupDao.findById(rule.getSecurityGroupId()); _accountMgr.checkAccess(caller, null, securityGroup); @@ -731,8 +774,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return false; } - _ingressRuleDao.remove(id); - s_logger.debug("revokeSecurityGroupIngress succeeded for ingress rule id: " + id); + _securityGroupRuleDao.remove(id); + s_logger.debug("revokeSecurityGroupIngress succeeded for security rule id: " + id); final ArrayList affectedVms = new ArrayList(); affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(groupHandle.getId())); @@ -740,8 +783,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return true; } catch (Exception e) { - s_logger.warn("Exception caught when deleting ingress rules ", e); - throw new CloudRuntimeException("Exception caught when deleting ingress rules", e); + s_logger.warn("Exception caught when deleting security rules ", e); + throw new CloudRuntimeException("Exception caught when deleting security rules", e); } finally { if (groupHandle != null) { _securityGroupDao.releaseFromLockTable(groupHandle.getId()); @@ -885,16 +928,26 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG seqnum = log.getLogsequence(); if (vm != null && vm.getState() == State.Running) { - Map> rules = generateRulesForVM(userVmId); + Map> rules = generateRulesForVM(userVmId, SecurityRuleType.IngressRule); agentId = vm.getHostId(); if (agentId != null) { - SecurityIngressRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), generateRulesetSignature(rules), seqnum, + SecurityGroupRulesCmd cmd = generateRulesetCmd(SecurityRuleType.IngressRule, vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), generateRulesetSignature(rules), seqnum, rules); Commands cmds = new Commands(cmd); try { _agentMgr.send(agentId, cmds, _answerListener); } catch (AgentUnavailableException e) { - s_logger.debug("Unable to send updates for vm: " + userVmId + "(agentid=" + agentId + ")"); + s_logger.debug("Unable to send ingress rules updates for vm: " + userVmId + "(agentid=" + agentId + ")"); + _workDao.updateStep(work.getInstanceId(), seqnum, Step.Done); + } + + cmd = generateRulesetCmd(SecurityRuleType.EgressRule, vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), generateRulesetSignature(rules), seqnum, + rules); + cmds = new Commands(cmd); + try { + _agentMgr.send(agentId, cmds, _answerListener); + } catch (AgentUnavailableException e) { + s_logger.debug("Unable to send egress rules updates for vm: " + userVmId + "(agentid=" + agentId + ")"); _workDao.updateStep(work.getInstanceId(), seqnum, Step.Done); } } @@ -1002,7 +1055,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG throw new InvalidParameterValueException("The network group default is reserved"); } - List allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(groupId); + List allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(groupId); List securityGroupVmMap = _securityGroupVMMapDao.listBySecurityGroup(groupId); if (!allowingRules.isEmpty()) { throw new ResourceInUseException("Cannot delete group when there are ingress rules that allow this group"); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java index ed52e79a65f..82dbc2f7614 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl2.java @@ -28,7 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.ejb.Local; import javax.naming.ConfigurationException; -import com.cloud.agent.api.SecurityIngressRulesCmd; +import com.cloud.agent.api.SecurityGroupRulesCmd; import com.cloud.agent.manager.Commands; import com.cloud.configuration.Config; import com.cloud.exception.AgentUnavailableException; @@ -39,7 +39,7 @@ import com.cloud.utils.Profiler; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.mgmt.JmxUtil; import com.cloud.vm.VirtualMachine.State; - +import com.cloud.network.security.SecurityRule.SecurityRuleType; /** * Same as the base class -- except it uses the abstracted security group work queue @@ -143,7 +143,8 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ continue; } work.setLogsequenceNumber(rulesetLog.getLogsequence()); - sendRulesetUpdates(work); + sendRulesetUpdates(work, SecurityRuleType.IngressRule); + sendRulesetUpdates(work, SecurityRuleType.EgressRule); _mBean.logUpdateDetails(work.getInstanceId(), work.getLogsequenceNumber()); }catch (Exception e) { s_logger.error("Problem during SG work " + work, e); @@ -155,7 +156,7 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ } } - public void sendRulesetUpdates(SecurityGroupWork work){ + public void sendRulesetUpdates(SecurityGroupWork work, SecurityRuleType ruleType){ Long userVmId = work.getInstanceId(); UserVm vm = _userVMDao.findById(userVmId); @@ -170,8 +171,8 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ + ": too many messages outstanding on host " + agentId); return; } - Map> rules = generateRulesForVM(userVmId); - SecurityIngressRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), vm.getPrivateIpAddress(), + Map> rules = generateRulesForVM(userVmId, ruleType); + SecurityGroupRulesCmd cmd = generateRulesetCmd(ruleType, vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), null, work.getLogsequenceNumber(), rules); cmd.setMsId(_serverId); @@ -212,14 +213,14 @@ public class SecurityGroupManagerImpl2 extends SecurityGroupManagerImpl{ * then we get all ips, including the default nic ip. This is also probably the correct behavior. */ @Override - protected Map> generateRulesForVM(Long userVmId) { + protected Map> generateRulesForVM(Long userVmId, SecurityRuleType type) { Map> allowed = new TreeMap>(); List groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVmId); for (SecurityGroupVMMapVO mapVO : groupsForVm) { - List rules = _ingressRuleDao.listBySecurityGroupId(mapVO.getSecurityGroupId()); - for (IngressRuleVO rule : rules) { + List rules = _securityGroupRuleDao.listBySecurityGroupId(mapVO.getSecurityGroupId(), type); + for (SecurityGroupRuleVO rule : rules) { PortAndProto portAndProto = new PortAndProto(rule.getProtocol(), rule.getStartPort(), rule.getEndPort()); Set cidrs = allowed.get(portAndProto); if (cidrs == null) { diff --git a/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java b/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java index dc8d15196b2..7eb1fc0abe2 100644 --- a/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java +++ b/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java @@ -14,6 +14,7 @@ import com.cloud.network.security.LocalSecurityGroupWorkQueue.LocalSecurityGroup import com.cloud.network.security.SecurityGroupWork.Step; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.Type; +import com.cloud.network.security.SecurityRule.SecurityRuleType; public class SecurityManagerMBeanImpl extends StandardMBean implements SecurityGroupManagerMBean, RuleUpdateLog { SecurityGroupManagerImpl2 _sgMgr; @@ -118,7 +119,8 @@ public class SecurityManagerMBeanImpl extends StandardMBean implements SecurityG @Override public void tryRulesetUpdateForVmBypassSchedulerVeryDangerous(Long vmId, Long seqno) { LocalSecurityGroupWork work = new LocalSecurityGroupWorkQueue.LocalSecurityGroupWork(vmId, seqno, Step.Scheduled); - _sgMgr.sendRulesetUpdates(work); + _sgMgr.sendRulesetUpdates(work, SecurityRuleType.IngressRule); + _sgMgr.sendRulesetUpdates(work, SecurityRuleType.EgressRule); } @Override diff --git a/server/src/com/cloud/network/security/dao/EgressRuleDao.java b/server/src/com/cloud/network/security/dao/EgressRuleDao.java deleted file mode 100644 index 9cc514d0a86..00000000000 --- a/server/src/com/cloud/network/security/dao/EgressRuleDao.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package com.cloud.network.security.dao; - -import java.util.List; - -import com.cloud.network.security.EgressRuleVO; -import com.cloud.utils.db.GenericDao; - -public interface EgressRuleDao extends GenericDao { - List listBySecurityGroupId(long networkGroupId); - List listByAllowedSecurityGroupId(long networkGroupId); - EgressRuleVO findByProtoPortsAndCidr(long networkGroupId, String proto, int startPort, int endPort, String cidr); - EgressRuleVO findByProtoPortsAndGroup(String proto, int startPort, int endPort, String networkGroup); - EgressRuleVO findByProtoPortsAndAllowedGroupId(long networkGroupId, String proto, int startPort, int endPort, Long allowedGroupId); - int deleteBySecurityGroup(long securityGroupId); - int deleteByPortProtoAndGroup(long securityGroupId, String protocol, int startPort,int endPort, Long id); - int deleteByPortProtoAndCidr(long securityGroupId, String protocol, int startPort,int endPort, String cidr); - -} diff --git a/server/src/com/cloud/network/security/dao/EgressRuleDaoImpl.java b/server/src/com/cloud/network/security/dao/EgressRuleDaoImpl.java deleted file mode 100644 index adb11b71e43..00000000000 --- a/server/src/com/cloud/network/security/dao/EgressRuleDaoImpl.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - * - * This software is licensed under the GNU General Public License v3 or later. - * - * It is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package com.cloud.network.security.dao; - -import java.util.List; -import java.util.Map; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import com.cloud.network.security.EgressRuleVO; -import com.cloud.network.security.SecurityGroupVO; -import com.cloud.utils.component.Inject; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; - -@Local(value={EgressRuleDao.class}) -public class EgressRuleDaoImpl extends GenericDaoBase implements EgressRuleDao { - - @Inject SecurityGroupDao _securityGroupDao; - - protected SearchBuilder securityGroupIdSearch; - protected SearchBuilder allowedSecurityGroupIdSearch; - protected SearchBuilder protoPortsAndCidrSearch; - protected SearchBuilder protoPortsAndSecurityGroupNameSearch; - protected SearchBuilder protoPortsAndSecurityGroupIdSearch; - - - - protected EgressRuleDaoImpl() { - securityGroupIdSearch = createSearchBuilder(); - securityGroupIdSearch.and("securityGroupId", securityGroupIdSearch.entity().getSecurityGroupId(), SearchCriteria.Op.EQ); - securityGroupIdSearch.done(); - - allowedSecurityGroupIdSearch = createSearchBuilder(); - allowedSecurityGroupIdSearch.and("allowedNetworkId", allowedSecurityGroupIdSearch.entity().getAllowedNetworkId(), SearchCriteria.Op.EQ); - allowedSecurityGroupIdSearch.done(); - - protoPortsAndCidrSearch = createSearchBuilder(); - protoPortsAndCidrSearch.and("securityGroupId", protoPortsAndCidrSearch.entity().getSecurityGroupId(), SearchCriteria.Op.EQ); - protoPortsAndCidrSearch.and("proto", protoPortsAndCidrSearch.entity().getProtocol(), SearchCriteria.Op.EQ); - protoPortsAndCidrSearch.and("startPort", protoPortsAndCidrSearch.entity().getStartPort(), SearchCriteria.Op.EQ); - protoPortsAndCidrSearch.and("endPort", protoPortsAndCidrSearch.entity().getEndPort(), SearchCriteria.Op.EQ); - protoPortsAndCidrSearch.and("cidr", protoPortsAndCidrSearch.entity().getAllowedDestinationIpCidr(), SearchCriteria.Op.EQ); - protoPortsAndCidrSearch.done(); - - protoPortsAndSecurityGroupIdSearch = createSearchBuilder(); - protoPortsAndSecurityGroupIdSearch.and("securityGroupId", protoPortsAndSecurityGroupIdSearch.entity().getSecurityGroupId(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupIdSearch.and("proto", protoPortsAndSecurityGroupIdSearch.entity().getProtocol(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupIdSearch.and("startPort", protoPortsAndSecurityGroupIdSearch.entity().getStartPort(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupIdSearch.and("endPort", protoPortsAndSecurityGroupIdSearch.entity().getEndPort(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupIdSearch.and("allowedNetworkId", protoPortsAndSecurityGroupIdSearch.entity().getAllowedNetworkId(), SearchCriteria.Op.EQ); - - } - - public List listBySecurityGroupId(long securityGroupId) { - SearchCriteria sc = securityGroupIdSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); - return listBy(sc); - } - - public int deleteBySecurityGroup(long securityGroupId) { - SearchCriteria sc = securityGroupIdSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); - return expunge(sc); - } - - @Override - public List listByAllowedSecurityGroupId(long securityGroupId) { - SearchCriteria sc = allowedSecurityGroupIdSearch.create(); - sc.setParameters("allowedNetworkId", securityGroupId); - return listBy(sc); - } - - @Override - public EgressRuleVO findByProtoPortsAndCidr(long securityGroupId, String proto, int startPort, - int endPort, String cidr) { - SearchCriteria sc = protoPortsAndCidrSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); - sc.setParameters("proto", proto); - sc.setParameters("startPort", startPort); - sc.setParameters("endPort", endPort); - sc.setParameters("cidr", cidr); - return findOneIncludingRemovedBy(sc); - } - - @Override - public EgressRuleVO findByProtoPortsAndGroup(String proto, int startPort, - int endPort, String securityGroup) { - SearchCriteria sc = protoPortsAndSecurityGroupNameSearch.create(); - sc.setParameters("proto", proto); - sc.setParameters("startPort", startPort); - sc.setParameters("endPort", endPort); - sc.setJoinParameters("groupName", "groupName", securityGroup); - return findOneIncludingRemovedBy(sc); - } - - @Override - public boolean configure(String name, Map params) - throws ConfigurationException { - protoPortsAndSecurityGroupNameSearch = createSearchBuilder(); - protoPortsAndSecurityGroupNameSearch.and("proto", protoPortsAndSecurityGroupNameSearch.entity().getProtocol(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupNameSearch.and("startPort", protoPortsAndSecurityGroupNameSearch.entity().getStartPort(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupNameSearch.and("endPort", protoPortsAndSecurityGroupNameSearch.entity().getEndPort(), SearchCriteria.Op.EQ); - SearchBuilder ngSb = _securityGroupDao.createSearchBuilder(); - ngSb.and("groupName", ngSb.entity().getName(), SearchCriteria.Op.EQ); - protoPortsAndSecurityGroupNameSearch.join("groupName", ngSb, protoPortsAndSecurityGroupNameSearch.entity().getAllowedNetworkId(), ngSb.entity().getId(), JoinBuilder.JoinType.INNER); - protoPortsAndSecurityGroupNameSearch.done(); - return super.configure(name, params); - } - - @Override - public int deleteByPortProtoAndGroup(long securityGroupId, String protocol, int startPort, int endPort, Long allowedGroupId) { - SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); - sc.setParameters("proto", protocol); - sc.setParameters("startPort", startPort); - sc.setParameters("endPort", endPort); - sc.setParameters("allowedNetworkId", allowedGroupId); - - return expunge(sc); - - } - - @Override - public int deleteByPortProtoAndCidr(long securityGroupId, String protocol, int startPort, int endPort, String cidr) { - SearchCriteria sc = protoPortsAndCidrSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); - sc.setParameters("proto", protocol); - sc.setParameters("startPort", startPort); - sc.setParameters("endPort", endPort); - sc.setParameters("cidr", cidr); - - return expunge(sc); - } - - @Override - public EgressRuleVO findByProtoPortsAndAllowedGroupId(long securityGroupId, String proto, - int startPort, int endPort, Long allowedGroupId) { - SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); - sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroupId); - sc.setParameters("proto", proto); - sc.setParameters("startPort", startPort); - sc.setParameters("endPort", endPort); - sc.setParameters("allowedNetworkId", allowedGroupId); - - return findOneIncludingRemovedBy(sc); - } -} diff --git a/server/src/com/cloud/network/security/dao/IngressRuleDao.java b/server/src/com/cloud/network/security/dao/SecurityGroupRuleDao.java similarity index 59% rename from server/src/com/cloud/network/security/dao/IngressRuleDao.java rename to server/src/com/cloud/network/security/dao/SecurityGroupRuleDao.java index c95e4ee567b..dad4c23c472 100644 --- a/server/src/com/cloud/network/security/dao/IngressRuleDao.java +++ b/server/src/com/cloud/network/security/dao/SecurityGroupRuleDao.java @@ -20,15 +20,16 @@ package com.cloud.network.security.dao; import java.util.List; -import com.cloud.network.security.IngressRuleVO; +import com.cloud.network.security.SecurityGroupRuleVO; +import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.utils.db.GenericDao; -public interface IngressRuleDao extends GenericDao { - List listBySecurityGroupId(long networkGroupId); - List listByAllowedSecurityGroupId(long networkGroupId); - IngressRuleVO findByProtoPortsAndCidr(long networkGroupId, String proto, int startPort, int endPort, String cidr); - IngressRuleVO findByProtoPortsAndGroup(String proto, int startPort, int endPort, String networkGroup); - IngressRuleVO findByProtoPortsAndAllowedGroupId(long networkGroupId, String proto, int startPort, int endPort, Long allowedGroupId); +public interface SecurityGroupRuleDao extends GenericDao { + List listBySecurityGroupId(long securityGroupId, SecurityRuleType type); + List listByAllowedSecurityGroupId(long networkGroupId); + SecurityGroupRuleVO findByProtoPortsAndCidr(long networkGroupId, String proto, int startPort, int endPort, String cidr); + SecurityGroupRuleVO findByProtoPortsAndGroup(String proto, int startPort, int endPort, String networkGroup); + SecurityGroupRuleVO findByProtoPortsAndAllowedGroupId(long networkGroupId, String proto, int startPort, int endPort, Long allowedGroupId); int deleteBySecurityGroup(long securityGroupId); int deleteByPortProtoAndGroup(long securityGroupId, String protocol, int startPort,int endPort, Long id); int deleteByPortProtoAndCidr(long securityGroupId, String protocol, int startPort,int endPort, String cidr); diff --git a/server/src/com/cloud/network/security/dao/IngressRuleDaoImpl.java b/server/src/com/cloud/network/security/dao/SecurityGroupRuleDaoImpl.java similarity index 71% rename from server/src/com/cloud/network/security/dao/IngressRuleDaoImpl.java rename to server/src/com/cloud/network/security/dao/SecurityGroupRuleDaoImpl.java index dab386e1170..f5bb5a3bb70 100644 --- a/server/src/com/cloud/network/security/dao/IngressRuleDaoImpl.java +++ b/server/src/com/cloud/network/security/dao/SecurityGroupRuleDaoImpl.java @@ -24,32 +24,39 @@ import java.util.Map; import javax.ejb.Local; import javax.naming.ConfigurationException; -import com.cloud.network.security.IngressRuleVO; +import com.cloud.network.security.SecurityGroupRuleVO; import com.cloud.network.security.SecurityGroupVO; +import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.utils.component.Inject; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -@Local(value={IngressRuleDao.class}) -public class IngressRuleDaoImpl extends GenericDaoBase implements IngressRuleDao { +@Local(value={SecurityGroupRuleDao.class}) +public class SecurityGroupRuleDaoImpl extends GenericDaoBase implements SecurityGroupRuleDao { @Inject SecurityGroupDao _securityGroupDao; - protected SearchBuilder securityGroupIdSearch; - protected SearchBuilder allowedSecurityGroupIdSearch; - protected SearchBuilder protoPortsAndCidrSearch; - protected SearchBuilder protoPortsAndSecurityGroupNameSearch; - protected SearchBuilder protoPortsAndSecurityGroupIdSearch; + protected SearchBuilder securityGroupIdSearch; + protected SearchBuilder securityGroupIdAndTypeSearch; + protected SearchBuilder allowedSecurityGroupIdSearch; + protected SearchBuilder protoPortsAndCidrSearch; + protected SearchBuilder protoPortsAndSecurityGroupNameSearch; + protected SearchBuilder protoPortsAndSecurityGroupIdSearch; - protected IngressRuleDaoImpl() { + protected SecurityGroupRuleDaoImpl() { securityGroupIdSearch = createSearchBuilder(); securityGroupIdSearch.and("securityGroupId", securityGroupIdSearch.entity().getSecurityGroupId(), SearchCriteria.Op.EQ); securityGroupIdSearch.done(); + securityGroupIdAndTypeSearch = createSearchBuilder(); + securityGroupIdAndTypeSearch.and("securityGroupId", securityGroupIdAndTypeSearch.entity().getSecurityGroupId(), SearchCriteria.Op.EQ); + securityGroupIdAndTypeSearch.and("type", securityGroupIdAndTypeSearch.entity().getType(), SearchCriteria.Op.EQ); + securityGroupIdAndTypeSearch.done(); + allowedSecurityGroupIdSearch = createSearchBuilder(); allowedSecurityGroupIdSearch.and("allowedNetworkId", allowedSecurityGroupIdSearch.entity().getAllowedNetworkId(), SearchCriteria.Op.EQ); allowedSecurityGroupIdSearch.done(); @@ -71,29 +78,37 @@ public class IngressRuleDaoImpl extends GenericDaoBase impl } - public List listBySecurityGroupId(long securityGroupId) { - SearchCriteria sc = securityGroupIdSearch.create(); - sc.setParameters("securityGroupId", securityGroupId); + public List listBySecurityGroupId(long securityGroupId, SecurityRuleType type) { + SearchCriteria sc = securityGroupIdAndTypeSearch.create(); + sc.setParameters("securityGroupId", securityGroupId); + String dbType; + if (type == SecurityRuleType.EgressRule) { + dbType = SecurityRuleType.EgressRule.getType(); + }else { + dbType = SecurityRuleType.IngressRule.getType(); + } + + sc.setParameters("type", dbType); return listBy(sc); } public int deleteBySecurityGroup(long securityGroupId) { - SearchCriteria sc = securityGroupIdSearch.create(); + SearchCriteria sc = securityGroupIdSearch.create(); sc.setParameters("securityGroupId", securityGroupId); return expunge(sc); } @Override - public List listByAllowedSecurityGroupId(long securityGroupId) { - SearchCriteria sc = allowedSecurityGroupIdSearch.create(); + public List listByAllowedSecurityGroupId(long securityGroupId) { + SearchCriteria sc = allowedSecurityGroupIdSearch.create(); sc.setParameters("allowedNetworkId", securityGroupId); return listBy(sc); } @Override - public IngressRuleVO findByProtoPortsAndCidr(long securityGroupId, String proto, int startPort, + public SecurityGroupRuleVO findByProtoPortsAndCidr(long securityGroupId, String proto, int startPort, int endPort, String cidr) { - SearchCriteria sc = protoPortsAndCidrSearch.create(); + SearchCriteria sc = protoPortsAndCidrSearch.create(); sc.setParameters("securityGroupId", securityGroupId); sc.setParameters("proto", proto); sc.setParameters("startPort", startPort); @@ -103,9 +118,9 @@ public class IngressRuleDaoImpl extends GenericDaoBase impl } @Override - public IngressRuleVO findByProtoPortsAndGroup(String proto, int startPort, + public SecurityGroupRuleVO findByProtoPortsAndGroup(String proto, int startPort, int endPort, String securityGroup) { - SearchCriteria sc = protoPortsAndSecurityGroupNameSearch.create(); + SearchCriteria sc = protoPortsAndSecurityGroupNameSearch.create(); sc.setParameters("proto", proto); sc.setParameters("startPort", startPort); sc.setParameters("endPort", endPort); @@ -129,7 +144,7 @@ public class IngressRuleDaoImpl extends GenericDaoBase impl @Override public int deleteByPortProtoAndGroup(long securityGroupId, String protocol, int startPort, int endPort, Long allowedGroupId) { - SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); + SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); sc.setParameters("securityGroupId", securityGroupId); sc.setParameters("proto", protocol); sc.setParameters("startPort", startPort); @@ -142,7 +157,7 @@ public class IngressRuleDaoImpl extends GenericDaoBase impl @Override public int deleteByPortProtoAndCidr(long securityGroupId, String protocol, int startPort, int endPort, String cidr) { - SearchCriteria sc = protoPortsAndCidrSearch.create(); + SearchCriteria sc = protoPortsAndCidrSearch.create(); sc.setParameters("securityGroupId", securityGroupId); sc.setParameters("proto", protocol); sc.setParameters("startPort", startPort); @@ -153,9 +168,9 @@ public class IngressRuleDaoImpl extends GenericDaoBase impl } @Override - public IngressRuleVO findByProtoPortsAndAllowedGroupId(long securityGroupId, String proto, + public SecurityGroupRuleVO findByProtoPortsAndAllowedGroupId(long securityGroupId, String proto, int startPort, int endPort, Long allowedGroupId) { - SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); + SearchCriteria sc = protoPortsAndSecurityGroupIdSearch.create(); sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroupId); sc.setParameters("proto", proto); sc.setParameters("startPort", startPort); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 778601e619d..61bdcf5e8ae 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -129,6 +129,7 @@ import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.DateUtil; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -1712,6 +1713,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene AgentVmInfo info = infos.remove(vm.getId()); VMInstanceVO castedVm = null; if (info == null) { + // the vm is not there on cluster, check the vm status in DB + if (vm.getState() == State.Starting && (DateUtil.currentGMTTime().getTime() - vm.getUpdateTime().getTime()) < 10*60*1000){ + continue; // ignoring this VM as it is still settling + } info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); castedVm = info.guru.findById(vm.getId()); hId = vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId(); diff --git a/server/src/com/cloud/vm/dao/UserVmData.java b/server/src/com/cloud/vm/dao/UserVmData.java index 56b3a778f97..4cb014bd67f 100644 --- a/server/src/com/cloud/vm/dao/UserVmData.java +++ b/server/src/com/cloud/vm/dao/UserVmData.java @@ -22,7 +22,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import com.cloud.api.response.IngressRuleResponse; +import com.cloud.api.response.SecurityGroupRuleResponse; public class UserVmData { private Long id; @@ -580,7 +580,7 @@ public class UserVmData { private String domainName; private Long jobId; private Integer jobStatus; - private List ingressRules; + private List securityGroupRules; public String getObjectName() { return objectName; @@ -637,16 +637,15 @@ public class UserVmData { public void setDomainName(String domainName) { this.domainName = domainName; } - - public List getIngressRules() { - return ingressRules; +/* FIXME : the below functions are not used, so commenting out later need to include egress list + public List getIngressRules() { + return securityGroupRules; } - public void setIngressRules(List ingressRules) { - this.ingressRules = ingressRules; - } + public void setIngressRules(List securityGroupRules) { + this.securityGroupRules = securityGroupRules; + } */ - @Override public int hashCode() { final int prime = 31; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 28240b0e89f..bddbc5eafe7 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -107,8 +107,7 @@ DROP TABLE IF EXISTS `cloud`.`ovs_vm_flow_log`; DROP TABLE IF EXISTS `cloud`.`ovs_work`; DROP TABLE IF EXISTS `cloud`.`remote_access_vpn`; DROP TABLE IF EXISTS `cloud`.`resource_count`; -DROP TABLE IF EXISTS `cloud`.`security_ingress_rule`; -DROP TABLE IF EXISTS `cloud`.`security_egress_rule`; +DROP TABLE IF EXISTS `cloud`.`security_group_rule`; DROP TABLE IF EXISTS `cloud`.`stack_maid`; DROP TABLE IF EXISTS `cloud`.`storage_pool_work`; DROP TABLE IF EXISTS `cloud`.`user_vm_details`; @@ -1515,10 +1514,11 @@ CREATE TABLE `cloud`.`security_group` ( CONSTRAINT `uc_security_group__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE `cloud`.`security_ingress_rule` ( +CREATE TABLE `cloud`.`security_group_rule` ( `id` bigint unsigned NOT NULL auto_increment, `uuid` varchar(40), `security_group_id` bigint unsigned NOT NULL, + `type` varchar(10) default 'ingress', `start_port` varchar(10) default NULL, `end_port` varchar(10) default NULL, `protocol` varchar(16) NOT NULL default 'TCP', @@ -1526,21 +1526,7 @@ CREATE TABLE `cloud`.`security_ingress_rule` ( `allowed_ip_cidr` varchar(44), `create_status` varchar(32) COMMENT 'rule creation status', PRIMARY KEY (`id`), - CONSTRAINT `uc_security_ingress_rule__uuid` UNIQUE (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -CREATE TABLE `cloud`.`security_egress_rule` ( - `id` bigint unsigned NOT NULL auto_increment, - `uuid` varchar(40), - `security_group_id` bigint unsigned NOT NULL, - `start_port` varchar(10) default NULL, - `end_port` varchar(10) default NULL, - `protocol` varchar(16) NOT NULL default 'TCP', - `allowed_network_id` bigint unsigned, - `allowed_ip_cidr` varchar(44), - `create_status` varchar(32) COMMENT 'rule creation status', - PRIMARY KEY (`id`), - CONSTRAINT `uc_security_egress_rule__uuid` UNIQUE (`uuid`) + CONSTRAINT `uc_security_group_rule__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`security_group_vm_map` ( diff --git a/setup/db/db/schema-2213to30.sql b/setup/db/db/schema-2213to30.sql index 7cb06e94fca..5129bd2f80c 100755 --- a/setup/db/db/schema-2213to30.sql +++ b/setup/db/db/schema-2213to30.sql @@ -187,11 +187,6 @@ ALTER TABLE `cloud`.`firewall_rules` ADD CONSTRAINT `uc_firewall_rules__uuid` UN ALTER TABLE `cloud`.`cluster` ADD COLUMN `uuid` varchar(40); ALTER TABLE `cloud`.`cluster` ADD CONSTRAINT `uc_cluster__uuid` UNIQUE (`uuid`); -ALTER TABLE `cloud`.`security_ingress_rule` ADD COLUMN `uuid` varchar(40); -ALTER TABLE `cloud`.`security_ingress_rule` ADD CONSTRAINT `uc_security_ingress_rule__uuid` UNIQUE (`uuid`); - -ALTER TABLE `cloud`.`security_egress_rule` ADD COLUMN `uuid` varchar(40); -ALTER TABLE `cloud`.`security_egress_rule` ADD CONSTRAINT `uc_security_egress_rule__uuid` UNIQUE (`uuid`); ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `uuid` varchar(40); ALTER TABLE `cloud`.`network_offerings` ADD CONSTRAINT `uc_network_offerings__uuid` UNIQUE (`uuid`); @@ -217,3 +212,8 @@ ALTER TABLE `cloud`.`guest_os_category` ADD CONSTRAINT `uc_guest_os_category__uu ALTER TABLE `cloud`.`nics` ADD COLUMN `uuid` varchar(40); ALTER TABLE `cloud`.`nics` ADD CONSTRAINT `uc_nics__uuid` UNIQUE (`uuid`); +ALTER TABLE `cloud`.`security_ingress_rule` RENAME TO `security_group_rule`; +ALTER TABLE `cloud`.`security_group_rule` ADD COLUMN `type` varchar(10) default 'ingress' AFTER security_group_id; + +ALTER TABLE `cloud`.`security_group_rule` ADD COLUMN `uuid` varchar(40); +ALTER TABLE `cloud`.`security_group_rule` ADD CONSTRAINT `uc_security_group_rule__uuid` UNIQUE (`uuid`);