diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index 1c1c882bb73..c4149680f65 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -425,7 +425,8 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma } @DB - protected void removeRule(FirewallRule rule) { + @Override + public void removeRule(FirewallRule rule) { Transaction txn = Transaction.currentTxn(); txn.start(); @@ -527,7 +528,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma if (s_logger.isDebugEnabled()) { s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule); } - _firewallDao.remove(rule.getId()); + removeRule(rule); generateUsageEvent = true; } else if (rule.getState() == State.Add || rule.getState() == State.Active) { rule.setState(State.Revoke); diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index a777d9ad787..83e79c28250 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -675,7 +675,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa s_logger.warn("Unable to remove firewall rule id=" + lb.getId() + " as it has related firewall rule id=" + relatedRule.getId() + "; leaving it in Revoke state"); success = false; } else { - _firewallDao.remove(lb.getId()); + _firewallMgr.removeRule(lb); } _elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller); @@ -720,6 +720,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa } LoadBalancer result = _elbMgr.handleCreateLoadBalancerRule(lb, lbOwner, lb.getNetworkId()); + boolean performedIpAssoc = false; if (result == null) { IpAddress ip = null; Network guestNetwork = _networkMgr.getNetwork(lb.getNetworkId()); @@ -732,8 +733,13 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa try { if (ipAddressVO != null) { if (ipAddressVO.getAssociatedWithNetworkId() == null) { + //set networkId just for verification purposes + ipAddressVO.setAssociatedWithNetworkId(lb.getNetworkId()); + _networkMgr.checkIpForService(ipAddressVO, Service.Lb); + s_logger.debug("The ip is not associated with the network id="+ lb.getNetworkId() + " so assigning"); ipAddressVO = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId()); + boolean perfomedIpAssoc = true; } _networkMgr.checkIpForService(ipAddressVO, Service.Lb); } @@ -752,6 +758,15 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa s_logger.debug("Releasing system IP address " + ip + " as corresponding lb rule failed to create"); _networkMgr.handleSystemIpRelease(ip); } + // release ip address if ipassoc was perfored + if (performedIpAssoc) { + //if the rule is the last one for the ip address assigned to VPC, unassign it from the network + ip = _ipAddressDao.findById(ip.getId()); + if (ip != null && ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) { + s_logger.debug("Releasing VPC ip address " + ip + " as LB rule failed to create"); + _networkMgr.unassignIPFromVpcNetwork(ip.getId()); + } + } } } @@ -771,7 +786,6 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa long sourceIpId = lb.getSourceIpAddressId(); IPAddressVO ipAddr = _ipAddressDao.findById(sourceIpId); - Long networkId = ipAddr.getSourceNetworkId(); // make sure ip address exists if (ipAddr == null || !ipAddr.readyToUse()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id specified"); @@ -786,7 +800,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa _firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing, FirewallRuleType.User); - networkId = ipAddr.getAssociatedWithNetworkId(); + Long networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule ; specified sourceip id is not associated with any network"); ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); @@ -842,7 +856,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa txn.start(); _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); - _lbDao.remove(newRule.getId()); + removeLBRule(newRule); txn.commit(); } @@ -897,7 +911,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa boolean checkForReleaseElasticIp = false; txn.start(); if (lb.getState() == FirewallRule.State.Revoke) { - _lbDao.remove(lb.getId()); + removeLBRule(lb); s_logger.debug("LB " + lb.getId() + " is successfully removed"); checkForReleaseElasticIp = true; } else if (lb.getState() == FirewallRule.State.Add) { @@ -1290,4 +1304,17 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa return _lbDao.findById(lbId); } + @DB + protected void removeLBRule(LoadBalancerVO rule) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + _lbDao.remove(rule.getId()); + //if the rule is the last one for the ip address assigned to VPC, unassign it from the network + IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId()); + if (ip != null && ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) { + _networkMgr.unassignIPFromVpcNetwork(ip.getId()); + } + + txn.commit(); + } } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index f53ae247a76..c9ccc410745 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -310,6 +310,15 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian NicProfile publicNic = _itMgr.addVmToNetwork(router, publicNetwork, defaultNic); //setup public network if (publicNic != null) { + if (ipAddress.isSourceNat()) { + if (router.getPublicIpAddress() == null) { + DomainRouterVO routerVO = _routerDao.findById(router.getId()); + routerVO.setPublicIpAddress(ipAddress.getAddress().toString()); + routerVO.setPublicNetmask(ipAddress.getNetmask()); + routerVO.setPublicMacAddress(ipAddress.getMacAddress()); + _routerDao.update(routerVO.getId(), routerVO); + } + } publicNic.setDefaultNic(true); if (ipAddress != null) { IPAddressVO ipVO = _ipAddressDao.findById(ipAddress.getId()); diff --git a/server/src/com/cloud/network/rules/FirewallManager.java b/server/src/com/cloud/network/rules/FirewallManager.java index abf4403b3c6..1f9e0e8094e 100644 --- a/server/src/com/cloud/network/rules/FirewallManager.java +++ b/server/src/com/cloud/network/rules/FirewallManager.java @@ -76,4 +76,9 @@ public interface FirewallManager extends FirewallService { boolean addSystemFirewallRules(IPAddressVO ip, Account acct); + /** + * @param rule + */ + void removeRule(FirewallRule rule); + } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 3ce19c7f4a4..2e0d14ee42c 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -173,92 +173,113 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { Long networkId = rule.getNetworkId(); //associate ip address to network (if needed) + boolean performedIpAssoc = false; if (ipAddress.getAssociatedWithNetworkId() == null) { + //set networkId just for verification purposes + ipAddress.setAssociatedWithNetworkId(networkId); + _networkMgr.checkIpForService(ipAddress, Service.PortForwarding); + s_logger.debug("The ip is not associated with the network id="+ networkId + " so assigning"); try { ipAddress = _networkMgr.associateIPToGuestNetwork(ipAddrId, networkId); + performedIpAssoc = true; } catch (Exception ex) { throw new CloudRuntimeException("Failed to associate ip to network as " + "a part of port forwarding rule creation"); } + } else { + _networkMgr.checkIpForService(ipAddress, Service.PortForwarding); } - _networkMgr.checkIpForService(ipAddress, Service.PortForwarding); - - _firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), - rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User); - - Long accountId = ipAddress.getAllocatedToAccountId(); - Long domainId = ipAddress.getAllocatedInDomainId(); - - // start port can't be bigger than end port - if (rule.getDestinationPortStart() > rule.getDestinationPortEnd()) { - throw new InvalidParameterValueException("Start port can't be bigger than end port"); - } - - // check that the port ranges are of equal size - if ((rule.getDestinationPortEnd() - rule.getDestinationPortStart()) != (rule.getSourcePortEnd() - rule.getSourcePortStart())) { - throw new InvalidParameterValueException("Source port and destination port ranges should be of equal sizes."); - } - - // validate user VM exists - UserVm vm = _vmDao.findById(vmId); - if (vm == null) { - throw new InvalidParameterValueException("Unable to create port forwarding rule on address " + ipAddress + - ", invalid virtual machine id specified (" + vmId + ")."); - } else { - checkRuleAndUserVm(rule, vm, caller); - } - - - // Verify that vm has nic in the network - Ip dstIp = rule.getDestinationIpAddress(); - Nic guestNic = _networkMgr.getNicInNetwork(vmId, networkId); - if (guestNic == null || guestNic.getIp4Address() == null) { - throw new InvalidParameterValueException("Vm doesn't belong to network associated with ipAddress"); - } else { - dstIp = new Ip(guestNic.getIp4Address()); - } - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - PortForwardingRuleVO newRule = new PortForwardingRuleVO(rule.getXid(), rule.getSourceIpAddressId(), - rule.getSourcePortStart(), rule.getSourcePortEnd(), dstIp, rule.getDestinationPortStart(), - rule.getDestinationPortEnd(), rule.getProtocol().toLowerCase(), networkId, accountId, domainId, vmId); - newRule = _portForwardingDao.persist(newRule); - - // create firewallRule for 0.0.0.0/0 cidr - if (openFirewall) { - _firewallMgr.createRuleForAllCidrs(ipAddrId, caller, rule.getSourcePortStart(), rule.getSourcePortEnd(), - rule.getProtocol(), null, null, newRule.getId(), networkId); - } - try { - _firewallMgr.detectRulesConflict(newRule); - 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(), - ipAddress.getDataCenterId(), newRule.getId(), null); - _usageEventDao.persist(usageEvent); - txn.commit(); - return newRule; - } catch (Exception e) { - if (newRule != null) { - txn.start(); - // no need to apply the rule as it wasn't programmed on the backend yet - _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); - _portForwardingDao.remove(newRule.getId()); - txn.commit(); + _firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), + rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User); + + Long accountId = ipAddress.getAllocatedToAccountId(); + Long domainId = ipAddress.getAllocatedInDomainId(); + + // start port can't be bigger than end port + if (rule.getDestinationPortStart() > rule.getDestinationPortEnd()) { + throw new InvalidParameterValueException("Start port can't be bigger than end port"); } - if (e instanceof NetworkRuleConflictException) { - throw (NetworkRuleConflictException) e; + // check that the port ranges are of equal size + if ((rule.getDestinationPortEnd() - rule.getDestinationPortStart()) != (rule.getSourcePortEnd() - rule.getSourcePortStart())) { + throw new InvalidParameterValueException("Source port and destination port ranges should be of equal sizes."); + } + + // validate user VM exists + UserVm vm = _vmDao.findById(vmId); + if (vm == null) { + throw new InvalidParameterValueException("Unable to create port forwarding rule on address " + ipAddress + + ", invalid virtual machine id specified (" + vmId + ")."); + } else { + checkRuleAndUserVm(rule, vm, caller); + } + + + // Verify that vm has nic in the network + Ip dstIp = rule.getDestinationIpAddress(); + Nic guestNic = _networkMgr.getNicInNetwork(vmId, networkId); + if (guestNic == null || guestNic.getIp4Address() == null) { + throw new InvalidParameterValueException("Vm doesn't belong to network associated with ipAddress"); + } else { + dstIp = new Ip(guestNic.getIp4Address()); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + PortForwardingRuleVO newRule = new PortForwardingRuleVO(rule.getXid(), rule.getSourceIpAddressId(), + rule.getSourcePortStart(), rule.getSourcePortEnd(), dstIp, rule.getDestinationPortStart(), + rule.getDestinationPortEnd(), rule.getProtocol().toLowerCase(), networkId, accountId, domainId, vmId); + newRule = _portForwardingDao.persist(newRule); + + // create firewallRule for 0.0.0.0/0 cidr + if (openFirewall) { + _firewallMgr.createRuleForAllCidrs(ipAddrId, caller, rule.getSourcePortStart(), rule.getSourcePortEnd(), + rule.getProtocol(), null, null, newRule.getId(), networkId); + } + + try { + _firewallMgr.detectRulesConflict(newRule); + 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(), + ipAddress.getDataCenterId(), newRule.getId(), null); + _usageEventDao.persist(usageEvent); + txn.commit(); + return newRule; + } catch (Exception e) { + if (newRule != null) { + txn.start(); + // no need to apply the rule as it wasn't programmed on the backend yet + _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); + removePFRule(newRule); + txn.commit(); + } + + if (e instanceof NetworkRuleConflictException) { + throw (NetworkRuleConflictException) e; + } + + throw new CloudRuntimeException("Unable to add rule for the ip id=" + ipAddrId, e); + } + } finally { + // release ip address if ipassoc was perfored + if (performedIpAssoc) { + //if the rule is the last one for the ip address assigned to VPC, unassign it from the network + IpAddress ip = _ipAddressDao.findById(ipAddress.getId()); + if (ip != null && ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) { + s_logger.debug("Releasing VPC ip address " + ip + " as PF rule failed to create"); + _networkMgr.unassignIPFromVpcNetwork(ip.getId()); + } } - throw new CloudRuntimeException("Unable to add rule for the ip id=" + ipAddrId, e); } + + } @Override @@ -326,7 +347,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { txn.start(); // no need to apply the rule as it wasn't programmed on the backend yet _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); - _portForwardingDao.remove(newRule.getId()); + _firewallMgr.removeRule(newRule); txn.commit(); } @@ -1017,7 +1038,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { txn.start(); for (FirewallRuleVO newRule : rules) { - _portForwardingDao.remove(newRule.getId()); + _firewallMgr.removeRule(newRule); } txn.commit(); } @@ -1271,4 +1292,18 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } } } + + @DB + protected void removePFRule(PortForwardingRuleVO rule) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + _portForwardingDao.remove(rule.getId()); + //if the rule is the last one for the ip address assigned to VPC, unassign it from the network + IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId()); + if (ip != null && ip.getVpcId() != null && _firewallDao.listByIp(ip.getId()).isEmpty()) { + _networkMgr.unassignIPFromVpcNetwork(ip.getId()); + } + + txn.commit(); + } } diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java index 2bdaea58e44..e4fbbb0e77e 100644 --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java @@ -16,8 +16,6 @@ import java.util.List; import javax.ejb.Local; -import org.apache.log4j.Logger; - import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.State; @@ -30,7 +28,6 @@ import com.cloud.utils.db.SearchCriteria.Op; @Local(value=PortForwardingRulesDao.class) public class PortForwardingRulesDaoImpl extends GenericDaoBase implements PortForwardingRulesDao { - private static final Logger s_logger = Logger.getLogger(PortForwardingRulesDaoImpl.class); protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder ApplicationSearch;