diff --git a/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java new file mode 100644 index 00000000000..d7942e0cf7a --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesAnswer.java @@ -0,0 +1,38 @@ +/** + * 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.routing; + +import com.cloud.agent.api.Answer; + +public class SetStaticNatRulesAnswer extends Answer { + String[] results; + protected SetStaticNatRulesAnswer() { + super(); + } + + public SetStaticNatRulesAnswer(SetStaticNatRulesCommand cmd, String[] results) { + super(cmd, true, null); + + assert(cmd.getRules().length == results.length) : "Shouldn't the results match the commands?"; + this.results = results; + } + + String[] getResults() { + return results; + } +} diff --git a/api/src/com/cloud/agent/api/routing/SetStaticNatRulesCommand.java b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesCommand.java new file mode 100644 index 00000000000..5f7a07927d2 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/SetStaticNatRulesCommand.java @@ -0,0 +1,44 @@ +/** + * 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.routing; + +import java.util.List; + +import com.cloud.agent.api.to.StaticNatRuleTO; + +public class SetStaticNatRulesCommand extends NetworkElementCommand{ + + StaticNatRuleTO[] rules; + + protected SetStaticNatRulesCommand() { + } + + public SetStaticNatRulesCommand(List staticNatRules) { + rules = new StaticNatRuleTO[staticNatRules.size()]; + int i = 0; + for (StaticNatRuleTO rule : staticNatRules) { + rules[i++] = rule; + } + } + + public StaticNatRuleTO[] getRules() { + return rules; + } + +} diff --git a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java index ae6bfb5c538..8b0fce0295d 100644 --- a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java +++ b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java @@ -48,23 +48,22 @@ public class FirewallRuleTO { int[] srcPortRange; boolean revoked; boolean alreadyAdded; - boolean isOneToOneNat; - String vlanNetmask; // FIXME: Get rid of this! + FirewallRule.Purpose purpose; protected FirewallRuleTO() { } - public FirewallRuleTO(long id, String srcIp, String protocol, int srcPortStart, int srcPortEnd, boolean revoked, boolean alreadyAdded, boolean isOneToOneNat) { + public FirewallRuleTO(long id, String srcIp, String protocol, int srcPortStart, int srcPortEnd, boolean revoked, boolean alreadyAdded, FirewallRule.Purpose purpose) { this.srcIp = srcIp; this.protocol = protocol; this.srcPortRange = new int[] {srcPortStart, srcPortEnd}; this.revoked = revoked; this.alreadyAdded = alreadyAdded; - this.isOneToOneNat = isOneToOneNat; + this.purpose = purpose; } public FirewallRuleTO(FirewallRule rule, String srcIp) { - this(rule.getId(), srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.isOneToOneNat()); + this(rule.getId(), srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose()); } public long getId() { @@ -91,15 +90,12 @@ public class FirewallRuleTO { return revoked; } - public String getVlanNetmask() { - return vlanNetmask; - } - public boolean isAlreadyAdded() { return alreadyAdded; } - - public boolean isOneToOneNat() { - return isOneToOneNat; + + public FirewallRule.Purpose getPurpose() { + return purpose; } + } diff --git a/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java b/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java index 43e0e74bc26..4e7b5f5aacb 100644 --- a/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java +++ b/api/src/com/cloud/agent/api/to/PortForwardingRuleTO.java @@ -17,6 +17,7 @@ */ package com.cloud.agent.api.to; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.utils.net.NetUtils; @@ -41,7 +42,7 @@ public class PortForwardingRuleTO extends FirewallRuleTO { } protected PortForwardingRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) { - super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, false); + super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.PortForwarding); this.dstIp = dstIp; this.dstPortRange = new int[] { dstPortStart, dstPortEnd }; } diff --git a/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java b/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java new file mode 100644 index 00000000000..2c2f0dfdd1b --- /dev/null +++ b/api/src/com/cloud/agent/api/to/StaticNatRuleTO.java @@ -0,0 +1,53 @@ +/** + * 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.to; + +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRule.State; +import com.cloud.network.rules.StaticNatRule; + +/** + * StaticNatRuleTO specifies one static nat rule. + * + * See FirewallRuleTO for the stuff. + * + */ + +public class StaticNatRuleTO extends FirewallRuleTO{ + String dstIp; + + protected StaticNatRuleTO() { + } + + public StaticNatRuleTO(StaticNatRule rule, String scrIp, String dstIp) { + super(rule.getId(), scrIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(),rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose()); + this.dstIp = dstIp; + } + + + protected StaticNatRuleTO(long id, String srcIp, int srcPortStart, int srcPortEnd, String dstIp, int dstPortStart, int dstPortEnd, String protocol, boolean revoked, boolean brandNew) { + super(id, srcIp, protocol, srcPortStart, srcPortEnd, revoked, brandNew, FirewallRule.Purpose.StaticNat); + this.dstIp = dstIp; + } + + public String getDstIp() { + return dstIp; + } + +} diff --git a/api/src/com/cloud/api/ResponseGenerator.java b/api/src/com/cloud/api/ResponseGenerator.java index f4d6d160997..02d4dee5b81 100644 --- a/api/src/com/cloud/api/ResponseGenerator.java +++ b/api/src/com/cloud/api/ResponseGenerator.java @@ -40,12 +40,12 @@ import com.cloud.api.response.InstanceGroupResponse; import com.cloud.api.response.IpForwardingRuleResponse; import com.cloud.api.response.ListResponse; import com.cloud.api.response.LoadBalancerResponse; -import com.cloud.api.response.SecurityGroupResponse; import com.cloud.api.response.NetworkOfferingResponse; import com.cloud.api.response.NetworkResponse; import com.cloud.api.response.PodResponse; import com.cloud.api.response.RemoteAccessVpnResponse; import com.cloud.api.response.ResourceLimitResponse; +import com.cloud.api.response.SecurityGroupResponse; import com.cloud.api.response.ServiceOfferingResponse; import com.cloud.api.response.SnapshotPolicyResponse; import com.cloud.api.response.SnapshotResponse; @@ -76,6 +76,7 @@ import com.cloud.network.VpnUser; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNatRule; import com.cloud.network.security.IngressRule; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupRules; @@ -143,7 +144,7 @@ public interface ResponseGenerator { FirewallRuleResponse createFirewallRuleResponse(PortForwardingRule fwRule); - IpForwardingRuleResponse createIpForwardingRuleResponse(PortForwardingRule fwRule); + IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule); User findUserById(Long userId); diff --git a/api/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java b/api/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java index a8b055ead62..8ee28f75300 100644 --- a/api/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreateIpForwardingRuleCmd.java @@ -30,16 +30,15 @@ import com.cloud.api.ServerApiException; import com.cloud.api.response.FirewallRuleResponse; import com.cloud.api.response.IpForwardingRuleResponse; import com.cloud.event.EventTypes; -import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.network.IpAddress; -import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.StaticNatRule; import com.cloud.user.Account; import com.cloud.user.UserContext; -import com.cloud.utils.net.Ip; @Implementation(description="Creates an ip forwarding rule", responseObject=FirewallRuleResponse.class) -public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule { +public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements StaticNatRule { public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName()); private static final String s_name = "createipforwardingruleresponse"; @@ -91,15 +90,16 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por boolean result; try { UserContext.current().setEventDetails("Rule Id: "+getEntityId()); - result = _rulesService.applyPortForwardingRules(ipAddressId, UserContext.current().getCaller()); + result = _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller()); } catch (Exception e) { s_logger.error("Unable to apply port forwarding rules", e); - _rulesService.revokePortForwardingRule(getEntityId(), true); + _rulesService.revokeStaticNatRule(getEntityId(), true); result = false; } if (result) { - PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getEntityId()); - IpForwardingRuleResponse fwResponse = _responseGenerator.createIpForwardingRuleResponse(rule); + FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId()); + StaticNatRule staticNatRule = _rulesService.buildStaticNatRule(rule); + IpForwardingRuleResponse fwResponse = _responseGenerator.createIpForwardingRuleResponse(staticNatRule); fwResponse.setResponseName(getCommandName()); this.setResponseObject(fwResponse); } else { @@ -110,11 +110,11 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por @Override public void create() { - PortForwardingRule rule; + StaticNatRule rule; try { - rule = _rulesService.createPortForwardingRule(this, getVirtualMachineId(), true); + rule = _rulesService.createStaticNatRule(this); } catch (NetworkRuleConflictException e) { - s_logger.info("Unable to create Port Forwarding Rule due to " + e.getMessage()); + s_logger.info("Unable to create Static Nat Rule due to " + e.getMessage()); throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } @@ -140,7 +140,16 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por @Override public String getEventDescription() { IpAddress ip = _networkService.getIp(ipAddressId); - return ("Applying an ipforwarding 1:1 NAT rule for Ip: "+ip.getAddress()+" with virtual machine:"+ getVirtualMachineId()); + return ("Applying an ipforwarding 1:1 NAT rule for Ip: "+ip.getAddress()+" with virtual machine:"+ this.getVirtualMachineId()); + } + + private long getVirtualMachineId() { + return _networkService.getIp(ipAddressId).getAssociatedWithVmId(); + } + + @Override + public String getDestIpAddress(){ + return null; } @Override @@ -148,11 +157,6 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por throw new UnsupportedOperationException("Don't call me"); } - @Override - public String getXid() { - return null; - } - @Override public long getSourceIpAddressId() { return ipAddressId; @@ -178,12 +182,12 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por } @Override - public Purpose getPurpose() { - return Purpose.PortForwarding; + public FirewallRule.Purpose getPurpose() { + return FirewallRule.Purpose.StaticNat; } @Override - public State getState() { + public FirewallRule.State getState() { throw new UnsupportedOperationException("Don't call me"); } @@ -198,25 +202,6 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por return ip.getDomainId(); } - @Override - public Ip getDestinationIpAddress() { - return null; - } - - @Override - public int getDestinationPortStart() { - return startPort; - } - - @Override - public int getDestinationPortEnd() { - if (endPort == null) { - return startPort; - } else { - return endPort; - } - } - @Override public long getAccountId() { IpAddress ip = _networkService.getIp(ipAddressId); @@ -224,20 +209,9 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por } @Override - public boolean isOneToOneNat() { - return true; - } - - @Override - public long getVirtualMachineId() { - IpAddress ip = _networkService.getIp(ipAddressId); - if (ip == null) { - throw new InvalidParameterValueException("Ip address id=" + ipAddressId + " doesn't exist in the system"); - } else if (ip.isOneToOneNat() && ip.getAssociatedWithVmId() != null){ - return _networkService.getIp(ipAddressId).getAssociatedWithVmId(); - } else { - throw new InvalidParameterValueException("Ip address id=" + ipAddressId + " doesn't have 1-1 Nat feature enabled"); - } + public String getXid() { + // FIXME: We should allow for end user to specify Xid. + return null; } @Override @@ -249,5 +223,4 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Por public Long getSyncObjId() { return ipAddressId; } - } diff --git a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java index 3238579ec89..ac2c44598f6 100644 --- a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java @@ -181,11 +181,5 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer @Override public int getDefaultPortEnd() { return privatePort.intValue(); - } - - @Override - public boolean isOneToOneNat() { - return false; - } - + } } diff --git a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java index 7ba35187b5a..e4483956df1 100644 --- a/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreatePortForwardingRuleCmd.java @@ -200,7 +200,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements @Override public void create() { try { - PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, false); + PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId); setEntityId(result.getId()); } catch (NetworkRuleConflictException ex) { s_logger.info("Network rule conflict: " + ex.getMessage()); @@ -226,11 +226,6 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements return ip.getAccountId(); } - @Override - public boolean isOneToOneNat() { - return false; - } - @Override public String getSyncObjType() { return BaseAsyncCmd.ipAddressSyncObject; diff --git a/api/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java b/api/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java index 010a2db0e61..12da3295f77 100644 --- a/api/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java +++ b/api/src/com/cloud/api/commands/DeleteIpForwardingRuleCmd.java @@ -29,7 +29,7 @@ import com.cloud.api.ServerApiException; import com.cloud.api.response.SuccessResponse; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.FirewallRule; import com.cloud.user.UserContext; @Implementation(description="Deletes an ip forwarding rule", responseObject=SuccessResponse.class) @@ -69,7 +69,7 @@ public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd { @Override public void execute(){ UserContext.current().setEventDetails("Rule Id: "+id); - boolean result = _rulesService.revokePortForwardingRule(id, true); + boolean result = _rulesService.revokeStaticNatRule(id, true); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); @@ -82,9 +82,9 @@ public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { if (ownerId == null) { - PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, id); + FirewallRule rule = _entityMgr.findById(FirewallRule.class, id); if (rule == null) { - throw new InvalidParameterValueException("Unable to find firewall rule by id: " + id); + throw new InvalidParameterValueException("Unable to find static nat rule by id: " + id); } else { ownerId = rule.getAccountId(); } @@ -109,7 +109,7 @@ public class DeleteIpForwardingRuleCmd extends BaseAsyncCmd { @Override public Long getSyncObjId() { - return _rulesService.getPortForwardigRule(id).getSourceIpAddressId(); + return _rulesService.getFirewallRule(id).getSourceIpAddressId(); } } diff --git a/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java b/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java index 7d7f3182cdc..a5f51fbe84a 100644 --- a/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java +++ b/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java @@ -29,7 +29,8 @@ import com.cloud.api.Parameter; import com.cloud.api.response.FirewallRuleResponse; import com.cloud.api.response.IpForwardingRuleResponse; import com.cloud.api.response.ListResponse; -import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.StaticNatRule; @Implementation(description="List the ip forwarding rules", responseObject=FirewallRuleResponse.class) public class ListIpForwardingRulesCmd extends BaseListCmd { @@ -91,11 +92,12 @@ public class ListIpForwardingRulesCmd extends BaseListCmd { @Override public void execute(){ - List result = _rulesService.searchForIpForwardingRules(publicIpAddressId, id, vmId, this.getStartIndex(), this.getPageSizeVal(), this.getAccountName(), this.getDomainId()); + List result = _rulesService.searchStaticNatRules(publicIpAddressId, id, vmId, this.getStartIndex(), this.getPageSizeVal(), this.getAccountName(), this.getDomainId()); ListResponse response = new ListResponse(); List ipForwardingResponses = new ArrayList(); - for (PortForwardingRule rule : result) { - IpForwardingRuleResponse resp = _responseGenerator.createIpForwardingRuleResponse(rule); + for (FirewallRule rule : result) { + StaticNatRule staticNatRule = _rulesService.buildStaticNatRule(rule); + IpForwardingRuleResponse resp = _responseGenerator.createIpForwardingRuleResponse(staticNatRule); if (resp != null) { ipForwardingResponses.add(resp); } diff --git a/api/src/com/cloud/api/commands/RestartNetworkCmd.java b/api/src/com/cloud/api/commands/RestartNetworkCmd.java index 32a91b75afd..e619573e3bc 100644 --- a/api/src/com/cloud/api/commands/RestartNetworkCmd.java +++ b/api/src/com/cloud/api/commands/RestartNetworkCmd.java @@ -62,7 +62,12 @@ public class RestartNetworkCmd extends BaseAsyncCmd { } public long getEntityOwnerId() { - return _networkService.getNetwork(id).getAccountId(); + Network network = _networkService.getNetwork(id); + if (network == null) { + throw new InvalidParameterValueException("Networkd id=" + id + " doesn't exist"); + } else { + return _networkService.getNetwork(id).getAccountId(); + } } public Long getNetworkId() { diff --git a/api/src/com/cloud/network/lb/LoadBalancingRule.java b/api/src/com/cloud/network/lb/LoadBalancingRule.java index 0dfd4a06959..f6988a210fe 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRule.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRule.java @@ -135,9 +135,4 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer{ return revoked; } } - - @Override - public boolean isOneToOneNat() { - return false; - } } diff --git a/api/src/com/cloud/network/rules/FirewallRule.java b/api/src/com/cloud/network/rules/FirewallRule.java index 04780aa6993..a1cd05e8acc 100644 --- a/api/src/com/cloud/network/rules/FirewallRule.java +++ b/api/src/com/cloud/network/rules/FirewallRule.java @@ -25,6 +25,7 @@ public interface FirewallRule extends ControlledEntity { PortForwarding, LoadBalancing, Vpn, + StaticNat, } enum State { @@ -65,7 +66,5 @@ public interface FirewallRule extends ControlledEntity { long getNetworkId(); - boolean isOneToOneNat(); - long getSourceIpAddressId(); } diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java index b3ff6c16d4e..a538a069b9a 100644 --- a/api/src/com/cloud/network/rules/RulesService.java +++ b/api/src/com/cloud/network/rules/RulesService.java @@ -19,25 +19,23 @@ package com.cloud.network.rules; import java.util.List; -import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.api.commands.ListPortForwardingRulesCmd; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; public interface RulesService { - List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId); + List searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId); /** * Creates a port forwarding rule between two ip addresses or between * an ip address and a virtual machine. * @param rule rule to be created. * @param vmId vm to be linked to. If specified the destination ip address is ignored. - * @param isNat TODO * @return PortForwardingRule if created. * @throws NetworkRuleConflictException if conflicts in the network rules are detected. */ - PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean isNat) throws NetworkRuleConflictException; + PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException; /** * Revokes a port forwarding rule @@ -59,8 +57,15 @@ public interface RulesService { boolean disableOneToOneNat(long ipAddressId); - List buildPortForwardingTOrules(List pfRules); - PortForwardingRule getPortForwardigRule(long ruleId); + FirewallRule getFirewallRule(long ruleId); + + StaticNatRule createStaticNatRule(StaticNatRule rule) throws NetworkRuleConflictException; + + boolean revokeStaticNatRule(long ruleId, boolean apply); + + boolean applyStaticNatRules(long ipAdddressId, Account caller) throws ResourceUnavailableException; + + StaticNatRule buildStaticNatRule(FirewallRule rule); } diff --git a/api/src/com/cloud/network/rules/StaticNatRule.java b/api/src/com/cloud/network/rules/StaticNatRule.java new file mode 100644 index 00000000000..d236d2b7325 --- /dev/null +++ b/api/src/com/cloud/network/rules/StaticNatRule.java @@ -0,0 +1,48 @@ +/** + * 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.rules; + +import com.cloud.acl.ControlledEntity; + +public interface StaticNatRule extends ControlledEntity, FirewallRule{ + + long getId(); + + String getXid(); + + String getProtocol(); + + int getSourcePortStart(); + + int getSourcePortEnd(); + + Purpose getPurpose(); + + State getState(); + + long getAccountId(); + + long getDomainId(); + + long getNetworkId(); + + long getSourceIpAddressId(); + + String getDestIpAddress(); +} diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 08038ef149e..ba0a3f8c8b1 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -52,9 +52,12 @@ import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.network.HAProxyConfigurator; import com.cloud.network.LoadBalancerConfigurator; import com.cloud.utils.NumbersUtil; @@ -97,7 +100,9 @@ public class VirtualRoutingResource implements Manager { try { if (cmd instanceof SetPortForwardingRulesCommand ) { return execute((SetPortForwardingRulesCommand)cmd); - } else if (cmd instanceof LoadBalancerConfigCommand) { + } else if (cmd instanceof SetStaticNatRulesCommand){ + return execute((SetStaticNatRulesCommand)cmd); + }else if (cmd instanceof LoadBalancerConfigCommand) { return execute((LoadBalancerConfigCommand)cmd); } else if (cmd instanceof IPAssocCommand) { return execute((IPAssocCommand)cmd); @@ -126,28 +131,46 @@ public class VirtualRoutingResource implements Manager { for (PortForwardingRuleTO rule : cmd.getRules()) { String result = null; final Script command = new Script(_firewallPath, _timeout, s_logger); + command.add(routerIp); command.add(rule.revoked() ? "-D" : "-A"); - if (rule.isOneToOneNat()){ - //1:1 NAT needs instanceip;publicip;domrip;op - command.add(" -l ", rule.getSrcIp()); - command.add(" -r ", rule.getDstIp()); - command.add(" -P ", rule.getProtocol().toLowerCase()); - command.add(" -d ", rule.getStringDstPortRange()); - command.add(" -G ") ; - } else { - command.add("-P ", rule.getProtocol().toLowerCase()); - command.add("-l ", rule.getSrcIp()); - command.add("-p ", rule.getStringSrcPortRange()); - command.add("-r ", rule.getDstIp()); - command.add("-d ", rule.getStringDstPortRange()); - } + command.add("-P ", rule.getProtocol().toLowerCase()); + command.add("-l ", rule.getSrcIp()); + command.add("-p ", rule.getStringSrcPortRange()); + command.add("-r ", rule.getDstIp()); + command.add("-d ", rule.getStringDstPortRange()); + result = command.execute(); results[i++] = (!(result == null || result.isEmpty())) ? "Failed" : null; } return new SetPortForwardingRulesAnswer(cmd, results); } + + private Answer execute(SetStaticNatRulesCommand cmd) { + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + String[] results = new String[cmd.getRules().length]; + int i = 0; + for (StaticNatRuleTO rule : cmd.getRules()) { + String result = null; + final Script command = new Script(_firewallPath, _timeout, s_logger); + command.add(routerIp); + command.add(rule.revoked() ? "-D" : "-A"); + + //1:1 NAT needs instanceip;publicip;domrip;op + command.add(" -l ", rule.getSrcIp()); + command.add(" -r ", rule.getDstIp()); + command.add(" -P ", rule.getProtocol().toLowerCase()); + command.add(" -d ", rule.getStringSrcPortRange()); + command.add(" -G ") ; + + result = command.execute(); + results[i++] = (!(result == null || result.isEmpty())) ? "Failed" : null; + } + + return new SetStaticNatRulesAnswer(cmd, results); + } + private Answer execute(LoadBalancerConfigCommand cmd) { String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 1b797826f7b..ceffcd41833 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -133,6 +133,8 @@ import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; @@ -146,6 +148,7 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; @@ -375,7 +378,9 @@ public abstract class CitrixResourceBase implements ServerResource { return execute((CreateCommand) cmd); } else if (cmd instanceof SetPortForwardingRulesCommand) { return execute((SetPortForwardingRulesCommand) cmd); - } else if (cmd instanceof LoadBalancerConfigCommand) { + } else if (cmd instanceof SetStaticNatRulesCommand) { + return execute((SetStaticNatRulesCommand) cmd); + } else if (cmd instanceof LoadBalancerConfigCommand) { return execute((LoadBalancerConfigCommand) cmd); } else if (cmd instanceof IPAssocCommand) { return execute((IPAssocCommand) cmd); @@ -1158,32 +1163,42 @@ public abstract class CitrixResourceBase implements ServerResource { String[] results = new String[cmd.getRules().length]; int i = 0; for (PortForwardingRuleTO rule : cmd.getRules()) { - if (rule.isOneToOneNat()){ - //1:1 NAT needs instanceip;publicip;domrip;op - args += rule.revoked() ? " -D " : " -A "; - - args += " -l " + rule.getSrcIp(); - args += " -r " + rule.getDstIp(); - args += " -P " + rule.getProtocol().toLowerCase(); - args += " -d " + rule.getStringDstPortRange(); - args += " -G " ; + args += rule.revoked() ? " -D " : " -A "; + args += " -P " + rule.getProtocol().toLowerCase(); + args += " -l " + rule.getSrcIp(); + args += " -p " + rule.getStringSrcPortRange(); + args += " -r " + rule.getDstIp(); + args += " -d " + rule.getStringDstPortRange(); - } else { - args += rule.revoked() ? " -D " : " -A "; - - args += " -P " + rule.getProtocol().toLowerCase(); - args += " -l " + rule.getSrcIp(); - args += " -p " + rule.getStringSrcPortRange(); - args += " -r " + rule.getDstIp(); - args += " -d " + rule.getStringDstPortRange(); - - } String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args); results[i++] = (result == null || result.isEmpty()) ? "Failed" : null; } return new SetPortForwardingRulesAnswer(cmd, results); } + + protected SetStaticNatRulesAnswer execute(SetStaticNatRulesCommand cmd) { + Connection conn = getConnection(); + + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + String args = routerIp; + String[] results = new String[cmd.getRules().length]; + int i = 0; + for (StaticNatRuleTO rule : cmd.getRules()) { + //1:1 NAT needs instanceip;publicip;domrip;op + args += rule.revoked() ? " -D " : " -A "; + args += " -l " + rule.getSrcIp(); + args += " -r " + rule.getDstIp(); + args += " -P " + rule.getProtocol().toLowerCase(); + args += " -d " + rule.getStringSrcPortRange(); + args += " -G " ; + + String result = callHostPlugin(conn, "vmops", "setFirewallRule", "args", args); + results[i++] = (result == null || result.isEmpty()) ? "Failed" : null; + } + + return new SetStaticNatRulesAnswer(cmd, results); + } protected Answer execute(final LoadBalancerConfigCommand cmd) { Connection conn = getConnection(); diff --git a/core/src/com/cloud/network/HAProxyConfigurator.java b/core/src/com/cloud/network/HAProxyConfigurator.java index 1fe17880039..23d35f81364 100644 --- a/core/src/com/cloud/network/HAProxyConfigurator.java +++ b/core/src/com/cloud/network/HAProxyConfigurator.java @@ -191,35 +191,6 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { private String getBlankLine() { return new String("\t "); } - - @Override - public String[][] generateFwRules(List fwRules) { - String [][] result = new String [2][]; - Set toAdd = new HashSet(); - Set toRemove = new HashSet(); - - for (int i = 0; i < fwRules.size(); i++) { - PortForwardingRuleTO rule = fwRules.get(i); - - String vlanNetmask = rule.getVlanNetmask(); - - StringBuilder sb = new StringBuilder(); - sb.append(rule.getSrcIp()).append(":"); - sb.append(rule.getSrcPortRange()[0]).append(":"); - sb.append(vlanNetmask); - String lbRuleEntry = sb.toString(); - if (!rule.revoked()) { - toAdd.add(lbRuleEntry); - } else { - toRemove.add(lbRuleEntry); - } - } - toRemove.removeAll(toAdd); - result[ADD] = toAdd.toArray(new String[toAdd.size()]); - result[REMOVE] = toRemove.toArray(new String[toRemove.size()]); - - return result; - } @Override public String[] generateConfiguration(LoadBalancerConfigCommand lbCmd) { diff --git a/core/src/com/cloud/network/LoadBalancerConfigurator.java b/core/src/com/cloud/network/LoadBalancerConfigurator.java index ad2b3d7ddda..e4360bae449 100644 --- a/core/src/com/cloud/network/LoadBalancerConfigurator.java +++ b/core/src/com/cloud/network/LoadBalancerConfigurator.java @@ -32,7 +32,6 @@ public interface LoadBalancerConfigurator { public final static int REMOVE = 1; public String [] generateConfiguration(List fwRules); - public String [][] generateFwRules(List fwRules); public String [] generateConfiguration(LoadBalancerConfigCommand lbCmd); public String [][] generateFwRules(LoadBalancerConfigCommand lbCmd); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index e186d9a96d3..cc115fbb03e 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -109,6 +109,7 @@ import com.cloud.network.router.VirtualRouter; 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.IngressRule; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupRules; @@ -951,7 +952,7 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public IpForwardingRuleResponse createIpForwardingRuleResponse(PortForwardingRule fwRule) { + public IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule) { IpForwardingRuleResponse response = new IpForwardingRuleResponse(); response.setId(fwRule.getId()); response.setProtocol(fwRule.getProtocol()); @@ -960,8 +961,8 @@ public class ApiResponseHelper implements ResponseGenerator { response.setPublicIpAddressId(ip.getId()); response.setPublicIpAddress(ip.getAddress().addr()); - if (ip != null && fwRule.getDestinationIpAddress() != null) { - UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId()); + if (ip != null && fwRule.getDestIpAddress() != null) { + UserVm vm = ApiDBUtils.findUserVmById(ip.getAssociatedWithVmId()); if(vm != null){//vm might be destroyed response.setVirtualMachineId(vm.getId()); response.setVirtualMachineName(vm.getName()); diff --git a/server/src/com/cloud/network/LoadBalancerVO.java b/server/src/com/cloud/network/LoadBalancerVO.java index 2a642dfa690..75a085913c0 100644 --- a/server/src/com/cloud/network/LoadBalancerVO.java +++ b/server/src/com/cloud/network/LoadBalancerVO.java @@ -53,7 +53,7 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer { } public LoadBalancerVO(String xId, String name, String description, long srcIpId, int srcPort, int dstPort, String algorithm, long networkId, long accountId, long domainId) { - super(xId, srcIpId, srcPort, NetUtils.TCP_PROTO, networkId, accountId, domainId, Purpose.LoadBalancing, false); + super(xId, srcIpId, srcPort, NetUtils.TCP_PROTO, networkId, accountId, domainId, Purpose.LoadBalancing); this.name = name; this.description = description; this.algorithm = algorithm; diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 3c0018a22d1..eb429bec2f1 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -81,10 +81,11 @@ public interface NetworkManager extends NetworkService { * Do all of the work of releasing public ip addresses. Note that * if this method fails, there can be side effects. * @param userId + * @param caller TODO * @param ipAddress * @return true if it did; false if it didn't */ - public boolean releasePublicIpAddress(long id, long ownerId, long userId); + public boolean releasePublicIpAddress(long id, long userId, Account caller); /** * Lists IP addresses that belong to VirtualNetwork VLANs @@ -111,6 +112,8 @@ public interface NetworkManager extends NetworkService { List getNics(VirtualMachine vm); + List getNicsIncludingRemoved(VirtualMachine vm); + List getNicProfiles(VirtualMachine vm); List getAccountsUsingNetwork(long configurationId); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index b5fde732429..5e39c719036 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -608,9 +608,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public boolean releasePublicIpAddress(long addrId, long ownerId, long userId) { + public boolean releasePublicIpAddress(long addrId, long userId, Account caller) { IPAddressVO ip = _ipAddressDao.markAsUnavailable(addrId); - assert (ip != null) : "Unable to mark the ip address id=" + addrId + " owned by " + ownerId + " as unavailable."; + assert (ip != null) : "Unable to mark the ip address id=" + addrId + " owned by " + ip.getAccountId() + " as unavailable."; if (ip == null) { return true; } @@ -621,7 +621,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag boolean success = true; try { - if (!_rulesMgr.revokeAllRules(addrId, userId)) { + if (!_rulesMgr.revokeAllRules(addrId, userId, caller)) { s_logger.warn("Unable to revoke all the port forwarding rules for ip " + ip); success = false; } @@ -630,7 +630,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag success = false; } - if (!_lbMgr.removeAllLoadBalanacers(addrId)) { + if (!_lbMgr.removeAllLoadBalanacers(addrId, caller, userId)) { s_logger.warn("Unable to revoke all the load balancer rules for ip " + ip); success = false; } @@ -1072,7 +1072,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public void prepare(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - List nics = _nicDao.listBy(vmProfile.getId()); + List nics = _nicDao.listByVmId(vmProfile.getId()); for (NicVO nic : nics) { Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); NetworkGuru concierge = implemented.first(); @@ -1123,7 +1123,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) { - List nics = _nicDao.listBy(vm.getId()); + List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { NetworkVO network = _networksDao.findById(nic.getNetworkId()); NetworkOffering no = _configMgr.getNetworkOffering(network.getNetworkOfferingId()); @@ -1138,7 +1138,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public void release(VirtualMachineProfile vmProfile, boolean forced) { - List nics = _nicDao.listBy(vmProfile.getId()); + List nics = _nicDao.listByVmId(vmProfile.getId()); for (NicVO nic : nics) { NetworkVO network = _networksDao.findById(nic.getNetworkId()); if (nic.getState() == Nic.State.Reserved || nic.getState() == Nic.State.Reserving) { @@ -1167,7 +1167,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public List getNics(VirtualMachine vm) { - return _nicDao.listBy(vm.getId()); + return _nicDao.listByVmId(vm.getId()); + } + + @Override + public List getNicsIncludingRemoved(VirtualMachine vm) { + return _nicDao.listByVmIdIncludingRemoved(vm.getId()); } private Account findAccountByIpAddress(Long ipAddressId) { @@ -1180,7 +1185,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public List getNicProfiles(VirtualMachine vm) { - List nics = _nicDao.listBy(vm.getId()); + List nics = _nicDao.listByVmId(vm.getId()); List profiles = new ArrayList(); if (nics != null) { @@ -1265,7 +1270,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new PermissionDeniedException("Ip address id=" + ipAddressId + " belongs to Account wide IP pool and cannot be disassociated"); } - return releasePublicIpAddress(ipAddressId, accountId, userId); + return releasePublicIpAddress(ipAddressId, userId, caller); } catch (PermissionDeniedException pde) { throw pde; @@ -1333,7 +1338,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public void cleanupNics(VirtualMachineProfile vm) { - List nics = _nicDao.listBy(vm.getId()); + List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { nic.setState(Nic.State.Deallocating); _nicDao.update(nic.getId(), nic); @@ -1938,7 +1943,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag //apply port forwarding rules if (!_rulesMgr.applyPortForwardingRulesForNetwork(networkId, false, context.getAccount())) { - s_logger.warn("Failed to reapply firewall rule(s) as a part of network id=" + networkId + " restart"); + s_logger.warn("Failed to reapply port forwarding rule(s) as a part of network id=" + networkId + " restart"); + } + + //apply static nat rules + if (!_rulesMgr.applyStaticNatRulesForNetwork(networkId, false, context.getAccount())) { + s_logger.warn("Failed to reapply static nat rule(s) as a part of network id=" + networkId + " restart"); } //apply load balancer rules @@ -2066,7 +2076,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public List listNetworksUsedByVm(long vmId, boolean isSystem) { List networks = new ArrayList(); - List nics = _nicDao.listBy(vmId); + List nics = _nicDao.listByVmId(vmId); if (nics != null) { for (Nic nic : nics) { NetworkVO network = _networksDao.findByIdIncludingRemoved(nic.getNetworkId()); @@ -2173,7 +2183,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public Nic getDefaultNic(long vmId) { - List nics = _nicDao.listBy(vmId); + List nics = _nicDao.listByVmId(vmId); Nic defaultNic = null; if (nics != null) { for (Nic nic : nics) { diff --git a/server/src/com/cloud/network/dao/FirewallRulesDao.java b/server/src/com/cloud/network/dao/FirewallRulesDao.java index 07f398fd8a7..595509cb84e 100644 --- a/server/src/com/cloud/network/dao/FirewallRulesDao.java +++ b/server/src/com/cloud/network/dao/FirewallRulesDao.java @@ -28,7 +28,7 @@ import com.cloud.utils.db.GenericDao; * Data Access Object for user_ip_address and ip_forwarding tables */ public interface FirewallRulesDao extends GenericDao { - List listByIpAndNotRevoked(long ipAddressId, Boolean isOneToOneNat); + List listByIpAndNotRevoked(long ipAddressId, FirewallRule.Purpose purpose); boolean setStateToAdd(FirewallRuleVO rule); @@ -37,32 +37,9 @@ public interface FirewallRulesDao extends GenericDao { boolean releasePorts(long ipAddressId, String protocol, FirewallRule.Purpose purpose, int[] ports); List listByIpAndPurpose(long ipAddressId, FirewallRule.Purpose purpose); - -// public List listIPForwarding(String publicIPAddress, boolean forwarding); -// public List listIPForwarding(String publicIPAddress, String port, boolean forwarding); -// -// public List listIPForwarding(long userId); -// public List listIPForwarding(long userId, long dcId); -// public void deleteIPForwardingByPublicIpAddress(String ipAddress); -// public List listIPForwarding(String publicIPAddress); -// public List listIPForwardingForUpdate(String publicIPAddress); -// public void disableIPForwarding(String publicIPAddress); -// public List listIPForwardingForUpdate(String publicIp, boolean fwding); -// public List listIPForwardingForUpdate(String publicIp, String publicPort, String proto); -// public List listIPForwardingByPortAndProto(String publicIp, String publicPort, String proto); -// -// public List listLoadBalanceRulesForUpdate(String publicIp, String publicPort, String algo); -// public List listIpForwardingRulesForLoadBalancers(String publicIp); -// -// -// public List listRulesExcludingPubIpPort(String publicIpAddress, long securityGroupId); -// public List listBySecurityGroupId(long securityGroupId); -// public List listByLoadBalancerId(long loadBalancerId); -// public List listForwardingByPubAndPrivIp(boolean forwarding, String publicIPAddress, String privateIp); -// public PortForwardingRuleVO findByGroupAndPrivateIp(long groupId, String privateIp, boolean forwarding); -// public List findByPublicIpPrivateIpForNatRule(String publicIp,String privateIp); -// public List listByPrivateIp(String privateIp); -// public boolean isPublicIpOneToOneNATted(String publicIp); -// void deleteIPForwardingByPublicIpAndPort(String ipAddress, String port); -// public List listIPForwardingForLB(long userId, long dcId); + + List listByNetworkIdAndPurpose(long networkId, FirewallRule.Purpose purpose); + + List listStaticNatByVmId(long vmId); + } diff --git a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java index 622e4a2984c..2d8d09bcfe7 100644 --- a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java +++ b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java @@ -24,15 +24,18 @@ import javax.ejb.Local; import org.apache.log4j.Logger; +import com.cloud.network.IPAddressVO; import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.State; import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.net.Ip; @Local(value=FirewallRulesDao.class) @DB(txn=false) public class FirewallRulesDaoImpl extends GenericDaoBase implements FirewallRulesDao { @@ -41,6 +44,7 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder IpNotRevokedSearch; protected final SearchBuilder ReleaseSearch; + protected SearchBuilder VmSearch; protected FirewallRulesDaoImpl() { super(); @@ -59,7 +63,7 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i IpNotRevokedSearch = createSearchBuilder(); IpNotRevokedSearch.and("ipId", IpNotRevokedSearch.entity().getSourceIpAddressId(), Op.EQ); IpNotRevokedSearch.and("state", IpNotRevokedSearch.entity().getState(), Op.NEQ); - IpNotRevokedSearch.and("oneToOneNat", IpNotRevokedSearch.entity().isOneToOneNat(), Op.EQ); + IpNotRevokedSearch.and("purpose", IpNotRevokedSearch.entity().getPurpose(), Op.EQ); IpNotRevokedSearch.done(); ReleaseSearch = createSearchBuilder(); @@ -84,7 +88,7 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i @Override public List listByIpAndPurpose(long ipId, FirewallRule.Purpose purpose) { - SearchCriteria sc = ReleaseSearch.create(); + SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("ipId", ipId); sc.setParameters("purpose", purpose); @@ -92,17 +96,28 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i } @Override - public List listByIpAndNotRevoked(long ipId, Boolean isOneToOneNat) { + public List listByIpAndNotRevoked(long ipId, FirewallRule.Purpose purpose) { SearchCriteria sc = IpNotRevokedSearch.create(); sc.setParameters("ipId", ipId); sc.setParameters("state", State.Revoke); - if (isOneToOneNat != null) { - sc.setParameters("oneToOneNat", isOneToOneNat); + + if (purpose != null) { + sc.setParameters("purpose", purpose); } return listBy(sc); } - + + + @Override + public List listByNetworkIdAndPurpose(long networkId, FirewallRule.Purpose purpose) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("purpose", purpose); + sc.setParameters("networkId", networkId); + + return listBy(sc); + } + @Override public boolean setStateToAdd(FirewallRuleVO rule) { SearchCriteria sc = AllFieldsSearch.create(); @@ -120,388 +135,26 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i return update(rule.getId(), rule); } - - -// public static String SELECT_IP_FORWARDINGS_BY_USERID_SQL = null; -// public static String SELECT_IP_FORWARDINGS_BY_USERID_AND_DCID_SQL = null; -// public static String SELECT_LB_FORWARDINGS_BY_USERID_AND_DCID_SQL = null; -// -// -// public static final String DELETE_IP_FORWARDING_BY_IPADDRESS_SQL = "DELETE FROM ip_forwarding WHERE public_ip_address = ?"; -// public static final String DELETE_IP_FORWARDING_BY_IP_PORT_SQL = "DELETE FROM ip_forwarding WHERE public_ip_address = ? and public_port = ?"; -// -// public static final String DISABLE_IP_FORWARDING_BY_IPADDRESS_SQL = "UPDATE ip_forwarding set enabled=0 WHERE public_ip_address = ?"; -// -// -// protected SearchBuilder FWByIPAndForwardingSearch; -// protected SearchBuilder FWByIPPortAndForwardingSearch; -// protected SearchBuilder FWByIPPortProtoSearch; -// protected SearchBuilder FWByIPPortAlgoSearch; -// protected SearchBuilder FWByPrivateIPSearch; -// protected SearchBuilder RulesExcludingPubIpPort; -// protected SearchBuilder FWByGroupId; -// protected SearchBuilder FWByIpForLB; -// -// protected SearchBuilder FWByGroupAndPrivateIp; -// protected SearchBuilder FWByPrivateIpPrivatePortPublicIpPublicPortSearch; -// protected SearchBuilder OneToOneNATSearch; -// -// -// protected FirewallRulesDaoImpl() { -// } -// -// @Override -// public boolean configure(String name, Map params) throws ConfigurationException { -// if (!super.configure(name, params)) { -// return false; -// } -// -// SELECT_IP_FORWARDINGS_BY_USERID_SQL = buildSelectByUserIdSql(); -// if (s_logger.isDebugEnabled()) { -// s_logger.debug(SELECT_IP_FORWARDINGS_BY_USERID_SQL); -// } -// -// SELECT_IP_FORWARDINGS_BY_USERID_AND_DCID_SQL = buildSelectByUserIdAndDatacenterIdSql(); -// if (s_logger.isDebugEnabled()) { -// s_logger.debug(SELECT_IP_FORWARDINGS_BY_USERID_AND_DCID_SQL); -// } -// -// SELECT_LB_FORWARDINGS_BY_USERID_AND_DCID_SQL = buildSelectByUserIdAndDatacenterIdForLBSql(); -// if (s_logger.isDebugEnabled()) { -// s_logger.debug(SELECT_LB_FORWARDINGS_BY_USERID_AND_DCID_SQL); -// } -// -// -// FWByIPSearch = createSearchBuilder(); -// FWByIPSearch.and("publicIpAddress", FWByIPSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIPSearch.done(); -// -// FWByIPAndForwardingSearch = createSearchBuilder(); -// FWByIPAndForwardingSearch.and("publicIpAddress", FWByIPAndForwardingSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIPAndForwardingSearch.and("forwarding", FWByIPAndForwardingSearch.entity().isForwarding(), SearchCriteria.Op.EQ); -// FWByIPAndForwardingSearch.done(); -// -// FWByIPPortAndForwardingSearch = createSearchBuilder(); -// FWByIPPortAndForwardingSearch.and("publicIpAddress", FWByIPPortAndForwardingSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIPPortAndForwardingSearch.and("publicPort", FWByIPPortAndForwardingSearch.entity().getSourcePort(), SearchCriteria.Op.EQ); -// FWByIPPortAndForwardingSearch.and("forwarding", FWByIPPortAndForwardingSearch.entity().isForwarding(), SearchCriteria.Op.EQ); -// FWByIPPortAndForwardingSearch.done(); -// -// FWByIPPortProtoSearch = createSearchBuilder(); -// FWByIPPortProtoSearch.and("publicIpAddress", FWByIPPortProtoSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIPPortProtoSearch.and("publicPort", FWByIPPortProtoSearch.entity().getSourcePort(), SearchCriteria.Op.EQ); -// FWByIPPortProtoSearch.and("protocol", FWByIPPortProtoSearch.entity().getProtocol(), SearchCriteria.Op.EQ); -// FWByIPPortProtoSearch.done(); -// -// FWByIPPortAlgoSearch = createSearchBuilder(); -// FWByIPPortAlgoSearch.and("publicIpAddress", FWByIPPortAlgoSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIPPortAlgoSearch.and("publicPort", FWByIPPortAlgoSearch.entity().getSourcePort(), SearchCriteria.Op.EQ); -// FWByIPPortAlgoSearch.and("algorithm", FWByIPPortAlgoSearch.entity().getAlgorithm(), SearchCriteria.Op.EQ); -// FWByIPPortAlgoSearch.done(); -// -// FWByPrivateIPSearch = createSearchBuilder(); -// FWByPrivateIPSearch.and("privateIpAddress", FWByPrivateIPSearch.entity().getDestinationIpAddress(), SearchCriteria.Op.EQ); -// FWByPrivateIPSearch.done(); -// -// RulesExcludingPubIpPort = createSearchBuilder(); -// RulesExcludingPubIpPort.and("publicIpAddress", RulesExcludingPubIpPort.entity().getDestinationIpAddress(), SearchCriteria.Op.EQ); -// RulesExcludingPubIpPort.and("groupId", RulesExcludingPubIpPort.entity().getGroupId(), SearchCriteria.Op.NEQ); -// RulesExcludingPubIpPort.and("forwarding", RulesExcludingPubIpPort.entity().isForwarding(), SearchCriteria.Op.EQ); -// RulesExcludingPubIpPort.done(); -// -// FWByGroupId = createSearchBuilder(); -// FWByGroupId.and("groupId", FWByGroupId.entity().getGroupId(), SearchCriteria.Op.EQ); -// FWByGroupId.and("forwarding", FWByGroupId.entity().isForwarding(), SearchCriteria.Op.EQ); -// FWByGroupId.done(); -// -// FWByGroupAndPrivateIp = createSearchBuilder(); -// FWByGroupAndPrivateIp.and("groupId", FWByGroupAndPrivateIp.entity().getGroupId(), SearchCriteria.Op.EQ); -// FWByGroupAndPrivateIp.and("privateIpAddress", FWByGroupAndPrivateIp.entity().getDestinationIpAddress(), SearchCriteria.Op.EQ); -// FWByGroupAndPrivateIp.and("forwarding", FWByGroupAndPrivateIp.entity().isForwarding(), SearchCriteria.Op.EQ); -// FWByGroupAndPrivateIp.done(); -// -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch = createSearchBuilder(); -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("publicIpAddress", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("privateIpAddress", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getDestinationIpAddress(), SearchCriteria.Op.EQ); -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("privatePort", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getDestinationPort(), SearchCriteria.Op.NULL); -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch.and("publicPort", FWByPrivateIpPrivatePortPublicIpPublicPortSearch.entity().getSourcePort(), SearchCriteria.Op.NULL); -// FWByPrivateIpPrivatePortPublicIpPublicPortSearch.done(); -// -// OneToOneNATSearch = createSearchBuilder(); -// OneToOneNATSearch.and("publicIpAddress", OneToOneNATSearch.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// OneToOneNATSearch.and("protocol", OneToOneNATSearch.entity().getProtocol(), SearchCriteria.Op.EQ); -// OneToOneNATSearch.done(); -// -// FWByIpForLB = createSearchBuilder(); -// FWByIpForLB.and("publicIpAddress", FWByIpForLB.entity().getSourceIpAddress(), SearchCriteria.Op.EQ); -// FWByIpForLB.and("groupId", FWByIpForLB.entity().getGroupId(), SearchCriteria.Op.NNULL); -// FWByIpForLB.and("forwarding", FWByIpForLB.entity().isForwarding(), SearchCriteria.Op.EQ); -// FWByIpForLB.done(); -// -// return true; -// } -// -// protected String buildSelectByUserIdSql() { -// StringBuilder sql = createPartialSelectSql(null, true); -// sql.insert(sql.length() - 6, ", user_ip_address "); -// sql.append("ip_forwarding.public_ip_address = user_ip_address.public_ip_address AND user_ip_address.account_id = ?"); -// -// return sql.toString(); -// } -// -// protected String buildSelectByUserIdAndDatacenterIdSql() { -// return "SELECT i.id, i.group_id, i.public_ip_address, i.public_port, i.private_ip_address, i.private_port, i.enabled, i.protocol, i.forwarding, i.algorithm FROM ip_forwarding i, user_ip_address u WHERE i.public_ip_address=u.public_ip_address AND u.account_id=? AND u.data_center_id=?"; -// } -// -// protected String buildSelectByUserIdAndDatacenterIdForLBSql() { -// return "SELECT i.id, i.group_id, i.public_ip_address, i.public_port, i.private_ip_address, i.private_port, i.enabled, i.protocol, i.forwarding, i.algorithm FROM ip_forwarding i, user_ip_address u WHERE i.public_ip_address=u.public_ip_address AND u.account_id=? AND u.data_center_id=? AND i.group_id is not NULL"; -// } -// -// public List listIPForwarding(String publicIPAddress, boolean forwarding) { -// SearchCriteria sc = FWByIPAndForwardingSearch.create(); -// sc.setParameters("publicIpAddress", publicIPAddress); -// sc.setParameters("forwarding", forwarding); -// return listBy(sc); -// } -// -// @Override -// public List listIPForwarding(long userId) { -// Transaction txn = Transaction.currentTxn(); -// List forwardings = new ArrayList(); -// PreparedStatement pstmt = null; -// try { -// pstmt = txn.prepareAutoCloseStatement(SELECT_IP_FORWARDINGS_BY_USERID_SQL); -// pstmt.setLong(1, userId); -// ResultSet rs = pstmt.executeQuery(); -// while (rs.next()) { -// forwardings.add(toEntityBean(rs, false)); -// } -// } catch (Exception e) { -// s_logger.warn(e); -// } -// return forwardings; -// } -// -// public List listIPForwarding(long userId, long dcId) { -// Transaction txn = Transaction.currentTxn(); -// List forwardings = new ArrayList(); -// PreparedStatement pstmt = null; -// try { -// pstmt = txn.prepareAutoCloseStatement(SELECT_IP_FORWARDINGS_BY_USERID_AND_DCID_SQL); -// pstmt.setLong(1, userId); -// pstmt.setLong(2, dcId); -// ResultSet rs = pstmt.executeQuery(); -// while (rs.next()) { -// forwardings.add(toEntityBean(rs, false)); -// } -// } catch (Exception e) { -// s_logger.warn(e); -// } -// return forwardings; -// } -// -// @Override -// public void deleteIPForwardingByPublicIpAddress(String ipAddress) { -// Transaction txn = Transaction.currentTxn(); -// PreparedStatement pstmt = null; -// try { -// pstmt = txn.prepareAutoCloseStatement(DELETE_IP_FORWARDING_BY_IPADDRESS_SQL); -// pstmt.setString(1, ipAddress); -// pstmt.executeUpdate(); -// } catch (Exception e) { -// s_logger.warn(e); -// } -// } -// -// @Override -// public void deleteIPForwardingByPublicIpAndPort(String ipAddress, String port) { -// Transaction txn = Transaction.currentTxn(); -// PreparedStatement pstmt = null; -// try { -// pstmt = txn.prepareAutoCloseStatement(DELETE_IP_FORWARDING_BY_IP_PORT_SQL); -// pstmt.setString(1, ipAddress); -// pstmt.setString(2, port); -// -// pstmt.executeUpdate(); -// } catch (Exception e) { -// s_logger.warn(e); -// } -// } -// -// @Override -// public List listIPForwarding(String publicIPAddress) { -// SearchCriteria sc = FWByIPSearch.create(); -// sc.setParameters("publicIpAddress", publicIPAddress); -// return listBy(sc); -// } -// -// @Override -// public List listIPForwardingForUpdate(String publicIPAddress) { -// SearchCriteria sc = FWByIPSearch.create(); -// sc.setParameters("publicIpAddress", publicIPAddress); -// return listBy(sc, null); -// } -// -// @Override -// public List listIPForwardingForUpdate(String publicIp, boolean fwding) { -// SearchCriteria sc = FWByIPAndForwardingSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("forwarding", fwding); -// return search(sc, null); -// } -// -// @Override -// public List listIPForwardingForUpdate(String publicIp, -// String publicPort, String proto) { -// SearchCriteria sc = FWByIPPortProtoSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("publicPort", publicPort); -// sc.setParameters("protocol", proto); -// return search(sc, null); -// } -// -// @Override -// public List listLoadBalanceRulesForUpdate(String publicIp, -// String publicPort, String algo) { -// SearchCriteria sc = FWByIPPortAlgoSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("publicPort", publicPort); -// sc.setParameters("algorithm", algo); -// return listBy(sc, null); -// } -// -// @Override -// public List listIPForwarding(String publicIPAddress, -// String port, boolean forwarding) { -// SearchCriteria sc = FWByIPPortAndForwardingSearch.create(); -// sc.setParameters("publicIpAddress", publicIPAddress); -// sc.setParameters("publicPort", port); -// sc.setParameters("forwarding", forwarding); -// -// return listBy(sc); -// } -// -// @Override -// public void disableIPForwarding(String publicIPAddress) { -// Transaction txn = Transaction.currentTxn(); -// PreparedStatement pstmt = null; -// try { -// txn.start(); -// pstmt = txn.prepareAutoCloseStatement(DISABLE_IP_FORWARDING_BY_IPADDRESS_SQL); -// pstmt.setString(1, publicIPAddress); -// pstmt.executeUpdate(); -// txn.commit(); -// } catch (Exception e) { -// txn.rollback(); -// throw new CloudRuntimeException("DB Exception ", e); -// } -// } -// -// @Override -// public List listRulesExcludingPubIpPort(String publicIpAddress, long securityGroupId) { -// SearchCriteria sc = RulesExcludingPubIpPort.create(); -// sc.setParameters("publicIpAddress", publicIpAddress); -// sc.setParameters("groupId", securityGroupId); -// sc.setParameters("forwarding", false); -// return listBy(sc); -// } -// -// @Override -// public List listBySecurityGroupId(long securityGroupId) { -// SearchCriteria sc = FWByGroupId.create(); -// sc.setParameters("groupId", securityGroupId); -// sc.setParameters("forwarding", Boolean.TRUE); -// return listBy(sc); -// } -// -// @Override -// public List listForwardingByPubAndPrivIp(boolean forwarding, String publicIPAddress, String privateIp) { -// SearchCriteria sc = FWByIPAndForwardingSearch.create(); -// sc.setParameters("publicIpAddress", publicIPAddress); -// sc.setParameters("forwarding", forwarding); -// sc.addAnd("privateIpAddress", SearchCriteria.Op.EQ, privateIp); -// return listBy(sc); -// } -// -// @Override -// public List listByLoadBalancerId(long loadBalancerId) { -// SearchCriteria sc = FWByGroupId.create(); -// sc.setParameters("groupId", loadBalancerId); -// sc.setParameters("forwarding", Boolean.FALSE); -// return listBy(sc); -// } -// -// @Override -// public PortForwardingRuleVO findByGroupAndPrivateIp(long groupId, String privateIp, boolean forwarding) { -// SearchCriteria sc = FWByGroupAndPrivateIp.create(); -// sc.setParameters("groupId", groupId); -// sc.setParameters("privateIpAddress", privateIp); -// sc.setParameters("forwarding", forwarding); -// return findOneBy(sc); -// -// } -// -// @Override -// public List findByPublicIpPrivateIpForNatRule(String publicIp, String privateIp){ -// SearchCriteria sc = FWByPrivateIpPrivatePortPublicIpPublicPortSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("privateIpAddress", privateIp); -// return listBy(sc); -// } -// -// @Override -// public List listByPrivateIp(String privateIp) { -// SearchCriteria sc = FWByPrivateIPSearch.create(); -// sc.setParameters("privateIpAddress", privateIp); -// return listBy(sc); -// } -// -// @Override -// public List listIPForwardingByPortAndProto(String publicIp, -// String publicPort, String proto) { -// SearchCriteria sc = FWByIPPortProtoSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("publicPort", publicPort); -// sc.setParameters("protocol", proto); -// return search(sc, null); -// } -// -// @Override -// public boolean isPublicIpOneToOneNATted(String publicIp) { -// SearchCriteria sc = OneToOneNATSearch.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("protocol", NetUtils.NAT_PROTO); -// List rules = search(sc, null); -// if (rules.size() != 1) -// return false; -// return rules.get(1).getProtocol().equalsIgnoreCase(NetUtils.NAT_PROTO); -// } -// -// @Override -// public List listIpForwardingRulesForLoadBalancers( -// String publicIp) { -// SearchCriteria sc = FWByIpForLB.create(); -// sc.setParameters("publicIpAddress", publicIp); -// sc.setParameters("forwarding", false); -// return search(sc, null); -// } -// -// @Override -// public List listIPForwardingForLB(long userId, long dcId) { -// Transaction txn = Transaction.currentTxn(); -// List forwardings = new ArrayList(); -// PreparedStatement pstmt = null; -// try { -// pstmt = txn.prepareAutoCloseStatement(SELECT_LB_FORWARDINGS_BY_USERID_AND_DCID_SQL); -// pstmt.setLong(1, userId); -// pstmt.setLong(2, dcId); -// ResultSet rs = pstmt.executeQuery(); -// while (rs.next()) { -// forwardings.add(toEntityBean(rs, false)); -// } -// } catch (Exception e) { -// s_logger.warn(e); -// } -// return forwardings; -// } + @Override + public List listStaticNatByVmId(long vmId) { + IPAddressDao _ipDao = ComponentLocator.getLocator("management-server").getDao(IPAddressDao.class); + + if (VmSearch == null) { + SearchBuilder IpSearch = _ipDao.createSearchBuilder(); + IpSearch.and("associatedWithVmId", IpSearch.entity().getAssociatedWithVmId(), SearchCriteria.Op.EQ); + IpSearch.and("oneToOneNat", IpSearch.entity().isOneToOneNat(), SearchCriteria.Op.NNULL); + + VmSearch = createSearchBuilder(); + VmSearch.and("purpose", VmSearch.entity().getPurpose(), Op.EQ); + VmSearch.join("ipSearch", IpSearch, VmSearch.entity().getSourceIpAddressId(), IpSearch.entity().getId(), JoinBuilder.JoinType.INNER); + VmSearch.done(); + } + + SearchCriteria sc = VmSearch.create(); + sc.setParameters("purpose", Purpose.StaticNat); + sc.setJoinParameters("ipSearch", "associatedWithVmId", vmId); + + return listBy(sc); + } + } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index b7d0ed05666..e841e19c69e 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -167,38 +167,14 @@ public class VirtualRouterElement extends DhcpElement implements NetworkElement, long networkId = config.getId(); DomainRouterVO router = _routerDao.findByNetwork(networkId); if (router == null) { - s_logger.warn("Unable to apply firewall rules, virtual router doesn't exist in the network " + config.getId()); - throw new CloudRuntimeException("Unable to apply firewall rules"); + s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual router doesn't exist in the network " + config.getId()); + return true; } - if (router.getState() == State.Running) { - if (rules != null && !rules.isEmpty()) { - if (rules.get(0).getPurpose() == Purpose.LoadBalancing) { - //for load balancer we have to resend all lb rules for the network - List lbs = _lbDao.listByNetworkId(config.getId()); - List lbRules = new ArrayList(); - for (LoadBalancerVO lb : lbs) { - List dstList = _lbMgr.getExistingDestinations(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); - lbRules.add(loadBalancing); - } - - return _routerMgr.applyLBRules(config, lbRules); - } else if (rules.get(0).getPurpose() == Purpose.PortForwarding) { - return _routerMgr.applyPortForwardingRules(config, _rulesMgr.buildPortForwardingTOrules((List)rules)); - } - } else { - return true; - } - } else if (router.getState() == State.Stopped || router.getState() == State.Stopping){ - s_logger.debug("Router is in " + router.getState() + ", so not sending apply firewall rules commands to the backend"); - return true; - } else { - s_logger.warn("Unable to apply firewall rules, virtual router is not in the right state " + router.getState()); - throw new CloudRuntimeException("Unable to apply firewall rules, domR is not in right state " + router.getState()); - } - } - return false; + return _routerMgr.applyFirewallRules(config, rules); + } else { + return true; + } } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java index b588eec90cd..0bb1325ae6d 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java @@ -21,9 +21,10 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.user.Account; public interface LoadBalancingRulesManager extends LoadBalancingRulesService { - boolean removeAllLoadBalanacers(long ipId); + boolean removeAllLoadBalanacers(long ipId, Account caller, long callerUserId); List getExistingDestinations(long lbId); /** diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index beaf00d8e08..c5173439537 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -270,18 +270,22 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, @Override @ActionEvent (eventType=EventTypes.EVENT_LOAD_BALANCER_DELETE, eventDescription="deleting load balancer", async=true) public boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply) { - return deleteLoadBalancerRuleInternal(loadBalancerId, apply); - } - - private boolean deleteLoadBalancerRuleInternal(long loadBalancerId, boolean apply) { - UserContext caller = UserContext.current(); + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); - LoadBalancerVO lb = _lbDao.findById(loadBalancerId); - if (lb == null) { - throw new InvalidParameterException("Invalid load balancer value: " + loadBalancerId); + LoadBalancerVO rule = _lbDao.findById(loadBalancerId); + if (rule == null) { + throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId); } - _accountMgr.checkAccess(caller.getCaller(), lb); + _accountMgr.checkAccess(caller, rule); + + return deleteLoadBalancerRule(loadBalancerId, apply, caller, ctx.getCallerUserId()); + } + + + private boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply, Account caller, long callerUserId) { + LoadBalancerVO lb = _lbDao.findById(loadBalancerId); lb.setState(FirewallRule.State.Revoke); _lbDao.persist(lb); @@ -430,17 +434,15 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, } @Override - public boolean removeAllLoadBalanacers(long ipId) { - List rules = _rulesDao.listByIpAndNotRevoked(ipId, null); + public boolean removeAllLoadBalanacers(long ipId, Account caller, long callerUserId) { + List rules = _rulesDao.listByIpAndNotRevoked(ipId, Purpose.LoadBalancing); if (rules != null) s_logger.debug("Found " + rules.size() + " lb rules to cleanup"); - for (FirewallRule rule : rules) { - if (rule.getPurpose() == Purpose.LoadBalancing) { - boolean result = deleteLoadBalancerRuleInternal(rule.getId(), true); - if (result == false) { - s_logger.warn("Unable to remove load balancer rule " + rule.getId()); - return false; - } + for (FirewallRule rule : rules) { + boolean result = deleteLoadBalancerRule(rule.getId(), true, caller, callerUserId); + if (result == false) { + s_logger.warn("Unable to remove load balancer rule " + rule.getId()); + return false; } } return true; @@ -521,685 +523,6 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, return lb; } -// @Override @DB -// public boolean removeFromLoadBalancer(RemoveFromLoadBalancerRuleCmd cmd) throws InvalidParameterValueException { -// -// Long userId = UserContext.current().getUserId(); -// Account account = UserContext.current().getAccount(); -// Long loadBalancerId = cmd.getId(); -// Long vmInstanceId = cmd.getVirtualMachineId(); -// List instanceIds = cmd.getVirtualMachineIds(); -// -// if ((vmInstanceId == null) && (instanceIds == null)) { -// throw new ServerApiException(BaseCmd.PARAM_ERROR, "No virtual machine id specified."); -// } -// -// // if a single instanceId was given, add it to the list so we can always just process the list if instanceIds -// if (instanceIds == null) { -// instanceIds = new ArrayList(); -// instanceIds.add(vmInstanceId); -// } -// -// if (userId == null) { -// userId = Long.valueOf(1); -// } -// -// LoadBalancerVO loadBalancer = _loadBalancerDao.findById(Long.valueOf(loadBalancerId)); -// -// if (loadBalancer == null) { -// throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find load balancer rule with id " + loadBalancerId); -// } else if (account != null) { -// if (!isAdmin(account.getType()) && (loadBalancer.getAccountId() != account.getId())) { -// throw new ServerApiException(BaseCmd.PARAM_ERROR, "Account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName() + -// " (id:" + loadBalancer.getId() + ")"); -// } else if (!_domainDao.isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) { -// throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid load balancer rule id (" + loadBalancer.getId() + ") given, unable to remove virtual machine instances."); -// } -// } -// -// Transaction txn = Transaction.currentTxn(); -// LoadBalancerVO loadBalancerLock = null; -// boolean success = true; -// try { -// -// IPAddressVO ipAddress = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// if (ipAddress == null) { -// return false; -// } -// -// DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId()); -// if (router == null) { -// return false; -// } -// -// txn.start(); -// for (Long instanceId : instanceIds) { -// UserVm userVm = _userVmDao.findById(instanceId); -// if (userVm == null) { -// s_logger.warn("Unable to find virtual machine with id " + instanceId); -// throw new InvalidParameterValueException("Unable to find virtual machine with id " + instanceId); -// } -// PortForwardingRuleVO fwRule = _rulesDao.findByGroupAndPrivateIp(loadBalancerId, userVm.getGuestIpAddress(), false); -// if (fwRule != null) { -// fwRule.setEnabled(false); -// _rulesDao.update(fwRule.getId(), fwRule); -// } -// } -// -// List allLbRules = new ArrayList(); -// IPAddressVO ipAddr = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// List ipAddrs = listPublicIpAddressesInVirtualNetwork(loadBalancer.getAccountId(), ipAddr.getDataCenterId(), null); -// for (IPAddressVO ipv : ipAddrs) { -// List rules = _rulesDao.listIPForwarding(ipv.getAddress(), false); -// allLbRules.addAll(rules); -// } -// -// updateFirewallRules(loadBalancer.getIpAddress(), allLbRules, router); -// -// // firewall rules are updated, lock the load balancer as mappings are updated -// loadBalancerLock = _loadBalancerDao.acquireInLockTable(loadBalancerId); -// if (loadBalancerLock == null) { -// s_logger.warn("removeFromLoadBalancer: failed to lock load balancer " + loadBalancerId + ", deleting mappings anyway..."); -// } -// -// // remove all the loadBalancer->VM mappings -// _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, Boolean.FALSE); -// -// // Save and create the event -// String description; -// String type = EventTypes.EVENT_NET_RULE_DELETE; -// String level = EventVO.LEVEL_INFO; -// -// for (PortForwardingRuleVO updatedRule : allLbRules) { -// if (!updatedRule.isEnabled()) { -// _rulesDao.remove(updatedRule.getId()); -// -// description = "deleted load balancer rule [" + updatedRule.getSourceIpAddress() + ":" + updatedRule.getSourcePort() + "]->[" -// + updatedRule.getDestinationIpAddress() + ":" + updatedRule.getDestinationPort() + "]" + " " + updatedRule.getProtocol(); -// -// EventUtils.saveEvent(userId, loadBalancer.getAccountId(), level, type, description); -// } -// } -// txn.commit(); -// } catch (Exception ex) { -// s_logger.warn("Failed to delete load balancing rule with exception: ", ex); -// success = false; -// txn.rollback(); -// } finally { -// if (loadBalancerLock != null) { -// _loadBalancerDao.releaseFromLockTable(loadBalancerId); -// } -// } -// return success; -// } -// -// @Override @DB -// public boolean deleteLoadBalancerRule(DeleteLoadBalancerRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{ -// Long loadBalancerId = cmd.getId(); -// Long userId = UserContext.current().getUserId(); -// Account account = UserContext.current().getAccount(); -// -// ///verify input parameters -// LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId); -// if (loadBalancer == null) { -// throw new InvalidParameterValueException ("Unable to find load balancer rule with id " + loadBalancerId); -// } -// -// if (account != null) { -// if (!isAdmin(account.getType())) { -// if (loadBalancer.getAccountId() != account.getId()) { -// throw new PermissionDeniedException("Account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName() + " (id:" + loadBalancerId + "), permission denied"); -// } -// } else if (!_domainDao.isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) { -// throw new PermissionDeniedException("Unable to delete load balancer rule " + loadBalancer.getName() + " (id:" + loadBalancerId + "), permission denied."); -// } -// } -// -// if (userId == null) { -// userId = Long.valueOf(1); -// } -// -// Transaction txn = Transaction.currentTxn(); -// LoadBalancerVO loadBalancerLock = null; -// try { -// -// IPAddressVO ipAddress = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// if (ipAddress == null) { -// return false; -// } -// -// DomainRouterVO router = _routerMgr.getRouter(ipAddress.getAccountId(), ipAddress.getDataCenterId()); -// List fwRules = _firewallRulesDao.listByLoadBalancerId(loadBalancerId); -// -// txn.start(); -// -// if ((fwRules != null) && !fwRules.isEmpty()) { -// for (PortForwardingRuleVO fwRule : fwRules) { -// fwRule.setEnabled(false); -// _firewallRulesDao.update(fwRule.getId(), fwRule); -// } -// -// List allLbRules = new ArrayList(); -// List ipAddrs = listPublicIpAddressesInVirtualNetwork(loadBalancer.getAccountId(), ipAddress.getDataCenterId(), null); -// for (IPAddressVO ipv : ipAddrs) { -// List rules = _firewallRulesDao.listIPForwarding(ipv.getAddress(), false); -// allLbRules.addAll(rules); -// } -// -// updateFirewallRules(loadBalancer.getIpAddress(), allLbRules, router); -// -// // firewall rules are updated, lock the load balancer as the mappings are updated -// loadBalancerLock = _loadBalancerDao.acquireInLockTable(loadBalancerId); -// if (loadBalancerLock == null) { -// s_logger.warn("deleteLoadBalancer: failed to lock load balancer " + loadBalancerId + ", deleting mappings anyway..."); -// } -// -// // remove all loadBalancer->VM mappings -// List lbVmMap = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId); -// if (lbVmMap != null && !lbVmMap.isEmpty()) { -// for (LoadBalancerVMMapVO lb : lbVmMap) { -// _loadBalancerVMMapDao.remove(lb.getId()); -// } -// } -// -// // Save and create the event -// String description; -// String type = EventTypes.EVENT_NET_RULE_DELETE; -// String ruleName = "load balancer"; -// String level = EventVO.LEVEL_INFO; -// Account accountOwner = _accountDao.findById(loadBalancer.getAccountId()); -// -// for (PortForwardingRuleVO updatedRule : fwRules) { -// _firewallRulesDao.remove(updatedRule.getId()); -// -// description = "deleted " + ruleName + " rule [" + updatedRule.getSourceIpAddress() + ":" + updatedRule.getSourcePort() + "]->[" -// + updatedRule.getDestinationIpAddress() + ":" + updatedRule.getDestinationPort() + "]" + " " + updatedRule.getProtocol(); -// -// EventUtils.saveEvent(userId, accountOwner.getId(), level, type, description); -// } -// } -// -// txn.commit(); -// } catch (Exception ex) { -// txn.rollback(); -// s_logger.error("Unexpected exception deleting load balancer " + loadBalancerId, ex); -// return false; -// } finally { -// if (loadBalancerLock != null) { -// _loadBalancerDao.releaseFromLockTable(loadBalancerId); -// } -// } -// -// boolean success = _loadBalancerDao.remove(loadBalancerId); -// -// // save off an event for removing the load balancer -// EventVO event = new EventVO(); -// event.setUserId(userId); -// event.setAccountId(loadBalancer.getAccountId()); -// event.setType(EventTypes.EVENT_LOAD_BALANCER_DELETE); -// if (success) { -// event.setLevel(EventVO.LEVEL_INFO); -// String params = "id="+loadBalancer.getId(); -// event.setParameters(params); -// event.setDescription("Successfully deleted load balancer " + loadBalancer.getName() + " (id:" + loadBalancer.getId() + ")"); -// } else { -// event.setLevel(EventVO.LEVEL_ERROR); -// event.setDescription("Failed to delete load balancer " + loadBalancer.getName() + " (id:" + loadBalancer.getId() + ")"); -// } -// _eventDao.persist(event); -// return success; -// } -// @Override @DB -// public boolean assignToLoadBalancer(AssignToLoadBalancerRuleCmd cmd) throws NetworkRuleConflictException { -// Long loadBalancerId = cmd.getLoadBalancerId(); -// Long instanceIdParam = cmd.getVirtualMachineId(); -// List instanceIds = cmd.getVirtualMachineIds(); -// -// if ((instanceIdParam == null) && (instanceIds == null)) { -// throw new InvalidParameterValueException("Unable to assign to load balancer " + loadBalancerId + ", no instance id is specified."); -// } -// -// if ((instanceIds == null) && (instanceIdParam != null)) { -// instanceIds = new ArrayList(); -// instanceIds.add(instanceIdParam); -// } -// -// // FIXME: We should probably lock the load balancer here to prevent multiple updates... -// LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId); -// if (loadBalancer == null) { -// throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found."); -// } -// -// -// // Permission check... -// Account account = UserContext.current().getAccount(); -// if (account != null) { -// if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { -// if (!_domainDao.isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) { -// throw new PermissionDeniedException("Failed to assign to load balancer " + loadBalancerId + ", permission denied."); -// } -// } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN && account.getId() != loadBalancer.getAccountId()) { -// throw new PermissionDeniedException("Failed to assign to load balancer " + loadBalancerId + ", permission denied."); -// } -// } -// -// Transaction txn = Transaction.currentTxn(); -// List firewallRulesToApply = new ArrayList(); -// long accountId = 0; -// DomainRouterVO router = null; -// -// List mappedInstances = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false); -// Set mappedInstanceIds = new HashSet(); -// if (mappedInstances != null) { -// for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { -// mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId())); -// } -// } -// -// List finalInstanceIds = new ArrayList(); -// for (Long instanceId : instanceIds) { -// if (mappedInstanceIds.contains(instanceId)) { -// continue; -// } else { -// finalInstanceIds.add(instanceId); -// } -// -// UserVmVO userVm = _vmDao.findById(instanceId); -// if (userVm == null) { -// s_logger.warn("Unable to find virtual machine with id " + instanceId); -// throw new InvalidParameterValueException("Unable to find virtual machine with id " + instanceId); -// } else { -// // sanity check that the vm can be applied to the load balancer -// ServiceOfferingVO offering = _serviceOfferingDao.findById(userVm.getServiceOfferingId()); -// if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) { -// // we previously added these instanceIds to the loadBalancerVMMap, so remove them here as we are rejecting the API request -// // without actually modifying the load balancer -// _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, Boolean.TRUE); -// -// if (s_logger.isDebugEnabled()) { -// s_logger.debug("Unable to add virtual machine " + userVm.toString() + " to load balancer " + loadBalancerId + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")"); -// } -// -// throw new InvalidParameterValueException("Unable to add virtual machine " + userVm.toString() + " to load balancer " + loadBalancerId + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")"); -// } -// } -// -// if (accountId == 0) { -// accountId = userVm.getAccountId(); -// } else if (accountId != userVm.getAccountId()) { -// s_logger.warn("guest vm " + userVm.getHostName() + " (id:" + userVm.getId() + ") belongs to account " + userVm.getAccountId() -// + ", previous vm in list belongs to account " + accountId); -// throw new InvalidParameterValueException("guest vm " + userVm.getHostName() + " (id:" + userVm.getId() + ") belongs to account " + userVm.getAccountId() -// + ", previous vm in list belongs to account " + accountId); -// } -// -// DomainRouterVO nextRouter = null; -// if (userVm.getDomainRouterId() != null) { -// nextRouter = _routerMgr.getRouter(userVm.getDomainRouterId()); -// } -// if (nextRouter == null) { -// s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + instanceId); -// throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + instanceId); -// } -// -// if (router == null) { -// router = nextRouter; -// -// // Make sure owner of router is owner of load balancer. Since we are already checking that all VMs belong to the same router, by checking router -// // ownership once we'll make sure all VMs belong to the owner of the load balancer. -// if (router.getAccountId() != loadBalancer.getAccountId()) { -// throw new InvalidParameterValueException("guest vm " + userVm.getHostName() + " (id:" + userVm.getId() + ") does not belong to the owner of load balancer " + -// loadBalancer.getName() + " (owner is account id " + loadBalancer.getAccountId() + ")"); -// } -// } else if (router.getId() != nextRouter.getId()) { -// throw new InvalidParameterValueException("guest vm " + userVm.getHostName() + " (id:" + userVm.getId() + ") belongs to router " + nextRouter.getHostName() -// + ", previous vm in list belongs to router " + router.getHostName()); -// } -// -// // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules -// String ipAddress = loadBalancer.getIpAddress(); -// String privateIpAddress = userVm.getGuestIpAddress(); -// List existingRulesOnPubIp = _rulesDao.listIPForwarding(ipAddress); -// -// if (existingRulesOnPubIp != null) { -// for (PortForwardingRuleVO fwRule : existingRulesOnPubIp) { -// if (!( (fwRule.isForwarding() == false) && -// (fwRule.getGroupId() != null) && -// (fwRule.getGroupId() == loadBalancer.getId()) )) { -// // if the rule is not for the current load balancer, check to see if the private IP is our target IP, -// // in which case we have a conflict -// if (fwRule.getSourcePort().equals(loadBalancer.getPublicPort())) { -// throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + loadBalancer.getPublicPort() -// + " exists, found while trying to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancer.getId() + ") to instance " -// + userVm.getHostName() + "."); -// } -// } else if (fwRule.getDestinationIpAddress().equals(privateIpAddress) && fwRule.getDestinationPort().equals(loadBalancer.getPrivatePort()) && fwRule.isEnabled()) { -// // for the current load balancer, don't add the same instance to the load balancer more than once -// continue; -// } -// } -// } -// -// PortForwardingRuleVO newFwRule = new PortForwardingRuleVO(); -// newFwRule.setAlgorithm(loadBalancer.getAlgorithm()); -// newFwRule.setEnabled(true); -// newFwRule.setForwarding(false); -// newFwRule.setPrivatePort(loadBalancer.getPrivatePort()); -// newFwRule.setPublicPort(loadBalancer.getPublicPort()); -// newFwRule.setPublicIpAddress(loadBalancer.getIpAddress()); -// newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress()); -// newFwRule.setGroupId(loadBalancer.getId()); -// -// firewallRulesToApply.add(newFwRule); -// } -// -// // if there's no work to do, bail out early rather than reconfiguring the proxy with the existing rules -// if (firewallRulesToApply.isEmpty()) { -// return true; -// } -// -// //Sync on domR -// if(router == null){ -// throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the domain router was not found at " + loadBalancer.getIpAddress()); -// } -// else{ -// cmd.synchronizeCommand("Router", router.getId()); -// } -// -// IPAddressVO ipAddr = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// List ipAddrs = listPublicIpAddressesInVirtualNetwork(accountId, ipAddr.getDataCenterId(), null); -// for (IPAddressVO ipv : ipAddrs) { -// List rules = _rulesDao.listIpForwardingRulesForLoadBalancers(ipv.getAddress()); -// firewallRulesToApply.addAll(rules); -// } -// -// txn.start(); -// -// List updatedRules = null; -// if (router.getState().equals(State.Starting)) { -// // Starting is a special case...if the router is starting that means the IP address hasn't yet been assigned to the domR and the update firewall rules script will fail. -// // In this case, just store the rules and they will be applied when the router state is resent (after the router is started). -// updatedRules = firewallRulesToApply; -// } else { -// updatedRules = updateFirewallRules(loadBalancer.getIpAddress(), firewallRulesToApply, router); -// } -// -// // Save and create the event -// String description; -// String type = EventTypes.EVENT_NET_RULE_ADD; -// String ruleName = "load balancer"; -// String level = EventVO.LEVEL_INFO; -// -// LoadBalancerVO loadBalancerLock = null; -// try { -// loadBalancerLock = _loadBalancerDao.acquireInLockTable(loadBalancerId); -// if (loadBalancerLock == null) { -// s_logger.warn("assignToLoadBalancer: Failed to lock load balancer " + loadBalancerId + ", proceeding with updating loadBalancerVMMappings..."); -// } -// if ((updatedRules != null) && (updatedRules.size() == firewallRulesToApply.size())) { -// // flag the instances as mapped to the load balancer -// for (Long addedInstanceId : finalInstanceIds) { -// LoadBalancerVMMapVO mappedVM = new LoadBalancerVMMapVO(loadBalancerId, addedInstanceId); -// _loadBalancerVMMapDao.persist(mappedVM); -// } -// -// /* We used to add these instances as pending when the API command is received on the server, and once they were applied, -// * the pending status was removed. In the 2.2 API framework, this is no longer done and instead the new mappings just -// * need to be persisted -// List pendingMappedVMs = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, true); -// for (LoadBalancerVMMapVO pendingMappedVM : pendingMappedVMs) { -// if (instanceIds.contains(pendingMappedVM.getInstanceId())) { -// LoadBalancerVMMapVO pendingMappedVMForUpdate = _loadBalancerVMMapDao.createForUpdate(); -// pendingMappedVMForUpdate.setPending(false); -// _loadBalancerVMMapDao.update(pendingMappedVM.getId(), pendingMappedVMForUpdate); -// } -// } -// */ -// -// for (PortForwardingRuleVO updatedRule : updatedRules) { -// _rulesDao.persist(updatedRule); -// -// description = "created new " + ruleName + " rule [" + updatedRule.getSourceIpAddress() + ":" -// + updatedRule.getSourcePort() + "]->[" + updatedRule.getDestinationIpAddress() + ":" -// + updatedRule.getDestinationPort() + "]" + " " + updatedRule.getProtocol(); -// -// EventUtils.saveEvent(UserContext.current().getUserId(), loadBalancer.getAccountId(), level, type, description); -// } -// txn.commit(); -// return true; -// } else { -// // Remove the instanceIds from the load balancer since there was a failure. Make sure to commit the -// // transaction here, otherwise the act of throwing the internal error exception will cause this -// // remove operation to be rolled back. -// _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, null); -// txn.commit(); -// -// s_logger.warn("Failed to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancerId + ") to guest virtual machines " + StringUtils.join(instanceIds, ",")); -// throw new CloudRuntimeException("Failed to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancerId + ") to guest virtual machine " + StringUtils.join(instanceIds, ",")); -// } -// } finally { -// if (loadBalancerLock != null) { -// _loadBalancerDao.releaseFromLockTable(loadBalancerId); -// } -// } -// } - - -// @Override @DB -// public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException { -// String publicIp = cmd.getPublicIp(); -// -// // make sure ip address exists -// IPAddressVO ipAddr = _ipAddressDao.findById(cmd.getPublicIp()); -// if (ipAddr == null) { -// throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address " + publicIp); -// } -// -// VlanVO vlan = _vlanDao.findById(ipAddr.getVlanDbId()); -// if (vlan != null) { -// if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) { -// throw new InvalidParameterValueException("Unable to create load balancer rule for IP address " + publicIp + ", only VirtualNetwork type IP addresses can be used for load balancers."); -// } -// } // else ERROR? -// -// // Verify input parameters -// if ((ipAddr.getAccountId() == null) || (ipAddr.getAllocated() == null)) { -// throw new InvalidParameterValueException("Unable to create load balancer rule, cannot find account owner for ip " + publicIp); -// } -// -// Account account = UserContext.current().getAccount(); -// if (account != null) { -// if ((account.getType() == Account.ACCOUNT_TYPE_ADMIN) || (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) { -// if (!_domainDao.isChildDomain(account.getDomainId(), ipAddr.getDomainId())) { -// throw new PermissionDeniedException("Unable to create load balancer rule on IP address " + publicIp + ", permission denied."); -// } -// } else if (account.getId() != ipAddr.getAccountId().longValue()) { -// throw new PermissionDeniedException("Unable to create load balancer rule, account " + account.getAccountName() + " doesn't own ip address " + publicIp); -// } -// } -// -// String loadBalancerName = cmd.getLoadBalancerRuleName(); -// LoadBalancerVO existingLB = _loadBalancerDao.findByAccountAndName(ipAddr.getAccountId(), loadBalancerName); -// if (existingLB != null) { -// throw new InvalidParameterValueException("Unable to create load balancer rule, an existing load balancer rule with name " + loadBalancerName + " already exists."); -// } -// -// // validate params -// String publicPort = cmd.getPublicPort(); -// String privatePort = cmd.getPrivatePort(); -// String algorithm = cmd.getAlgorithm(); -// -// if (!NetUtils.isValidPort(publicPort)) { -// throw new InvalidParameterValueException("publicPort is an invalid value"); -// } -// if (!NetUtils.isValidPort(privatePort)) { -// throw new InvalidParameterValueException("privatePort is an invalid value"); -// } -// if ((algorithm == null) || !NetUtils.isValidAlgorithm(algorithm)) { -// throw new InvalidParameterValueException("Invalid algorithm"); -// } -// -// boolean locked = false; -// try { -// LoadBalancerVO exitingLB = _loadBalancerDao.findByIpAddressAndPublicPort(publicIp, publicPort); -// if (exitingLB != null) { -// throw new InvalidParameterValueException("IP Address/public port already load balanced by an existing load balancer rule"); -// } -// -// List existingFwRules = _rulesDao.listIPForwarding(publicIp, publicPort, true); -// if ((existingFwRules != null) && !existingFwRules.isEmpty()) { -// throw new InvalidParameterValueException("IP Address (" + publicIp + ") and port (" + publicPort + ") already in use"); -// } -// -// ipAddr = _ipAddressDao.acquireInLockTable(publicIp); -// if (ipAddr == null) { -// throw new PermissionDeniedException("User does not own ip address " + publicIp); -// } -// -// locked = true; -// -// LoadBalancerVO loadBalancer = new LoadBalancerVO(loadBalancerName, cmd.getDescription(), ipAddr.getAccountId(), publicIp, publicPort, privatePort, algorithm); -// loadBalancer = _loadBalancerDao.persist(loadBalancer); -// Long id = loadBalancer.getId(); -// -// // Save off information for the event that the security group was applied -// Long userId = UserContext.current().getUserId(); -// if (userId == null) { -// userId = Long.valueOf(User.UID_SYSTEM); -// } -// -// EventVO event = new EventVO(); -// event.setUserId(userId); -// event.setAccountId(ipAddr.getAccountId()); -// event.setType(EventTypes.EVENT_LOAD_BALANCER_CREATE); -// -// if (id == null) { -// event.setDescription("Failed to create load balancer " + loadBalancer.getName() + " on ip address " + publicIp + "[" + publicPort + "->" + privatePort + "]"); -// event.setLevel(EventVO.LEVEL_ERROR); -// } else { -// event.setDescription("Successfully created load balancer " + loadBalancer.getName() + " on ip address " + publicIp + "[" + publicPort + "->" + privatePort + "]"); -// String params = "id="+loadBalancer.getId()+"\ndcId="+ipAddr.getDataCenterId(); -// event.setParameters(params); -// event.setLevel(EventVO.LEVEL_INFO); -// } -// _eventDao.persist(event); -// -// return _loadBalancerDao.findById(id); -// } finally { -// if (locked) { -// _ipAddressDao.releaseFromLockTable(publicIp); -// } -// } -// } - -// @Override -// public boolean updateLoadBalancerRules(final List fwRules, final DomainRouterVO router, Long hostId) { -// -// for (PortForwardingRuleVO rule : fwRules) { -// // Determine the the VLAN ID and netmask of the rule's public IP address -// IPAddressVO ip = _ipAddressDao.findById(rule.getSourceIpAddress()); -// VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId())); -// String vlanNetmask = vlan.getVlanNetmask(); -// -// rule.setVlanNetmask(vlanNetmask); -// } -// -// final LoadBalancerConfigurator cfgrtr = new HAProxyConfigurator(); -// final String [] cfg = cfgrtr.generateConfiguration(fwRules); -// final String [][] addRemoveRules = cfgrtr.generateFwRules(fwRules); -// final LoadBalancerCfgCommand cmd = new LoadBalancerCfgCommand(cfg, addRemoveRules, router.getInstanceName(), router.getPrivateIpAddress()); -// final Answer ans = _agentMgr.easySend(hostId, cmd); -// if (ans == null) { -// return false; -// } else { -// return ans.getResult(); -// } -// } -// @Override @DB -// public LoadBalancerVO updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{ -// Long loadBalancerId = cmd.getId(); -// String privatePort = cmd.getPrivatePort(); -// String algorithm = cmd.getAlgorithm(); -// String name = cmd.getLoadBalancerName(); -// String description = cmd.getDescription(); -// Account account = UserContext.current().getAccount(); -// -// //Verify input parameters -// LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId); -// if (loadBalancer == null) { -// throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId + " for update."); -// } -// -// // make sure the name's not already in use -// if (name != null) { -// LoadBalancerVO existingLB = _loadBalancerDao.findByAccountAndName(loadBalancer.getAccountId(), name); -// if ((existingLB != null) && (existingLB.getId() != loadBalancer.getId())) { -// throw new InvalidParameterValueException("Unable to update load balancer " + loadBalancer.getName() + " with new name " + name + ", the name is already in use."); -// } -// } -// -// Account lbOwner = _accountDao.findById(loadBalancer.getAccountId()); -// if (lbOwner == null) { -// throw new InvalidParameterValueException("Unable to update load balancer rule, cannot find owning account"); -// } -// -// Long accountId = lbOwner.getId(); -// if (account != null) { -// if (!isAdmin(account.getType())) { -// if (account.getId() != accountId.longValue()) { -// throw new PermissionDeniedException("Unable to update load balancer rule, permission denied"); -// } -// } else if (!_domainDao.isChildDomain(account.getDomainId(), lbOwner.getDomainId())) { -// throw new PermissionDeniedException("Unable to update load balancer rule, permission denied."); -// } -// } -// -// String updatedPrivatePort = ((privatePort == null) ? loadBalancer.getPrivatePort() : privatePort); -// String updatedAlgorithm = ((algorithm == null) ? loadBalancer.getAlgorithm() : algorithm); -// String updatedName = ((name == null) ? loadBalancer.getName() : name); -// String updatedDescription = ((description == null) ? loadBalancer.getDescription() : description); -// -// Transaction txn = Transaction.currentTxn(); -// try { -// txn.start(); -// loadBalancer.setPrivatePort(updatedPrivatePort); -// loadBalancer.setAlgorithm(updatedAlgorithm); -// loadBalancer.setName(updatedName); -// loadBalancer.setDescription(updatedDescription); -// _loadBalancerDao.update(loadBalancer.getId(), loadBalancer); -// -// List fwRules = _firewallRulesDao.listByLoadBalancerId(loadBalancer.getId()); -// if ((fwRules != null) && !fwRules.isEmpty()) { -// for (PortForwardingRuleVO fwRule : fwRules) { -// fwRule.setPrivatePort(updatedPrivatePort); -// fwRule.setAlgorithm(updatedAlgorithm); -// _firewallRulesDao.update(fwRule.getId(), fwRule); -// } -// } -// txn.commit(); -// } catch (RuntimeException ex) { -// s_logger.warn("Unhandled exception trying to update load balancer rule", ex); -// txn.rollback(); -// throw ex; -// } finally { -// txn.close(); -// } -// -// // now that the load balancer has been updated, reconfigure the HA Proxy on the router with all the LB rules -// List allLbRules = new ArrayList(); -// IPAddressVO ipAddress = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// List ipAddrs = listPublicIpAddressesInVirtualNetwork(loadBalancer.getAccountId(), ipAddress.getDataCenterId(), null); -// for (IPAddressVO ipv : ipAddrs) { -// List rules = _firewallRulesDao.listIPForwarding(ipv.getAddress(), false); -// allLbRules.addAll(rules); -// } -// -// IPAddressVO ip = _ipAddressDao.findById(loadBalancer.getIpAddress()); -// DomainRouterVO router = _routerMgr.getRouter(ip.getAccountId(), ip.getDataCenterId()); -// updateFirewallRules(loadBalancer.getIpAddress(), allLbRules, router); -// return _loadBalancerDao.findById(loadBalancer.getId()); -// } - @Override public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException { Account caller = UserContext.current().getCaller(); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index df66863eff1..0b0c5bebd95 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -22,7 +22,6 @@ import java.util.Map; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; @@ -32,6 +31,7 @@ import com.cloud.network.RemoteAccessVpn; import com.cloud.network.VirtualNetworkApplianceService; import com.cloud.network.VpnUser; import com.cloud.network.lb.LoadBalancingRule; +import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.uservm.UserVm; @@ -81,8 +81,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA boolean associateIP (Network network, List ipAddress) throws ResourceUnavailableException; - boolean applyLBRules(Network network, List rules) throws ResourceUnavailableException; - boolean applyPortForwardingRules(Network network, List rules) throws AgentUnavailableException; + boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException; String[] applyVpnUsers(Network network, List users) throws ResourceUnavailableException; diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 07f82ef2229..b5a2257306f 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -49,11 +49,13 @@ import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.api.commands.UpgradeRouterCmd; @@ -113,8 +115,10 @@ import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.RulesManager; +import com.cloud.network.rules.StaticNatRule; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; @@ -1027,23 +1031,21 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian createAssociateIPCommands(router, publicIps, cmds, 0); //Re-apply port forwarding rules for all public ips - List rulesToReapply = new ArrayList(); List vpns = new ArrayList(); + List rules = null; for (PublicIpAddress ip : publicIps) { - List rules = _pfRulesDao.listForApplication(ip.getId()); - if (rules != null){ - rulesToReapply.addAll(_rulesMgr.buildPortForwardingTOrules(rules)); - } + rules = _pfRulesDao.listForApplication(ip.getId()); + RemoteAccessVpn vpn = _vpnDao.findById(ip.getId()); if (vpn != null) { vpns.add(vpn); } } - s_logger.debug("Found " + rulesToReapply.size() + " port forwarding rule(s) to apply as a part of domR " + router + " start."); - if (!rulesToReapply.isEmpty()) { - createApplyPortForwardingRulesCommands(rulesToReapply, router, cmds); + s_logger.debug("Found " + rules.size() + " port forwarding rule(s) to apply as a part of domR " + router + " start."); + if (!rules.isEmpty()) { + createApplyPortForwardingRulesCommands(rules, router, cmds); } s_logger.debug("Found " + vpns.size() + " vpn(s) to apply as a part of domR " + router + " start."); @@ -1209,7 +1211,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian Commands cmds = new Commands(OnError.Stop); String routerControlIpAddress = null; - List nics = _nicDao.listBy(router.getId()); + List nics = _nicDao.listByVmId(router.getId()); for (NicVO n : nics) { NetworkVO nc = _networksDao.findById(n.getNetworkId()); if (nc.getTrafficType() == TrafficType.Control) { @@ -1403,8 +1405,35 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } } - private void createApplyPortForwardingRulesCommands(List rules, DomainRouterVO router, Commands cmds) { - SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rules); + private void createApplyPortForwardingRulesCommands(List rules, DomainRouterVO router, Commands cmds) { + List rulesTO = null; + if (rules != null) { + rulesTO = new ArrayList(); + for (PortForwardingRule rule : rules) { + IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId()); + PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, sourceIp.getAddress().addr()); + rulesTO.add(ruleTO); + } + } + + SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rulesTO); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress()); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + cmds.addCommand(cmd); + } + + private void createApplyStaticNatRulesCommands(List rules, DomainRouterVO router, Commands cmds) { + List rulesTO = null; + if (rules != null) { + rulesTO = new ArrayList(); + for (StaticNatRule rule : rules) { + IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId()); + StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, sourceIp.getAddress().addr(), rule.getDestIpAddress()); + rulesTO.add(ruleTO); + } + } + + SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress()); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); cmds.addCommand(cmd); @@ -1547,30 +1576,72 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian throw new ResourceUnavailableException("Unable to assign ip addresses, domR is not in right state " + router.getState(), DataCenter.class, network.getDataCenterId()); } } - + @Override - public boolean applyLBRules(Network network, List rules) throws ResourceUnavailableException { + public boolean applyFirewallRules(Network network, List rules) throws ResourceUnavailableException { DomainRouterVO router = _routerDao.findByNetwork(network.getId()); if (router == null) { s_logger.warn("Unable to apply lb rules, virtual router doesn't exist in the network " + network.getId()); throw new ResourceUnavailableException("Unable to apply lb rules", DataCenter.class, network.getDataCenterId()); } + if (router.getState() == State.Running) { + if (rules != null && !rules.isEmpty()) { + if (rules.get(0).getPurpose() == Purpose.LoadBalancing) { + //for load balancer we have to resend all lb rules for the network + List lbs = _loadBalancerDao.listByNetworkId(network.getId()); + List lbRules = new ArrayList(); + for (LoadBalancerVO lb : lbs) { + List dstList = _lbMgr.getExistingDestinations(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); + lbRules.add(loadBalancing); + } + + return applyLBRules(router, lbRules); + } else if (rules.get(0).getPurpose() == Purpose.PortForwarding) { + return applyPortForwardingRules(router, (List)rules); + } else if (rules.get(0).getPurpose() == Purpose.StaticNat) { + return applyStaticNatRules(router, (List)rules); + + }else { + s_logger.warn("Unable to apply rules of purpose: " + rules.get(0).getPurpose()); + return false; + } + } else { + return true; + } + } else if (router.getState() == State.Stopped || router.getState() == State.Stopping){ + s_logger.debug("Router is in " + router.getState() + ", so not sending apply firewall rules commands to the backend"); + return true; + } else { + s_logger.warn("Unable to apply firewall rules, virtual router is not in the right state " + router.getState()); + throw new CloudRuntimeException("Unable to apply firewall rules, domR is not in right state " + router.getState()); + } + } + + + protected boolean applyLBRules(DomainRouterVO router, List rules) throws ResourceUnavailableException { Commands cmds = new Commands(OnError.Continue); createApplyLoadBalancingRulesCommands(rules, router, cmds); //Send commands to router return sendCommandsToRouter(router, cmds); } - @Override - public boolean applyPortForwardingRules(Network network, List rules) throws AgentUnavailableException { - DomainRouterVO router = _routerDao.findByNetwork(network.getId()); - + protected boolean applyPortForwardingRules(DomainRouterVO router, List rules) throws ResourceUnavailableException { Commands cmds = new Commands(OnError.Continue); createApplyPortForwardingRulesCommands(rules, router, cmds); //Send commands to router return sendCommandsToRouter(router, cmds); } + + + protected boolean applyStaticNatRules(DomainRouterVO router, List rules) throws ResourceUnavailableException { + Commands cmds = new Commands(OnError.Continue); + createApplyStaticNatRulesCommands(rules, router, cmds); + //Send commands to router + return sendCommandsToRouter(router, cmds); + } + private List findLonelyRouters() { List routersToStop = new ArrayList(); diff --git a/server/src/com/cloud/network/rules/FirewallRuleVO.java b/server/src/com/cloud/network/rules/FirewallRuleVO.java index ef8cc1fbde7..7c2a9fb1027 100644 --- a/server/src/com/cloud/network/rules/FirewallRuleVO.java +++ b/server/src/com/cloud/network/rules/FirewallRuleVO.java @@ -79,9 +79,6 @@ public class FirewallRuleVO implements FirewallRule { @Column(name=GenericDao.CREATED_COLUMN) Date created; - @Column(name="is_static_nat", updatable=false) - boolean oneToOneNat; - @Column(name="network_id") long networkId; @@ -151,7 +148,7 @@ public class FirewallRuleVO implements FirewallRule { protected FirewallRuleVO() { } - public FirewallRuleVO(String xId, long ipAddressId, int portStart, int portEnd, String protocol, long networkId, long accountId, long domainId, Purpose purpose, boolean isOneToOneNat) { + public FirewallRuleVO(String xId, long ipAddressId, int portStart, int portEnd, String protocol, long networkId, long accountId, long domainId, Purpose purpose) { this.xId = xId; if (xId == null) { this.xId = UUID.randomUUID().toString(); @@ -165,11 +162,10 @@ public class FirewallRuleVO implements FirewallRule { this.purpose = purpose; this.networkId = networkId; this.state = State.Staged; - this.oneToOneNat = isOneToOneNat; } - public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, long networkId, long accountId, long domainId, Purpose purpose, boolean isOneToOneNat) { - this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose, isOneToOneNat); + public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, long networkId, long accountId, long domainId, Purpose purpose) { + this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose); } @Override @@ -177,8 +173,4 @@ public class FirewallRuleVO implements FirewallRule { return new StringBuilder("Rule[").append(id).append("-").append(purpose).append("-").append(state).append("]").toString(); } - @Override - public boolean isOneToOneNat() { - return oneToOneNat; - } } diff --git a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java index 04db1def417..057d9fd5055 100644 --- a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java +++ b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java @@ -52,16 +52,16 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi public PortForwardingRuleVO() { } - public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, long networkId, long accountId, long domainId, long instanceId, boolean isOneToOneNat) { - super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding, isOneToOneNat); + public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, long networkId, long accountId, long domainId, long instanceId) { + super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding); this.destinationIpAddress = dstIp; this.virtualMachineId = instanceId; this.destinationPortStart = dstPortStart; this.destinationPortEnd = dstPortEnd; } - public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip dstIp, int dstPort, String protocol, long networkId, long accountId, long domainId, long instanceId, boolean isOneToOneNat) { - this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, protocol.toLowerCase(), networkId, accountId, domainId, instanceId, isOneToOneNat); + public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip dstIp, int dstPort, String protocol, long networkId, long accountId, long domainId, long instanceId) { + this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, protocol.toLowerCase(), networkId, accountId, domainId, instanceId); } @Override diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java index ce864f58fab..ee5fd9a497d 100644 --- a/server/src/com/cloud/network/rules/RulesManager.java +++ b/server/src/com/cloud/network/rules/RulesManager.java @@ -35,8 +35,12 @@ public interface RulesManager extends RulesService { boolean applyPortForwardingRules(long ipAddressId, boolean continueOnError, Account caller); + boolean applyStaticNatRules(long sourceIpId, boolean continueOnError, Account caller); + boolean applyPortForwardingRulesForNetwork(long networkId, boolean continueOnError, Account caller); + boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnError, Account caller); + /** * detectRulesConflict finds conflicts in networking rules. It checks for * conflicts between the following types of netowrking rules; @@ -59,7 +63,7 @@ public interface RulesManager extends RulesService { void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) throws InvalidParameterValueException, PermissionDeniedException; void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller) throws InvalidParameterValueException, PermissionDeniedException; - boolean revokeAllRules(long ipId, long userId) throws ResourceUnavailableException; + boolean revokeAllRules(long ipId, long userId, Account caller) throws ResourceUnavailableException; List listFirewallRulesByIp(long ipAddressId); @@ -73,10 +77,14 @@ public interface RulesManager extends RulesService { List gatherPortForwardingRulesForApplication(List addrs); - boolean revokePortForwardingRule(long vmId); + boolean revokePortForwardingRulesForVm(long vmId); + + boolean revokeStaticNatRulesForVm(long vmId); FirewallRule[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, int... ports) throws NetworkRuleConflictException; boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports); List listByNetworkId(long networkId); + + } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 35eec29f2ca..2edc0225bc2 100644 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -26,7 +26,6 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.api.commands.ListPortForwardingRulesCmd; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -100,9 +99,9 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { continue; // Skips my own rule. } - if (rule.isOneToOneNat() && !newRule.isOneToOneNat()) { + if (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() != Purpose.StaticNat) { throw new NetworkRuleConflictException("There is 1 to 1 Nat rule specified for the ip address id=" + newRule.getSourceIpAddressId()); - } else if (!rule.isOneToOneNat() && newRule.isOneToOneNat()) { + } else if (rule.getPurpose() != Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat) { throw new NetworkRuleConflictException("There is already firewall rule specified for the ip address id=" + newRule.getSourceIpAddressId()); } @@ -176,8 +175,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } - @Override @DB @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="creating forwarding rule", create=true) - public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean isNat) throws NetworkRuleConflictException { + @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="creating forwarding rule", create=true) + public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId) throws NetworkRuleConflictException { UserContext ctx = UserContext.current(); Account caller = ctx.getCaller(); @@ -185,10 +184,12 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId); - //Verify ip address existst and if 1-1 nat is enabled for it + //Validate ip address if (ipAddress == null) { - throw new InvalidParameterValueException("Unable to create ip forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system"); - } else { + throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " doesn't exist in the system"); + } else if (ipAddress.isOneToOneNat()) { + throw new InvalidParameterValueException("Unable to create port forwarding rule; ip id=" + ipAddrId + " has static nat enabled"); + }else { _accountMgr.checkAccess(caller, ipAddress); } @@ -200,20 +201,14 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { // validate user VM exists vm = _vmDao.findById(vmId); if (vm == null) { - throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + vmId + ")."); + throw new InvalidParameterValueException("Unable to create port forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + vmId + ")."); } else { checkRuleAndUserVm(rule, vm, caller); } - dstIp = null; - List nics = _networkMgr.getNics(vm); - for (Nic nic : nics) { - Network ntwk = _networkMgr.getNetwork(nic.getNetworkId()); - if (ntwk.getGuestType() == GuestIpType.Virtual && nic.getIp4Address() != null) { - network = ntwk; - dstIp = new Ip(nic.getIp4Address()); - break; - } - } + + Pair guestNic = getUserVmGuestIpAddress(vm, false); + dstIp = guestNic.second(); + network = guestNic.first(); if (network == null) { throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vmId); @@ -230,11 +225,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { networkId = network.getId(); long accountId = network.getAccountId(); long domainId = network.getDomainId(); - - if (isNat && (ipAddress.isSourceNat() || !ipAddress.isOneToOneNat() || ipAddress.getAssociatedWithVmId() == null)) { - throw new NetworkRuleConflictException("Can't do one to one NAT on ip address: " + ipAddress.getAddress()); - } - //Verify that the network guru supports the protocol specified Map firewallCapability = _networkMgr.getServiceCapability(network.getDataCenterId(), Service.Firewall); @@ -244,7 +234,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } //start port can't be bigger than end port - if (rule.getDestinationPortStart() > rule.getDestinationPortEnd()) { + if (rule.getDestinationPortStart() > rule.getDestinationPortEnd() || rule.getSourcePortStart() > rule.getSourcePortEnd()) { throw new InvalidParameterValueException("Start port can't be bigger than end port"); } @@ -259,7 +249,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { rule.getProtocol().toLowerCase(), networkId, accountId, - domainId, vmId, isNat); + domainId, vmId); newRule = _forwardingDao.persist(newRule); try { @@ -280,6 +270,96 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } + + + @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="creating static nat rule", create=true) + public StaticNatRule createStaticNatRule(StaticNatRule rule) throws NetworkRuleConflictException { + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + Long ipAddrId = rule.getSourceIpAddressId(); + + IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId); + + //Verify ip address existst and if 1-1 nat is enabled for it + if (ipAddress == null) { + throw new InvalidParameterValueException("Unable to create static nat rule; ip id=" + ipAddrId + " doesn't exist in the system"); + } else if (ipAddress.isSourceNat() || !ipAddress.isOneToOneNat() || ipAddress.getAssociatedWithVmId() == null) { + throw new NetworkRuleConflictException("Can't do static nat on ip address: " + ipAddress.getAddress()); + }else { + _accountMgr.checkAccess(caller, ipAddress); + } + + //Get vm information and verify it + long vmId = ipAddress.getAssociatedWithVmId(); + + // validate user VM exists + UserVmVO vm = _vmDao.findById(vmId); + if (vm == null) { + throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + vmId + ")."); + } else { + checkRuleAndUserVm(rule, vm, caller); + } + + Pair guestNic = getUserVmGuestIpAddress(vm, false); + Ip dstIp = guestNic.second(); + Network guestNetwork = guestNic.first(); + + if (guestNetwork == null) { + throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vmId); + } + + _accountMgr.checkAccess(caller, guestNetwork); + + long accountId = guestNetwork.getAccountId(); + long domainId = guestNetwork.getDomainId(); + + //Verify that the network guru supports the protocol specified + Map firewallCapability = _networkMgr.getServiceCapability(guestNetwork.getDataCenterId(), Service.Firewall); + String supportedProtocols = firewallCapability.get(Capability.SupportedProtocols).toLowerCase(); + if (!supportedProtocols.contains(rule.getProtocol().toLowerCase())) { + throw new InvalidParameterValueException("Protocol " + rule.getProtocol() + " is not supported in zone " + guestNetwork.getDataCenterId()); + } + + //start port can't be bigger than end port + if (rule.getSourcePortStart() > rule.getSourcePortEnd()) { + throw new InvalidParameterValueException("Start port can't be bigger than end port"); + } + + FirewallRuleVO newRule = + new FirewallRuleVO(rule.getXid(), + rule.getSourceIpAddressId(), + rule.getSourcePortStart(), + rule.getSourcePortEnd(), + rule.getProtocol().toLowerCase(), + guestNetwork.getId(), + accountId, + domainId, + rule.getPurpose()); + newRule = _firewallDao.persist(newRule); + + try { + detectRulesConflict(newRule, ipAddress); + if (!_firewallDao.setStateToAdd(newRule)) { + throw new CloudRuntimeException("Unable to update the state to add for " + newRule); + } + UserContext.current().setEventDetails("Rule Id: "+newRule.getId()); + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_ADD, newRule.getAccountId(), 0, newRule.getId(), null); + _usageEventDao.persist(usageEvent); + + StaticNatRule staticNatRule = new StaticNatRuleImpl(newRule, dstIp.addr()); + + return staticNatRule; + } catch (Exception e) { + _forwardingDao.remove(newRule.getId()); + if (e instanceof NetworkRuleConflictException) { + throw (NetworkRuleConflictException)e; + } + throw new CloudRuntimeException("Unable to add static nat rule for the ip id=" + newRule.getSourceIpAddressId(), e); + } + } + + @Override public boolean enableOneToOneNat(long ipId, long vmId) throws NetworkRuleConflictException{ IPAddressVO ipAddress = _ipAddressDao.findById(ipId); @@ -298,7 +378,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } if (!ipAddress.isOneToOneNat()) { - List rules = _firewallDao.listByIpAndNotRevoked(ipId, false); + List rules = _firewallDao.listByIpAndNotRevoked(ipId, Purpose.PortForwarding); if (rules != null && !rules.isEmpty()) { throw new NetworkRuleConflictException("Failed to enable one to one nat for the ip address id=" + ipAddress.getId() + " as it already has firewall rules assigned"); } @@ -314,20 +394,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } - protected Pair getUserVmGuestIpAddress(UserVm vm) { - Ip dstIp = null; - List nics = _networkMgr.getNics(vm); - for (Nic nic : nics) { - Network ntwk = _networkMgr.getNetwork(nic.getNetworkId()); - if (ntwk.getGuestType() == GuestIpType.Virtual) { - dstIp = new Ip(nic.getIp4Address()); - return new Pair(ntwk, dstIp); - } - } - - throw new CloudRuntimeException("Unable to find ip address to map to in " + vm.getId()); - } - @DB protected void revokeRule(FirewallRuleVO rule, Account caller, long userId) { if (caller != null) { @@ -347,7 +413,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } // Save and create the event - String ruleName = rule.getPurpose() == Purpose.Firewall ? "Firewall" : (rule.isOneToOneNat() ? "ip forwarding" : "port forwarding"); + String ruleName = rule.getPurpose() == Purpose.Firewall ? "Firewall" : (rule.getPurpose() == FirewallRule.Purpose.StaticNat ? "ip forwarding" : "port forwarding"); StringBuilder description = new StringBuilder("deleted ").append(ruleName).append(" rule [ipAddressId=").append(rule.getSourceIpAddressId()).append(":").append(rule.getSourcePortStart()).append("-").append(rule.getSourcePortEnd()).append("]"); if (rule.getPurpose() == Purpose.PortForwarding) { PortForwardingRuleVO pfRule = (PortForwardingRuleVO)rule; @@ -360,10 +426,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_DELETE, eventDescription="revoking forwarding rule", async=true) public boolean revokePortForwardingRule(long ruleId, boolean apply) { - return revokePortForwardingRuleInternal(ruleId, apply); - } - - private boolean revokePortForwardingRuleInternal(long ruleId, boolean apply) { UserContext ctx = UserContext.current(); Account caller = ctx.getCaller(); @@ -372,10 +434,17 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { throw new InvalidParameterValueException("Unable to find " + ruleId); } - long ownerId = rule.getAccountId(); - _accountMgr.checkAccess(caller, rule); - revokeRule(rule, caller, ctx.getCallerUserId()); + + return revokePortForwardingRuleInternal(ruleId, caller, ctx.getCallerUserId(), apply); + } + + private boolean revokePortForwardingRuleInternal(long ruleId, Account caller, long userId, boolean apply) { + PortForwardingRuleVO rule = _forwardingDao.findById(ruleId); + + long ownerId = rule.getAccountId(); + + revokeRule(rule, caller, userId); boolean success = false; @@ -391,8 +460,44 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return success; } + + @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_DELETE, eventDescription="revoking forwarding rule", async=true) + public boolean revokeStaticNatRule(long ruleId, boolean apply) { + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + FirewallRuleVO rule = _firewallDao.findById(ruleId); + if (rule == null) { + throw new InvalidParameterValueException("Unable to find " + ruleId); + } + + _accountMgr.checkAccess(caller, rule); + + return revokeStaticNatRuleInternal(ruleId, caller, ctx.getCallerUserId(), apply); + } + + private boolean revokeStaticNatRuleInternal(long ruleId, Account caller, long userId, boolean apply) { + FirewallRuleVO rule = _firewallDao.findById(ruleId); + + revokeRule(rule, caller, userId); + + boolean success = false; + + if (apply) { + success = applyStaticNatRules(rule.getSourceIpAddressId(), true, caller); + } else { + success = true; + } + if(success){ + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, ruleId, null); + _usageEventDao.persist(usageEvent); + } + return success; + } + + @Override - public boolean revokePortForwardingRule(long vmId) { + public boolean revokePortForwardingRulesForVm(long vmId) { UserVmVO vm = _vmDao.findByIdIncludingRemoved(vmId); if (vm == null) { return false; @@ -401,17 +506,35 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { List rules = _forwardingDao.listByVm(vmId); if (rules == null || rules.isEmpty()) { + s_logger.debug("No port forwarding rules are found for vm id=" + vmId); return true; } for (PortForwardingRuleVO rule : rules) { - revokePortForwardingRuleInternal(rule.getId(), true); + revokePortForwardingRuleInternal(rule.getId(), _accountMgr.getSystemAccount(), Account.ACCOUNT_ID_SYSTEM, true); } return true; } - public List listFirewallRules(long ipId) { - return _firewallDao.listByIpAndNotRevoked(ipId, null); + + @Override + public boolean revokeStaticNatRulesForVm(long vmId) { + UserVmVO vm = _vmDao.findByIdIncludingRemoved(vmId); + if (vm == null) { + return false; + } + + List rules = _firewallDao.listStaticNatByVmId(vm.getId()); + + if (rules == null || rules.isEmpty()) { + s_logger.debug("No static nat rules are found for vm id=" + vmId); + return true; + } + + for (FirewallRuleVO rule : rules) { + revokeStaticNatRuleInternal(rule.getId(), _accountMgr.getSystemAccount(), Account.ACCOUNT_ID_SYSTEM, true); + } + return true; } @Override @@ -447,7 +570,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); sb.and("accountId", sb.entity().getAccountId(), Op.EQ); sb.and("domainId", sb.entity().getDomainId(), Op.EQ); - sb.and("oneToOneNat", sb.entity().isOneToOneNat(), Op.EQ); + sb.and("purpose", sb.entity().getPurpose(), Op.EQ); if (path != null) { //for domain admin we should show only subdomains information @@ -470,7 +593,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } - sc.setParameters("oneToOneNat", false); + sc.setParameters("purpose", Purpose.PortForwarding); if (path != null) { sc.setJoinParameters("domainSearch", "path", path + "%"); @@ -504,14 +627,56 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return true; } + @Override + public boolean applyStaticNatRules(long sourceIpId, boolean continueOnError, Account caller){ + List rules = _firewallDao.listByIpAndPurpose(sourceIpId, Purpose.StaticNat); + List staticNatRules = new ArrayList(); + + if (rules.size() == 0) { + s_logger.debug("There are no firwall rules to apply for ip id=" + sourceIpId); + return true; + } + + for (FirewallRuleVO rule : rules) { + IpAddress sourceIp = _ipAddressDao.findById(rule.getSourceIpAddressId()); + + UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId()); + + Pair guestNic = getUserVmGuestIpAddress(vm, true); + Ip dstIp = guestNic.second(); + Network network = guestNic.first(); + + if (network == null) { + throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vm.getId()); + } + + staticNatRules.add(new StaticNatRuleImpl(rule, dstIp.addr())); + } + + if (caller != null) { + _accountMgr.checkAccess(caller, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()])); + } + + try { + if (!applyRules(staticNatRules, continueOnError)) { + return false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to apply static nat rules due to ", ex); + return false; + } + + return true; + } + @Override public boolean applyPortForwardingRulesForNetwork(long networkId, boolean continueOnError, Account caller){ List rules = listByNetworkId(networkId); if (rules.size() == 0) { - s_logger.debug("There are no firewall rules to apply for network id=" + networkId); + s_logger.debug("There are no port forwarding rules to apply for network id=" + networkId); return true; } - + if (caller != null) { _accountMgr.checkAccess(caller, rules.toArray(new PortForwardingRuleVO[rules.size()])); } @@ -528,17 +693,63 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return true; } - private boolean applyRules(List rules, boolean continueOnError) throws ResourceUnavailableException{ + + @Override + public boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnError, Account caller){ + List rules = _firewallDao.listByNetworkIdAndPurpose(networkId, Purpose.StaticNat); + List staticNatRules = new ArrayList(); + + if (rules.size() == 0) { + s_logger.debug("There are no static nat rules to apply for network id=" + networkId); + return true; + } + + if (caller != null) { + _accountMgr.checkAccess(caller, rules.toArray(new FirewallRule[rules.size()])); + } + + for (FirewallRuleVO rule : rules) { + IpAddress sourceIp = _ipAddressDao.findById(rule.getSourceIpAddressId()); + + UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId()); + + Pair guestNic = getUserVmGuestIpAddress(vm, true); + Ip dstIp = guestNic.second(); + Network network = guestNic.first(); + + if (network == null) { + throw new CloudRuntimeException("Unable to find ip address to map to in vm id=" + vm.getId()); + } + + staticNatRules.add(new StaticNatRuleImpl(rule, dstIp.addr())); + } + + try { + if (!applyRules(staticNatRules, continueOnError)) { + return false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to apply firewall rules due to ", ex); + return false; + } + + return true; + } + + + + private boolean applyRules(List rules, boolean continueOnError) throws ResourceUnavailableException{ if (!_networkMgr.applyRules(rules, continueOnError)) { s_logger.warn("Rules are not completely applied"); return false; } else { - for (PortForwardingRuleVO rule : rules) { + for (FirewallRule rule : rules) { if (rule.getState() == FirewallRule.State.Revoke) { - _forwardingDao.remove(rule.getId()); + _firewallDao.remove(rule.getId()); } else if (rule.getState() == FirewallRule.State.Add) { - rule.setState(FirewallRule.State.Active); - _forwardingDao.update(rule.getId(), rule); + FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId()); + ruleVO.setState(FirewallRule.State.Active); + _firewallDao.update(ruleVO.getId(), ruleVO); } } return true; @@ -546,7 +757,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } @Override - public List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId) { + public List searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId) { Account caller = UserContext.current().getCaller(); String path = null; @@ -568,11 +779,11 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } Filter filter = new Filter(PortForwardingRuleVO.class, "id", false, start, size); - SearchBuilder sb = _forwardingDao.createSearchBuilder(); + SearchBuilder sb = _firewallDao.createSearchBuilder(); sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); sb.and("accountId", sb.entity().getAccountId(), Op.EQ); sb.and("domainId", sb.entity().getDomainId(), Op.EQ); - sb.and("oneToOneNat", sb.entity().isOneToOneNat(), Op.EQ); + sb.and("purpose", sb.entity().getPurpose(), Op.EQ); sb.and("id", sb.entity().getId(), Op.EQ); if (path != null) { @@ -588,7 +799,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { sb.join("ipSearch", ipSearch, sb.entity().getSourceIpAddressId(), ipSearch.entity().getId(), JoinBuilder.JoinType.INNER); } - SearchCriteria sc = sb.create(); + SearchCriteria sc = sb.create(); if (id != null) { sc.setParameters("id", id); @@ -606,7 +817,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } - sc.setParameters("oneToOneNat", true); + sc.setParameters("purpose", Purpose.StaticNat); if (path != null) { sc.setJoinParameters("domainSearch", "path", path + "%"); @@ -616,29 +827,52 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { sc.setJoinParameters("ipSearch", "associatedWithVmId", vmId); } - return _forwardingDao.search(sc, filter); + return _firewallDao.search(sc, filter); } - @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="applying forwarding rule", async=true) + @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="applying port forwarding rule", async=true) public boolean applyPortForwardingRules(long ipId, Account caller) throws ResourceUnavailableException { return applyPortForwardingRules(ipId, false, caller); } + + @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="applying static nat rule", async=true) + public boolean applyStaticNatRules(long ipId, Account caller) throws ResourceUnavailableException { + return applyStaticNatRules(ipId, false, caller); + } + @Override - public boolean revokeAllRules(long ipId, long userId) throws ResourceUnavailableException { - List rules = _forwardingDao.listByIpAndNotRevoked(ipId); + public boolean revokeAllRules(long ipId, long userId, Account caller) throws ResourceUnavailableException { + List rules = new ArrayList(); + + //revoke all port forwarding rules + List pfRules = _forwardingDao.listByIpAndNotRevoked(ipId); if (s_logger.isDebugEnabled()) { - s_logger.debug("Releasing " + rules.size() + " rules for ip id=" + ipId); + s_logger.debug("Releasing " + pfRules.size() + " port forwarding rules for ip id=" + ipId); } - for (PortForwardingRuleVO rule : rules) { - revokeRule(rule, null, userId); + for (PortForwardingRuleVO rule : pfRules) { + revokePortForwardingRuleInternal(rule.getId(), caller, userId, true); } applyPortForwardingRules(ipId, true, null); + //revoke all all static nat rules + List staticNatRules = _firewallDao.listByIpAndNotRevoked(ipId, Purpose.StaticNat); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing " + pfRules.size() + " static nat rules for ip id=" + ipId); + } + + for (FirewallRuleVO rule : staticNatRules) { + revokeStaticNatRuleInternal(rule.getId(), caller, userId, true); + } + + applyStaticNatRules(ipId, true, null); + + // Now we check again in case more rules have been inserted. - rules = _forwardingDao.listByIpAndNotRevoked(ipId); + rules.addAll(_forwardingDao.listByIpAndNotRevoked(ipId)); + rules.addAll(_firewallDao.listByIpAndPurpose(ipId, Purpose.StaticNat)); if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully released rules for ip id=" + ipId + " and # of rules now = " + rules.size()); @@ -693,7 +927,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { ip.getAssociatedWithNetworkId(), ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(), - purpose, ip.isOneToOneNat()); + purpose); rules[i] = _firewallDao.persist(rules[i]); } txn.commit(); @@ -743,24 +977,6 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { return _forwardingDao.listByNetworkId(networkId); } - public boolean isLastOneToOneNatRule(FirewallRule ruleToCheck) { - List rules = _firewallDao.listByIpAndNotRevoked(ruleToCheck.getSourceIpAddressId(), false); - if (rules != null && !rules.isEmpty()) { - for (FirewallRuleVO rule : rules) { - if (ruleToCheck.getId() == rule.getId()) { - continue; - } - if (rule.isOneToOneNat()) { - return false; - } - } - } else { - return true; - } - - return true; - } - @Override public boolean disableOneToOneNat(long ipId){ Account caller = UserContext.current().getCaller(); @@ -772,7 +988,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { throw new InvalidParameterValueException("One to one nat is not enabled for the ip id=" + ipId); } - List rules = _firewallDao.listByIpAndNotRevoked(ipId, true); + List rules = _firewallDao.listByIpAndNotRevoked(ipId, Purpose.StaticNat); if (rules != null) { for (FirewallRuleVO rule : rules) { rule.setState(State.Revoke); @@ -782,7 +998,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } - if (applyPortForwardingRules(ipId, true, caller)) { + if (applyStaticNatRules(ipId, true, caller)) { ipAddress.setOneToOneNat(false); ipAddress.setAssociatedWithVmId(null); _ipAddressDao.update(ipAddress.getId(), ipAddress); @@ -793,23 +1009,57 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } - @Override - public List buildPortForwardingTOrules(List pfRules) { - if (pfRules != null) { - List rulesTO = new ArrayList(); - for (PortForwardingRule rule : pfRules) { - IpAddress sourceIp = _networkMgr.getIp(rule.getSourceIpAddressId()); - PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, sourceIp.getAddress().addr()); - rulesTO.add(ruleTO); - } - return rulesTO; - } else { - return null; - } - } - @Override public PortForwardingRule getPortForwardigRule(long ruleId) { return _forwardingDao.findById(ruleId); } + + + @Override + public FirewallRule getFirewallRule(long ruleId) { + return _firewallDao.findById(ruleId); + } + + protected Pair getUserVmGuestIpAddress(UserVm vm, boolean includeRemovedNics) { + Ip dstIp = null; + List nics; + + if (includeRemovedNics) { + nics = _networkMgr.getNicsIncludingRemoved(vm); + } else { + nics = _networkMgr.getNics(vm); + } + + for (Nic nic : nics) { + Network ntwk = _networkMgr.getNetwork(nic.getNetworkId()); + if (ntwk.getGuestType() == GuestIpType.Virtual && nic.getIp4Address() != null) { + dstIp = new Ip(nic.getIp4Address()); + return new Pair(ntwk, dstIp); + } + } + + throw new CloudRuntimeException("Unable to find ip address to map to in " + vm.getId()); + } + + @Override + public StaticNatRule buildStaticNatRule(FirewallRule rule) { + IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId()); + FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId()); + + if (ip == null || !ip.isOneToOneNat()) { + throw new InvalidParameterValueException("Source ip address of the rule id=" + rule.getId() + " is not static nat enabled"); + } + + UserVm vm = _vmDao.findById(ip.getAssociatedWithVmId()); + + if (vm == null) { + throw new InvalidParameterValueException("Static nat rule id=" + rule.getId() + " doesn't have vm assocaited with it"); + } + + Pair guestNic = getUserVmGuestIpAddress(vm, false); + Ip dstIp = guestNic.second(); + + return new StaticNatRuleImpl(ruleVO, dstIp.addr()); + } + } diff --git a/server/src/com/cloud/network/rules/StaticNatRuleImpl.java b/server/src/com/cloud/network/rules/StaticNatRuleImpl.java new file mode 100644 index 00000000000..ebc3366ce51 --- /dev/null +++ b/server/src/com/cloud/network/rules/StaticNatRuleImpl.java @@ -0,0 +1,108 @@ +/** + * 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.rules; + + +public class StaticNatRuleImpl implements StaticNatRule{ + long id; + String xid; + String protocol; + int portStart; + int portEnd; + State state; + long accountId; + long domainId; + long networkId; + long sourceIpAddressId; + String destIpAddress; + + public StaticNatRuleImpl(FirewallRuleVO rule, String dstIp) { + this.id = rule.getId(); + this.xid = rule.getXid(); + this.protocol = rule.getProtocol(); + this.portStart = rule.getSourcePortStart(); + this.portEnd = rule.getSourcePortEnd(); + this.state = rule.getState(); + this.accountId = rule.getAccountId(); + this.domainId = rule.getDomainId(); + this.networkId = rule.getNetworkId(); + this.sourceIpAddressId = rule.getSourceIpAddressId(); + this.destIpAddress = dstIp; + } + + @Override + public String getProtocol() { + return protocol; + } + + @Override + public int getSourcePortEnd() { + return portEnd; + } + + @Override + public Purpose getPurpose() { + return Purpose.StaticNat; + } + + @Override + public State getState() { + return state; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public long getDomainId() { + return domainId; + } + + @Override + public long getNetworkId() { + return networkId; + } + + @Override + public long getId() { + return id; + } + + @Override + public int getSourcePortStart() { + return portStart; + } + + @Override + public long getSourceIpAddressId() { + return sourceIpAddressId; + } + + @Override + public String getDestIpAddress() { + return destIpAddress; + } + + @Override + public String getXid() { + return xid; + } +} diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java index 99ece7394bd..89a9e69056e 100644 --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java @@ -21,9 +21,9 @@ import java.util.List; import javax.ejb.Local; +import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.State; import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -47,25 +47,31 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase sc = ApplicationSearch.create(); sc.setParameters("ipId", ipId); sc.setParameters("state", State.Staged); + sc.setParameters("purpose", Purpose.PortForwarding); return listBy(sc, null); } @@ -82,6 +89,8 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase listByVm(Long vmId) { SearchCriteria sc = AllRulesSearchByVM.create(); sc.setParameters("vmId", vmId); + sc.setParameters("purpose", Purpose.PortForwarding); + return listBy(sc, null); } @@ -90,6 +99,7 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase sc = ActiveRulesSearch.create(); sc.setParameters("ipId", ipId); sc.setParameters("state", State.Revoke); + sc.setParameters("purpose", Purpose.PortForwarding); return listBy(sc, null); } @@ -98,6 +108,7 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase listByIp(long ipId) { SearchCriteria sc = ActiveRulesSearch.create(); sc.setParameters("ipId", ipId); + sc.setParameters("purpose", Purpose.PortForwarding); return listBy(sc, null); } @@ -106,6 +117,8 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase listByNetworkId(long networkId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("networkId", networkId); + sc.setParameters("purpose", Purpose.PortForwarding); + return listBy(sc); } @@ -114,6 +127,8 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase sc = ActiveRulesSearchByAccount.create(); sc.setParameters("accountId", accountId); sc.setParameters("state", State.Revoke); + sc.setParameters("purpose", Purpose.PortForwarding); + return listBy(sc); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 84da906dc4b..31c48c4c533 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -1124,8 +1124,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager //Cleanup LB/PF rules before expunging the vm long vmId = vm.getId(); + //cleanup port forwarding rules - if (_rulesMgr.revokePortForwardingRule(vmId)) { + if (_rulesMgr.revokePortForwardingRulesForVm(vmId)) { + s_logger.debug("Port forwarding rules are removed successfully as a part of vm id=" + vmId + " expunge"); + } else { + s_logger.warn("Fail to remove port forwarding rules as a part of vm id=" + vmId + " expunge"); + } + + //cleanup static nat rules + if (_rulesMgr.revokeStaticNatRulesForVm(vmId)) { s_logger.debug("Port forwarding rules are removed successfully as a part of vm id=" + vmId + " expunge"); } else { s_logger.warn("Fail to remove port forwarding rules as a part of vm id=" + vmId + " expunge"); @@ -2203,7 +2211,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { UserVmVO userVm = profile.getVirtualMachine(); - List nics = _nicDao.listBy(userVm.getId()); + List nics = _nicDao.listByVmId(userVm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); if (network.getTrafficType() == TrafficType.Guest) { @@ -2226,7 +2234,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(), vm.getTemplateId(), null); _usageEventDao.persist(usageEvent); - List nics = _nicDao.listBy(vm.getId()); + List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); long isDefault = (nic.isDefaultNic()) ? 1 : 0; @@ -2296,7 +2304,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_STOP, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(), vm.getTemplateId(), null); _usageEventDao.persist(usageEvent); - List nics = _nicDao.listBy(vm.getId()); + List nics = _nicDao.listByVmId(vm.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); usageEvent = new UsageEventVO(EventTypes.EVENT_NETWORK_OFFERING_DELETE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), null, network.getNetworkOfferingId(), null, null); diff --git a/server/src/com/cloud/vm/dao/NicDao.java b/server/src/com/cloud/vm/dao/NicDao.java index 4a3f2480ce5..6d526660da5 100644 --- a/server/src/com/cloud/vm/dao/NicDao.java +++ b/server/src/com/cloud/vm/dao/NicDao.java @@ -9,7 +9,9 @@ import com.cloud.utils.db.GenericDao; import com.cloud.vm.NicVO; public interface NicDao extends GenericDao { - List listBy(long instanceId); + List listByVmId(long instanceId); + + List listByVmIdIncludingRemoved(long instanceId); List listIpAddressInNetwork(long networkConfigId); List listIncludingRemovedBy(long instanceId); diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java b/server/src/com/cloud/vm/dao/NicDaoImpl.java index 85e4f553785..8b8e0903bd4 100644 --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java @@ -43,12 +43,19 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { } @Override - public List listBy(long instanceId) { + public List listByVmId(long instanceId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("instance", instanceId); return listBy(sc); } + @Override + public List listByVmIdIncludingRemoved(long instanceId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("instance", instanceId); + return listIncludingRemovedBy(sc); + } + @Override public List listIncludingRemovedBy(long instanceId) { diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 5ed76e7b2e9..58107211e5c 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -493,7 +493,6 @@ CREATE TABLE `cloud`.`firewall_rules` ( `account_id` bigint unsigned NOT NULL COMMENT 'owner id', `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', `network_id` bigint unsigned NOT NULL COMMENT 'network id', - `is_static_nat` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if firewall rule is one to one nat rule', `xid` char(40) NOT NULL COMMENT 'external id', `created` datetime COMMENT 'Date created', PRIMARY KEY (`id`),