@Override
  public List<UserVmVO> listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd)
      throws PermissionDeniedException {
    Account caller = UserContext.current().getCaller();
    Long loadBalancerId = cmd.getId();
    Boolean applied = cmd.isApplied();

    if (applied == null) {
      applied = Boolean.TRUE;
    }

    LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId);
    if (loadBalancer == null) {
      return null;
    }

    _accountMgr.checkAccess(caller, null, loadBalancer);

    List<UserVmVO> loadBalancerInstances = new ArrayList<UserVmVO>();
    List<LoadBalancerVMMapVO> vmLoadBalancerMappings = null;

    vmLoadBalancerMappings = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId);

    List<Long> appliedInstanceIdList = new ArrayList<Long>();
    if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
      for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
        appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
      }
    }

    IPAddressVO addr = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId());
    List<UserVmVO> userVms =
        _vmDao.listVirtualNetworkInstancesByAcctAndZone(
            loadBalancer.getAccountId(), addr.getDataCenterId(), loadBalancer.getNetworkId());

    for (UserVmVO userVm : userVms) {
      // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
      switch (userVm.getState()) {
        case Destroyed:
        case Expunging:
        case Error:
        case Unknown:
          continue;
      }

      boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
      if ((isApplied && applied) || (!isApplied && !applied)) {
        loadBalancerInstances.add(userVm);
      }
    }

    return loadBalancerInstances;
  }
  @Override
  @DB
  public void deallocate(
      Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug(
          "Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address());
    }

    IPAddressVO ip =
        _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address());
    if (ip != null) {
      Transaction txn = Transaction.currentTxn();
      txn.start();
      _networkMgr.markIpAsUnavailable(ip.getId());
      _ipAddressDao.unassignIpAddress(ip.getId());
      txn.commit();
    }
    nic.deallocate();
  }
  @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();
      }
    }
  }