@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();
      }
    }
  }