From a2499c9e69a4a24f1d3d8915dbfe9a1ee0173f20 Mon Sep 17 00:00:00 2001 From: Abhinandan Prateek Date: Thu, 10 Nov 2011 11:32:10 +0530 Subject: [PATCH 1/4] bug 11910: during full sync ignoring VMs which have been into starting state shortly reviewed-by: kishan --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index bf843c70c05..ade5a865d1d 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -130,6 +130,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; @@ -1713,6 +1714,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(); From 02adbd4bd3aa0b1cc97da059ee78085c03fb628b Mon Sep 17 00:00:00 2001 From: Naredula Janardhana Reddy Date: Thu, 10 Nov 2011 15:23:48 +0530 Subject: [PATCH 2/4] bug 10617: merging code from branch bug10617 --- .../computing/FakeComputingResource.java | 12 +- .../computing/LibvirtComputingResource.java | 21 +- .../agent/api/SecurityEgressRuleAnswer.java | 47 ---- .../agent/api/SecurityEgressRulesCmd.java | 144 ----------- ...swer.java => SecurityGroupRuleAnswer.java} | 10 +- ...lesCmd.java => SecurityGroupRulesCmd.java} | 25 +- api/src/com/cloud/api/ResponseGenerator.java | 7 +- .../AuthorizeSecurityGroupEgressCmd.java | 233 ++++++++++++++++++ .../AuthorizeSecurityGroupIngressCmd.java | 12 +- .../RevokeSecurityGroupEgressCmd.java | 111 +++++++++ .../RevokeSecurityGroupIngressCmd.java | 2 +- .../api/response/IngressRuleResponse.java | 124 ---------- .../api/response/SecurityGroupResponse.java | 22 +- ...se.java => SecurityGroupRuleResponse.java} | 16 +- api/src/com/cloud/event/EventTypes.java | 2 + .../cloud/network/security/EgressRule.java | 39 --- .../network/security/SecurityGroupRules.java | 3 + .../security/SecurityGroupService.java | 7 +- .../{IngressRule.java => SecurityRule.java} | 24 +- client/tomcatconf/commands.properties.in | 2 + .../xen/resource/CitrixResourceBase.java | 56 +---- .../cloud/network/security/EgressRuleVO.java | 141 ----------- ...ssRuleVO.java => SecurityGroupRuleVO.java} | 39 ++- .../security/SecurityGroupRulesVO.java | 27 +- .../cloud/ovm/hypervisor/OvmResourceBase.java | 14 +- scripts/vm/hypervisor/xenserver/vmops | 48 +++- scripts/vm/network/security_group.py | 65 +++-- .../src/com/cloud/api/ApiResponseHelper.java | 190 ++++++-------- .../api/response/EgressRuleResultObject.java | 112 --------- .../response/SecurityGroupResultObject.java | 86 ++++--- ...ava => SecurityGroupRuleResultObject.java} | 24 +- .../DefaultComponentLibrary.java | 4 +- .../security/SecurityGroupListener.java | 8 +- .../security/SecurityGroupManagerImpl.java | 151 ++++++++---- .../security/SecurityGroupManagerImpl2.java | 19 +- .../security/SecurityManagerMBeanImpl.java | 4 +- .../network/security/dao/EgressRuleDao.java | 36 --- .../security/dao/EgressRuleDaoImpl.java | 167 ------------- ...RuleDao.java => SecurityGroupRuleDao.java} | 15 +- ...mpl.java => SecurityGroupRuleDaoImpl.java} | 61 +++-- server/src/com/cloud/vm/dao/UserVmData.java | 17 +- setup/db/create-schema.sql | 22 +- setup/db/db/schema-2213to30.sql | 9 +- 43 files changed, 933 insertions(+), 1245 deletions(-) delete mode 100644 api/src/com/cloud/agent/api/SecurityEgressRuleAnswer.java delete mode 100644 api/src/com/cloud/agent/api/SecurityEgressRulesCmd.java rename api/src/com/cloud/agent/api/{SecurityIngressRuleAnswer.java => SecurityGroupRuleAnswer.java} (82%) rename api/src/com/cloud/agent/api/{SecurityIngressRulesCmd.java => SecurityGroupRulesCmd.java} (85%) create mode 100644 api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java create mode 100644 api/src/com/cloud/api/commands/RevokeSecurityGroupEgressCmd.java delete mode 100644 api/src/com/cloud/api/response/IngressRuleResponse.java rename api/src/com/cloud/api/response/{EgressRuleResponse.java => SecurityGroupRuleResponse.java} (89%) delete mode 100644 api/src/com/cloud/network/security/EgressRule.java rename api/src/com/cloud/network/security/{IngressRule.java => SecurityRule.java} (66%) delete mode 100644 core/src/com/cloud/network/security/EgressRuleVO.java rename core/src/com/cloud/network/security/{IngressRuleVO.java => SecurityGroupRuleVO.java} (75%) delete mode 100644 server/src/com/cloud/api/response/EgressRuleResultObject.java rename server/src/com/cloud/api/response/{IngressRuleResultObject.java => SecurityGroupRuleResultObject.java} (81%) delete mode 100644 server/src/com/cloud/network/security/dao/EgressRuleDao.java delete mode 100644 server/src/com/cloud/network/security/dao/EgressRuleDaoImpl.java rename server/src/com/cloud/network/security/dao/{IngressRuleDao.java => SecurityGroupRuleDao.java} (59%) rename server/src/com/cloud/network/security/dao/{IngressRuleDaoImpl.java => SecurityGroupRuleDaoImpl.java} (71%) 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 0eb311ce868..669e97e48f4 100755 --- a/api/src/com/cloud/api/ResponseGenerator.java +++ b/api/src/com/cloud/api/ResponseGenerator.java @@ -87,8 +87,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; @@ -187,9 +186,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 103316a6031..645d3ea5460 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 3884f03c781..992de44d233 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 d637de34e2f..fa4171bc99a 100755 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -113,10 +113,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; @@ -477,8 +475,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) { @@ -4678,38 +4676,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); @@ -4717,16 +4685,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()), @@ -4735,10 +4703,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/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 4ee69f2bace..192e2910725 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; @@ -127,8 +126,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; @@ -180,6 +179,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 { @@ -1771,8 +1772,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(); @@ -1781,37 +1784,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); @@ -2180,14 +2195,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()); @@ -2202,21 +2217,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) { @@ -2224,7 +2240,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) { @@ -2232,90 +2248,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(); @@ -2740,3 +2693,4 @@ public class ApiResponseHelper implements ResponseGenerator { return vmResponse; } } + 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 ee02971e66a..49e60d4b3bb 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -100,7 +100,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; @@ -210,7 +210,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 4a66c5fd139..4ea1e52febf 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; @@ -65,7 +67,7 @@ import com.cloud.exception.ResourceInUseException; import com.cloud.hypervisor.Hypervisor.HypervisorType; 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; @@ -107,6 +109,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; @@ -117,7 +120,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Inject SecurityGroupDao _securityGroupDao; @Inject - IngressRuleDao _ingressRuleDao; + SecurityGroupRuleDao _securityGroupRuleDao; @Inject SecurityGroupVMMapDao _securityGroupVMMapDao; @Inject @@ -326,14 +329,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) { @@ -446,9 +449,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; } @@ -458,18 +461,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) { @@ -479,16 +482,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) { @@ -519,11 +522,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(); @@ -532,10 +535,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); @@ -620,13 +643,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 @@ -650,7 +673,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(); @@ -663,23 +686,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()) { @@ -691,28 +714,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); @@ -729,8 +772,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())); @@ -738,8 +781,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()); @@ -883,16 +926,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); } } @@ -1000,7 +1053,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 ccef51c10d8..8350da4770e 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 @@ -147,7 +147,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); @@ -161,7 +162,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); @@ -176,8 +177,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); @@ -218,14 +219,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/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 213c3244dce..b3e255bf5a0 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`; @@ -1516,10 +1515,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', @@ -1527,21 +1527,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..5a5017e6be3 100755 --- a/setup/db/db/schema-2213to30.sql +++ b/setup/db/db/schema-2213to30.sql @@ -187,11 +187,9 @@ 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_group_rule` ADD COLUMN `uuid` varchar(40); +ALTER TABLE `cloud`.`security_group_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 +215,6 @@ 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; + From b53dc42d0a328e6c1515889e984cdc50530c0834 Mon Sep 17 00:00:00 2001 From: Naredula Janardhana Reddy Date: Thu, 10 Nov 2011 15:37:02 +0530 Subject: [PATCH 3/4] bug 10617: alter the sequence of add column --- setup/db/db/schema-2213to30.sql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setup/db/db/schema-2213to30.sql b/setup/db/db/schema-2213to30.sql index 5a5017e6be3..5129bd2f80c 100755 --- a/setup/db/db/schema-2213to30.sql +++ b/setup/db/db/schema-2213to30.sql @@ -187,9 +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_group_rule` ADD COLUMN `uuid` varchar(40); -ALTER TABLE `cloud`.`security_group_rule` ADD CONSTRAINT `uc_security_ingress_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`); @@ -218,3 +215,5 @@ 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`); From 991ac4835afd0a935a9606424c046973a0ff08b9 Mon Sep 17 00:00:00 2001 From: frank Date: Thu, 10 Nov 2011 14:46:56 -0800 Subject: [PATCH 4/4] Bug 11933 - Unable to add Primary Storage (OCFS2) to a OVM Cluster Bug 11948 - Cannot add a new OVM host to an existing OVM cluster Bug 11699 - OVM - add host previously used in other OVM cluster > host went to alert state> host cleanup procedure needed status 11933: resolve fixed status 11948: resolve fixed status 11699: resolve fixed replace ovs-agent ocfs2 functions with our implementation. ovs-agent's implementation doesn't check error condition, it can only run if everything is correct. we also add check for used host without clean up, clean up procedure will print out as error message reviewed-by: edison --- .../vm/hypervisor/ovm/OvmCommonModule.py | 16 +++- .../vm/hypervisor/ovm/OvmFaultConstants.py | 12 +++ .../vm/hypervisor/ovm/OvmOCFS2Module.py | 62 +++++++++++++++ .../vm/hypervisor/ovm/OvmStoragePoolModule.py | 75 +++++-------------- 4 files changed, 105 insertions(+), 60 deletions(-) create mode 100755 ovm/scripts/vm/hypervisor/ovm/OvmOCFS2Module.py 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