@DB protected boolean applyLoadBalancerRules(List<LoadBalancerVO> lbs) throws ResourceUnavailableException { Transaction txn = Transaction.currentTxn(); List<LoadBalancingRule> rules = new ArrayList<LoadBalancingRule>(); for (LoadBalancerVO lb : lbs) { List<LbDestination> dstList = getExistingDestinations(lb.getId()); LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList); rules.add(loadBalancing); } if (!_networkMgr.applyRules(rules, false)) { s_logger.debug("LB rules are not completely applied"); return false; } for (LoadBalancerVO lb : lbs) { txn.start(); if (lb.getState() == FirewallRule.State.Revoke) { _lbDao.remove(lb.getId()); s_logger.warn("LB " + lb.getId() + " is successfully removed"); } else if (lb.getState() == FirewallRule.State.Add) { lb.setState(FirewallRule.State.Active); s_logger.warn("LB rule " + lb.getId() + " state is set to Active"); _lbDao.persist(lb); } // remove LB-Vm mappings that were state to revoke List<LoadBalancerVMMapVO> lbVmMaps = _lb2VmMapDao.listByLoadBalancerId(lb.getId(), true); List<Long> instanceIds = new ArrayList<Long>(); for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { instanceIds.add(lbVmMap.getInstanceId()); } if (!instanceIds.isEmpty()) { _lb2VmMapDao.remove(lb.getId(), instanceIds, null); s_logger.debug( "Load balancer rule id " + lb.getId() + " is removed for vms " + instanceIds); } if (_lb2VmMapDao.listByLoadBalancerId(lb.getId()).isEmpty()) { lb.setState(FirewallRule.State.Add); _lbDao.persist(lb); s_logger.debug( "LB rule " + lb.getId() + " state is set to Add as there are no more active LB-VM mappings"); } txn.commit(); } return true; }
@Override @ActionEvent( eventType = EventTypes.EVENT_LOAD_BALANCER_UPDATE, eventDescription = "updating load balancer", async = true) public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) { Long lbRuleId = cmd.getId(); String name = cmd.getLoadBalancerName(); String description = cmd.getDescription(); String algorithm = cmd.getAlgorithm(); LoadBalancerVO lb = _lbDao.findById(lbRuleId); if (name != null) { lb.setName(name); } if (description != null) { lb.setDescription(description); } if (algorithm != null) { lb.setAlgorithm(algorithm); } _lbDao.update(lbRuleId, lb); // If algorithm is changed, have to reapply the lb config if (algorithm != null) { try { lb.setState(FirewallRule.State.Add); _lbDao.persist(lb); applyLoadBalancerConfig(lbRuleId); } catch (ResourceUnavailableException e) { s_logger.warn( "Unable to apply the load balancer config because resource is unavaliable.", e); } } return lb; }
private boolean removeFromLoadBalancerInternal(long loadBalancerId, List<Long> instanceIds) { UserContext caller = UserContext.current(); LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(loadBalancerId)); if (loadBalancer == null) { throw new InvalidParameterException("Invalid load balancer value: " + loadBalancerId); } _accountMgr.checkAccess(caller.getCaller(), null, loadBalancer); try { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); for (long instanceId : instanceIds) { LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); map.setRevoke(true); _lb2VmMapDao.persist(map); s_logger.debug( "Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId); } if (!applyLoadBalancerConfig(loadBalancerId)) { s_logger.warn( "Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds); throw new CloudRuntimeException( "Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds); } } catch (ResourceUnavailableException e) { s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); return false; } return true; }
@DB public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb, boolean openFirewall) throws NetworkRuleConflictException { long ipId = lb.getSourceIpAddressId(); UserContext caller = UserContext.current(); int srcPortStart = lb.getSourcePortStart(); int defPortStart = lb.getDefaultPortStart(); int srcPortEnd = lb.getSourcePortEnd(); IPAddressVO ipAddr = _ipAddressDao.findById(lb.getSourceIpAddressId()); Long networkId = ipAddr.getSourceNetworkId(); // make sure ip address exists if (ipAddr == null || !ipAddr.readyToUse()) { throw new InvalidParameterValueException( "Unable to create load balancer rule, invalid IP address id" + ipId); } _firewallMgr.validateFirewallRule( caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing); networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { throw new InvalidParameterValueException( "Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network"); } NetworkVO network = _networkDao.findById(networkId); _accountMgr.checkAccess(caller.getCaller(), null, ipAddr); // verify that lb service is supported by the network if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) { throw new InvalidParameterValueException( "LB service is not supported in network id= " + networkId); } Transaction txn = Transaction.currentTxn(); txn.start(); LoadBalancerVO newRule = new LoadBalancerVO( lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(), lb.getAlgorithm(), network.getId(), ipAddr.getAccountId(), ipAddr.getDomainId()); newRule = _lbDao.persist(newRule); if (openFirewall) { _firewallMgr.createRuleForAllCidrs( ipId, caller.getCaller(), lb.getSourcePortStart(), lb.getSourcePortEnd(), lb.getProtocol(), null, null, newRule.getId()); } boolean success = true; try { _firewallMgr.detectRulesConflict(newRule, ipAddr); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } s_logger.debug( "Load balancer " + newRule.getId() + " for Ip address id=" + ipId + ", public port " + srcPortStart + ", private port " + defPortStart + " is added successfully."); UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId()); UsageEventVO usageEvent = new UsageEventVO( EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(), ipAddr.getDataCenterId(), newRule.getId(), null); _usageEventDao.persist(usageEvent); txn.commit(); return newRule; } catch (Exception e) { success = false; if (e instanceof NetworkRuleConflictException) { throw (NetworkRuleConflictException) e; } throw new CloudRuntimeException( "Unable to add rule for ip address id=" + newRule.getSourceIpAddressId(), e); } finally { if (!success && newRule != null) { txn.start(); _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); _lbDao.remove(newRule.getId()); txn.commit(); } } }
@DB public boolean deleteLoadBalancerRule( long loadBalancerId, boolean apply, Account caller, long callerUserId) { LoadBalancerVO lb = _lbDao.findById(loadBalancerId); Transaction txn = Transaction.currentTxn(); boolean generateUsageEvent = false; boolean success = true; txn.start(); if (lb.getState() == FirewallRule.State.Staged) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found a rule that is still in stage state so just removing it: " + lb); } generateUsageEvent = true; } else if (lb.getState() == FirewallRule.State.Add || lb.getState() == FirewallRule.State.Active) { lb.setState(FirewallRule.State.Revoke); _lbDao.persist(lb); generateUsageEvent = true; } List<LoadBalancerVMMapVO> maps = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId); if (maps != null) { for (LoadBalancerVMMapVO map : maps) { map.setRevoke(true); _lb2VmMapDao.persist(map); s_logger.debug( "Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + map.getInstanceId()); } } if (generateUsageEvent) { // Generate usage event right after all rules were marked for revoke UsageEventVO usageEvent = new UsageEventVO( EventTypes.EVENT_LOAD_BALANCER_DELETE, lb.getAccountId(), 0, lb.getId(), null); _usageEventDao.persist(usageEvent); } txn.commit(); if (apply) { try { if (!applyLoadBalancerConfig(loadBalancerId)) { s_logger.warn("Unable to apply the load balancer config"); return false; } } catch (ResourceUnavailableException e) { s_logger.warn( "Unable to apply the load balancer config because resource is unavaliable.", e); return false; } } FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(lb.getId()); if (relatedRule != null) { 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()); } _elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller); if (success) { s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully"); } return success; }
@Override @DB @ActionEvent( eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true) public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds) { UserContext ctx = UserContext.current(); Account caller = ctx.getCaller(); LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); if (loadBalancer == null) { throw new InvalidParameterValueException( "Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found."); } List<LoadBalancerVMMapVO> mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false); Set<Long> mappedInstanceIds = new HashSet<Long>(); for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId())); } List<UserVm> vmsToAdd = new ArrayList<UserVm>(); for (Long instanceId : instanceIds) { if (mappedInstanceIds.contains(instanceId)) { throw new InvalidParameterValueException( "VM " + instanceId + " is already mapped to load balancer."); } UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { throw new InvalidParameterValueException("Invalid instance id: " + instanceId); } _rulesMgr.checkRuleAndUserVm(loadBalancer, vm, caller); if (vm.getAccountId() != loadBalancer.getAccountId()) { throw new PermissionDeniedException( "Cannot add virtual machines that do not belong to the same owner."); } // Let's check to make sure the vm has a nic in the same network as the load balancing rule. List<? extends Nic> nics = _networkMgr.getNics(vm.getId()); Nic nicInSameNetwork = null; for (Nic nic : nics) { if (nic.getNetworkId() == loadBalancer.getNetworkId()) { nicInSameNetwork = nic; break; } } if (nicInSameNetwork == null) { throw new InvalidParameterValueException( "VM " + instanceId + " cannot be added because it doesn't belong in the same network."); } if (s_logger.isDebugEnabled()) { s_logger.debug("Adding " + vm + " to the load balancer pool"); } vmsToAdd.add(vm); } Transaction txn = Transaction.currentTxn(); txn.start(); for (UserVm vm : vmsToAdd) { LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false); map = _lb2VmMapDao.persist(map); } txn.commit(); try { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); applyLoadBalancerConfig(loadBalancerId); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); return false; } return true; }