mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
VPC: set networkId to be null for IP address when the last PF/LB rule is removed for it and the IP belongs to VPC
Conflicts: server/src/com/cloud/network/rules/RulesManagerImpl.java
This commit is contained in:
parent
8d16d7f94f
commit
2dc1a286f6
@ -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);
|
||||
|
||||
@ -675,7 +675,7 @@ public class LoadBalancingRulesManagerImpl<Type> 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<Type> 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<Type> 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<Type> 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<Type> 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<Type> 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<Type> implements LoadBalancingRulesMa
|
||||
|
||||
txn.start();
|
||||
_firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false);
|
||||
_lbDao.remove(newRule.getId());
|
||||
removeLBRule(newRule);
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
@ -897,7 +911,7 @@ public class LoadBalancingRulesManagerImpl<Type> 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<Type> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -76,4 +76,9 @@ public interface FirewallManager extends FirewallService {
|
||||
|
||||
boolean addSystemFirewallRules(IPAddressVO ip, Account acct);
|
||||
|
||||
/**
|
||||
* @param rule
|
||||
*/
|
||||
void removeRule(FirewallRule rule);
|
||||
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<PortForwardingRuleVO, Long> implements PortForwardingRulesDao {
|
||||
private static final Logger s_logger = Logger.getLogger(PortForwardingRulesDaoImpl.class);
|
||||
|
||||
protected final SearchBuilder<PortForwardingRuleVO> AllFieldsSearch;
|
||||
protected final SearchBuilder<PortForwardingRuleVO> ApplicationSearch;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user