protected DomainRouterVO findElbVmForLb(FirewallRule lb) { // TODO: use a table to lookup
   ElasticLbVmMapVO map = _elbVmMapDao.findOneByIp(lb.getSourceIpAddressId());
   if (map == null) {
     return null;
   }
   DomainRouterVO elbVm = _routerDao.findById(map.getElbVmId());
   return elbVm;
 }
 private DomainRouterVO findELBVmWithCapacity(Network guestNetwork, IPAddressVO ipAddr) {
   List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
   if (unusedElbVms.size() > 0) {
     List<DomainRouterVO> candidateVms = new ArrayList<DomainRouterVO>();
     for (DomainRouterVO candidateVm : unusedElbVms) {
       if (candidateVm.getPodIdToDeployIn() == getPodIdForDirectIp(ipAddr))
         candidateVms.add(candidateVm);
     }
     return candidateVms.size() == 0
         ? null
         : candidateVms.get(new Random().nextInt(candidateVms.size()));
   }
   return null;
 }
  void garbageCollectUnusedElbVms() {
    List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
    if (unusedElbVms != null && unusedElbVms.size() > 0)
      s_logger.info("Found " + unusedElbVms.size() + " unused ELB vms");
    Set<Long> currentGcCandidates = new HashSet<Long>();
    for (DomainRouterVO elbVm : unusedElbVms) {
      currentGcCandidates.add(elbVm.getId());
    }
    _gcCandidateElbVmIds.retainAll(currentGcCandidates);
    currentGcCandidates.removeAll(_gcCandidateElbVmIds);
    User user = _accountService.getSystemUser();
    for (Long elbVmId : _gcCandidateElbVmIds) {
      DomainRouterVO elbVm = _routerDao.findById(elbVmId);
      boolean gceed = false;

      try {
        s_logger.info("Attempting to stop ELB VM: " + elbVm);
        stop(elbVm, true, user, _systemAcct);
        gceed = true;
      } catch (ConcurrentOperationException e) {
        s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
      } catch (ResourceUnavailableException e) {
        s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
        continue;
      }
      if (gceed) {
        try {
          s_logger.info("Attempting to destroy ELB VM: " + elbVm);
          _itMgr.expunge(elbVm, user, _systemAcct);
        } catch (ResourceUnavailableException e) {
          s_logger.warn("Unable to destroy unused ELB vm " + elbVm + " due to ", e);
          gceed = false;
        }
      }
      if (!gceed) {
        currentGcCandidates.add(elbVm.getId());
      }
    }
    _gcCandidateElbVmIds = currentGcCandidates;
  }
  @Override
  public boolean finalizeCommandsOnStart(
      Commands cmds, VirtualMachineProfile<DomainRouterVO> profile) {
    DomainRouterVO elbVm = profile.getVirtualMachine();
    DataCenterVO dcVo = _dcDao.findById(elbVm.getDataCenterId());

    NicProfile controlNic = null;
    Long guestNetworkId = null;

    if (profile.getHypervisorType() == HypervisorType.VMware
        && dcVo.getNetworkType() == NetworkType.Basic) {
      // TODO this is a ugly to test hypervisor type here
      // for basic network mode, we will use the guest NIC for control NIC
      for (NicProfile nic : profile.getNics()) {
        if (nic.getTrafficType() == TrafficType.Guest && nic.getIp4Address() != null) {
          controlNic = nic;
          guestNetworkId = nic.getNetworkId();
        }
      }
    } else {
      for (NicProfile nic : profile.getNics()) {
        if (nic.getTrafficType() == TrafficType.Control && nic.getIp4Address() != null) {
          controlNic = nic;
        } else if (nic.getTrafficType() == TrafficType.Guest) {
          guestNetworkId = nic.getNetworkId();
        }
      }
    }

    if (controlNic == null) {
      s_logger.error("Control network doesn't exist for the ELB vm " + elbVm);
      return false;
    }

    cmds.addCommand(
        "checkSsh",
        new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922));

    // Re-apply load balancing rules
    List<LoadBalancerVO> lbs = _elbVmMapDao.listLbsForElbVm(elbVm.getId());
    List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
    for (LoadBalancerVO lb : lbs) {
      List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
      List<LbStickinessPolicy> policyList = _lbMgr.getStickinessPolicies(lb.getId());
      List<LbHealthCheckPolicy> hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId());
      LoadBalancingRule loadBalancing =
          new LoadBalancingRule(lb, dstList, policyList, hcPolicyList);
      lbRules.add(loadBalancing);
    }

    s_logger.debug(
        "Found "
            + lbRules.size()
            + " load balancing rule(s) to apply as a part of ELB vm "
            + elbVm
            + " start.");
    if (!lbRules.isEmpty()) {
      createApplyLoadBalancingRulesCommands(lbRules, elbVm, cmds, guestNetworkId);
    }

    return true;
  }
  @Override
  @DB
  public LoadBalancer handleCreateLoadBalancerRule(
      CreateLoadBalancerRuleCmd lb, Account account, long networkId)
      throws InsufficientAddressCapacityException, NetworkRuleConflictException {
    // this part of code is executed when the LB provider is Elastic Load Balancer vm
    if (!_networkModel.isProviderSupportServiceInNetwork(
        lb.getNetworkId(), Service.Lb, Provider.ElasticLoadBalancerVm)) {
      return null;
    }

    Long ipId = lb.getSourceIpAddressId();
    if (ipId != null) {
      return null;
    }
    boolean newIp = false;
    account = _accountDao.acquireInLockTable(account.getId());
    if (account == null) {
      s_logger.warn("ELB: CreateLoadBalancer: Failed to acquire lock on account");
      throw new CloudRuntimeException("Failed to acquire lock on account");
    }
    try {
      List<LoadBalancerVO> existingLbs =
          findExistingLoadBalancers(
              lb.getName(),
              lb.getSourceIpAddressId(),
              lb.getAccountId(),
              lb.getDomainId(),
              lb.getSourcePortStart());
      if (existingLbs == null) {
        existingLbs =
            findExistingLoadBalancers(
                lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), null);
        if (existingLbs == null) {
          if (lb.getSourceIpAddressId() != null) {
            existingLbs =
                findExistingLoadBalancers(
                    lb.getName(), null, lb.getAccountId(), lb.getDomainId(), null);
            if (existingLbs != null) {
              throw new InvalidParameterValueException(
                  "Supplied LB name "
                      + lb.getName()
                      + " is not associated with IP "
                      + lb.getSourceIpAddressId());
            }
          } else {
            s_logger.debug(
                "Could not find any existing frontend ips for this account for this LB rule, acquiring a new frontent IP for ELB");
            PublicIp ip = allocDirectIp(account, networkId);
            ipId = ip.getId();
            newIp = true;
          }
        } else {
          ipId = existingLbs.get(0).getSourceIpAddressId();
          s_logger.debug(
              "ELB: Found existing frontend ip for this account for this LB rule " + ipId);
        }
      } else {
        s_logger.warn("ELB: Found existing load balancers matching requested new LB");
        throw new NetworkRuleConflictException(
            "ELB: Found existing load balancers matching requested new LB");
      }

      Network network = _networkModel.getNetwork(networkId);
      IPAddressVO ipAddr = _ipAddressDao.findById(ipId);

      LoadBalancer result = null;
      try {
        lb.setSourceIpAddressId(ipId);
        result = _lbMgr.createLoadBalancer(lb, false);
      } catch (NetworkRuleConflictException e) {
        s_logger.warn("Failed to create LB rule, not continuing with ELB deployment");
        if (newIp) {
          releaseIp(ipId, UserContext.current().getCallerUserId(), account);
        }
        throw e;
      }

      DomainRouterVO elbVm = null;

      if (existingLbs == null) {
        elbVm = findELBVmWithCapacity(network, ipAddr);
        if (elbVm == null) {
          elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId());
          if (elbVm == null) {
            s_logger.warn(
                "Failed to deploy a new ELB vm for ip "
                    + ipAddr
                    + " in network "
                    + network
                    + "lb name="
                    + lb.getName());
            if (newIp) releaseIp(ipId, UserContext.current().getCallerUserId(), account);
          }
        }

      } else {
        ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(ipId);
        if (elbVmMap != null) {
          elbVm = _routerDao.findById(elbVmMap.getElbVmId());
        }
      }

      if (elbVm == null) {
        s_logger.warn("No ELB VM can be found or deployed");
        s_logger.warn("Deleting LB since we failed to deploy ELB VM");
        _lbDao.remove(result.getId());
        return null;
      }

      ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId(), result.getId());
      _elbVmMapDao.persist(mapping);
      return result;

    } finally {
      if (account != null) {
        _accountDao.releaseFromLockTable(account.getId());
      }
    }
  }