public void createOrUpdateIpCapacity(Long dcId, Long podId, short capacityType) {
    SearchCriteria<CapacityVO> capacitySC = _capacityDao.createSearchCriteria();

    List<CapacityVO> capacities = _capacityDao.search(capacitySC, null);
    capacitySC = _capacityDao.createSearchCriteria();
    capacitySC.addAnd("podId", SearchCriteria.Op.EQ, podId);
    capacitySC.addAnd("dataCenterId", SearchCriteria.Op.EQ, dcId);
    capacitySC.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType);

    int totalIPs;
    int allocatedIPs;
    capacities = _capacityDao.search(capacitySC, null);
    if (capacityType == CapacityVO.CAPACITY_TYPE_PRIVATE_IP) {
      totalIPs = _privateIPAddressDao.countIPs(podId, dcId, false);
      allocatedIPs = _privateIPAddressDao.countIPs(podId, dcId, true);
    } else if (capacityType == CapacityVO.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP) {
      totalIPs = _publicIPAddressDao.countIPsForNetwork(dcId, false, VlanType.VirtualNetwork);
      allocatedIPs = _publicIPAddressDao.countIPsForNetwork(dcId, true, VlanType.VirtualNetwork);
    } else {
      totalIPs = _publicIPAddressDao.countIPsForNetwork(dcId, false, VlanType.DirectAttached);
      allocatedIPs = _publicIPAddressDao.countIPsForNetwork(dcId, true, VlanType.DirectAttached);
    }

    if (capacities.size() == 0) {
      CapacityVO newPublicIPCapacity =
          new CapacityVO(null, dcId, podId, null, allocatedIPs, totalIPs, capacityType);
      _capacityDao.persist(newPublicIPCapacity);
    } else if (!(capacities.get(0).getUsedCapacity() == allocatedIPs
        && capacities.get(0).getTotalCapacity() == totalIPs)) {
      CapacityVO capacity = capacities.get(0);
      capacity.setUsedCapacity(allocatedIPs);
      capacity.setTotalCapacity(totalIPs);
      _capacityDao.update(capacity.getId(), capacity);
    }
  }
 public void releaseIp(long ipId, long userId, Account caller) {
   s_logger.info("ELB: Release public IP for loadbalancing " + ipId);
   IPAddressVO ipvo = _ipAddressDao.findById(ipId);
   ipvo.setAssociatedWithNetworkId(null);
   _ipAddressDao.update(ipvo.getId(), ipvo);
   _networkMgr.disassociatePublicIpAddress(ipId, userId, caller);
   _ipAddressDao.unassignIpAddress(ipId);
 }
 @Override
 public List<IPAddressVO> listAllocatedDirectIps(long zoneId) {
   SearchCriteria<IPAddressVO> sc = AllocatedIpSearch.create();
   sc.setParameters("dc", zoneId);
   sc.setJoinParameters("network", "guestType", Network.GuestType.Shared);
   return _ipAddressDao.search(sc, null);
 }
  @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();
  }
  @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;
  }
  @DB
  public PublicIp allocDirectIp(Account account, long guestNetworkId)
      throws InsufficientAddressCapacityException {
    Network frontEndNetwork = _networkModel.getNetwork(guestNetworkId);
    Transaction txn = Transaction.currentTxn();
    txn.start();

    PublicIp ip =
        _networkMgr.assignPublicIpAddress(
            frontEndNetwork.getDataCenterId(),
            null,
            account,
            VlanType.DirectAttached,
            frontEndNetwork.getId(),
            null,
            true);
    IPAddressVO ipvo = _ipAddressDao.findById(ip.getId());
    ipvo.setAssociatedWithNetworkId(frontEndNetwork.getId());
    _ipAddressDao.update(ipvo.getId(), ipvo);
    txn.commit();
    s_logger.info("Acquired frontend IP for ELB " + ip);

    return ip;
  }
  @Override
  public boolean applyRules(
      List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB)
      throws ResourceUnavailableException {
    boolean success = true;
    if (rules == null || rules.size() == 0) {
      s_logger.debug("There are no rules to forward to the network elements");
      return true;
    }
    Purpose purpose = rules.get(0).getPurpose();
    if (!_ipAddrMgr.applyRules(rules, purpose, this, continueOnError)) {
      s_logger.warn("Rules are not completely applied");
      return false;
    } else {
      if (updateRulesInDB) {
        for (FirewallRule rule : rules) {
          if (rule.getState() == FirewallRule.State.Revoke) {
            FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(rule.getId());
            if (relatedRule != null) {
              s_logger.warn(
                  "Can't remove the firewall rule id="
                      + rule.getId()
                      + " as it has related firewall rule id="
                      + relatedRule.getId()
                      + "; leaving it in Revoke state");
              success = false;
            } else {
              removeRule(rule);
              if (rule.getSourceIpAddressId() != null) {
                // 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());
                _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), rule.getNetworkId());
              }
            }
          } else if (rule.getState() == FirewallRule.State.Add) {
            FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId());
            ruleVO.setState(FirewallRule.State.Active);
            _firewallDao.update(ruleVO.getId(), ruleVO);
          }
        }
      }
    }

    return success;
  }
  @Override
  public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
    AllocatedIpSearch = _ipAddressDao.createSearchBuilder();
    AllocatedIpSearch.and("allocated", AllocatedIpSearch.entity().getAllocatedTime(), Op.NNULL);
    AllocatedIpSearch.and("dc", AllocatedIpSearch.entity().getDataCenterId(), Op.EQ);
    SearchBuilder<NetworkVO> networkJoin = _networksDao.createSearchBuilder();
    networkJoin.and("guestType", networkJoin.entity().getGuestType(), Op.EQ);
    AllocatedIpSearch.join(
        "network",
        networkJoin,
        AllocatedIpSearch.entity().getSourceNetworkId(),
        networkJoin.entity().getId(),
        JoinBuilder.JoinType.INNER);
    AllocatedIpSearch.done();

    _networkStatsInterval =
        NumbersUtil.parseInt(_configDao.getValue(Config.DirectNetworkStatsInterval.key()), 86400);
    _TSinclZones = _configDao.getValue(Config.TrafficSentinelIncludeZones.key());
    _TSexclZones = _configDao.getValue(Config.TrafficSentinelExcludeZones.key());
    _agentMgr.registerForHostEvents(
        new DirectNetworkStatsListener(_networkStatsInterval), true, false, false);
    _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
    return true;
  }
  @Override
  public List<LoadBalancerVO> searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) {
    Account caller = UserContext.current().getCaller();
    Long ipId = cmd.getPublicIpId();
    Long zoneId = cmd.getZoneId();
    String path = null;

    Pair<String, Long> accountDomainPair =
        _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId());
    String accountName = accountDomainPair.first();
    Long domainId = accountDomainPair.second();

    if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN
        || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
      Domain domain = _domainMgr.getDomain(caller.getDomainId());
      path = domain.getPath();
    }

    Filter searchFilter =
        new Filter(LoadBalancerVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

    Object id = cmd.getId();
    Object name = cmd.getLoadBalancerRuleName();
    Object keyword = cmd.getKeyword();
    Object instanceId = cmd.getVirtualMachineId();

    SearchBuilder<LoadBalancerVO> sb = _lbDao.createSearchBuilder();
    sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
    sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
    sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ);
    sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
    sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);

    if (instanceId != null) {
      SearchBuilder<LoadBalancerVMMapVO> lbVMSearch = _lb2VmMapDao.createSearchBuilder();
      lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
      sb.join(
          "lbVMSearch",
          lbVMSearch,
          sb.entity().getId(),
          lbVMSearch.entity().getLoadBalancerId(),
          JoinBuilder.JoinType.INNER);
    }

    if (path != null) {
      // for domain admin we should show only subdomains information
      SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
      domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
      sb.join(
          "domainSearch",
          domainSearch,
          sb.entity().getDomainId(),
          domainSearch.entity().getId(),
          JoinBuilder.JoinType.INNER);
    }

    if (zoneId != null) {
      SearchBuilder<IPAddressVO> ipSearch = _ipAddressDao.createSearchBuilder();
      ipSearch.and("zoneId", ipSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
      sb.join(
          "ipSearch",
          ipSearch,
          sb.entity().getSourceIpAddressId(),
          ipSearch.entity().getId(),
          JoinBuilder.JoinType.INNER);
    }

    SearchCriteria<LoadBalancerVO> sc = sb.create();
    if (keyword != null) {
      SearchCriteria<LoadBalancerVO> ssc = _lbDao.createSearchCriteria();
      ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
      ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

      sc.addAnd("name", SearchCriteria.Op.SC, ssc);
    }

    if (name != null) {
      sc.setParameters("name", "%" + name + "%");
    }

    if (id != null) {
      sc.setParameters("id", id);
    }

    if (ipId != null) {
      sc.setParameters("sourceIpAddress", ipId);
    }

    if (instanceId != null) {
      sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
    }

    if (domainId != null) {
      sc.setParameters("domainId", domainId);
      if (accountName != null) {
        Account account = _accountMgr.getActiveAccountByName(accountName, domainId);
        sc.setParameters("accountId", account.getId());
      }
    }

    if (path != null) {
      sc.setJoinParameters("domainSearch", "path", path + "%");
    }

    if (zoneId != null) {
      sc.setJoinParameters("ipSearch", "zoneId", zoneId);
    }

    return _lbDao.search(sc, searchFilter);
  }
  @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();
      }
    }
  }
  @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());
      }
    }
  }
  @DB
  protected FirewallRule createFirewallRule(
      Long ipAddrId,
      Account caller,
      String xId,
      Integer portStart,
      Integer portEnd,
      String protocol,
      List<String> sourceCidrList,
      Integer icmpCode,
      Integer icmpType,
      Long relatedRuleId,
      FirewallRule.FirewallRuleType type,
      Long networkId,
      FirewallRule.TrafficType trafficType)
      throws NetworkRuleConflictException {

    IPAddressVO ipAddress = null;
    if (ipAddrId != null) {
      // this for ingress firewall rule, for egress id is null
      ipAddress = _ipAddressDao.findById(ipAddrId);
      // Validate ip address
      if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) {
        throw new InvalidParameterValueException(
            "Unable to create firewall rule; " + "couldn't locate IP address by id in the system");
      }
      _networkModel.checkIpForService(ipAddress, Service.Firewall, null);
    }

    validateFirewallRule(
        caller,
        ipAddress,
        portStart,
        portEnd,
        protocol,
        Purpose.Firewall,
        type,
        networkId,
        trafficType);

    // icmp code and icmp type can't be passed in for any other protocol rather than icmp
    if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
      throw new InvalidParameterValueException(
          "Can specify icmpCode and icmpType for ICMP protocol only");
    }

    if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) {
      throw new InvalidParameterValueException(
          "Can't specify start/end port when protocol is ICMP");
    }

    Long accountId = null;
    Long domainId = null;

    if (ipAddress != null) {
      // Ingress firewall rule
      accountId = ipAddress.getAllocatedToAccountId();
      domainId = ipAddress.getAllocatedInDomainId();
    } else if (networkId != null) {
      // egress firewall rule
      Network network = _networkModel.getNetwork(networkId);
      accountId = network.getAccountId();
      domainId = network.getDomainId();
    }

    Transaction txn = Transaction.currentTxn();
    txn.start();

    FirewallRuleVO newRule =
        new FirewallRuleVO(
            xId,
            ipAddrId,
            portStart,
            portEnd,
            protocol.toLowerCase(),
            networkId,
            accountId,
            domainId,
            Purpose.Firewall,
            sourceCidrList,
            icmpCode,
            icmpType,
            relatedRuleId,
            trafficType);
    newRule.setType(type);
    newRule = _firewallDao.persist(newRule);

    if (type == FirewallRuleType.User) detectRulesConflict(newRule);

    if (!_firewallDao.setStateToAdd(newRule)) {
      throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
    }
    CallContext.current().setEventDetails("Rule Id: " + newRule.getId());

    txn.commit();

    return newRule;
  }
  @Override
  public boolean implement(
      Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
      throws ConcurrentOperationException, ResourceUnavailableException,
          InsufficientCapacityException {
    DataCenter zone = _configMgr.getZone(network.getDataCenterId());

    if (zone.getNetworkType() == NetworkType.Basic) {
      s_logger.debug("Not handling network implement in zone of type " + NetworkType.Basic);
      return false;
    }

    if (!canHandle(network)) {
      return false;
    }

    List<CiscoVnmcControllerVO> devices =
        _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
    if (devices.isEmpty()) {
      s_logger.error("No Cisco Vnmc device on network " + network.getName());
      return false;
    }

    List<CiscoAsa1000vDeviceVO> asaList =
        _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
    if (asaList.isEmpty()) {
      s_logger.debug("No Cisco ASA 1000v device on network " + network.getName());
      return false;
    }

    NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
    if (asaForNetwork != null) {
      s_logger.debug("Cisco ASA 1000v device already associated with network " + network.getName());
      return true;
    }

    if (!_networkModel.isProviderSupportServiceInNetwork(
        network.getId(), Service.SourceNat, Provider.CiscoVnmc)) {
      s_logger.error(
          "SourceNat service is not provided by Cisco Vnmc device on network " + network.getName());
      return false;
    }

    Transaction txn = Transaction.currentTxn();
    boolean status = false;
    try {
      txn.start();

      // ensure that there is an ASA 1000v assigned to this network
      CiscoAsa1000vDevice assignedAsa = assignAsa1000vToNetwork(network);
      if (assignedAsa == null) {
        s_logger.error("Unable to assign ASA 1000v device to network " + network.getName());
        return false;
      }

      ClusterVO asaCluster = _clusterDao.findById(assignedAsa.getClusterId());
      ClusterVSMMapVO clusterVsmMap = _clusterVsmMapDao.findByClusterId(assignedAsa.getClusterId());
      if (clusterVsmMap == null) {
        s_logger.error(
            "Vmware cluster "
                + asaCluster.getName()
                + " has no Cisco Nexus VSM device associated with it");
        return false;
      }

      CiscoNexusVSMDeviceVO vsmDevice = _vsmDeviceDao.findById(clusterVsmMap.getVsmId());
      if (vsmDevice == null) {
        s_logger.error(
            "Unable to load details of Cisco Nexus VSM device associated with cluster "
                + asaCluster.getName());
        return false;
      }

      CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
      HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
      _hostDao.loadDetails(ciscoVnmcHost);
      Account owner = context.getAccount();
      PublicIp sourceNatIp = _ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, network);
      String vlan = network.getBroadcastUri().getHost();
      long vlanId = Long.parseLong(vlan);

      List<VlanVO> vlanVOList =
          _vlanDao.listVlansByPhysicalNetworkId(network.getPhysicalNetworkId());
      List<String> publicGateways = new ArrayList<String>();
      for (VlanVO vlanVO : vlanVOList) {
        publicGateways.add(vlanVO.getVlanGateway());
      }

      // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall,
      // an additional public ip needs to acquired for assigning as firewall outside ip.
      // In case there are already additional ip addresses available (network restart) use one
      // of them such that it is not the source NAT ip
      IpAddress outsideIp = null;
      List<IPAddressVO> publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null);
      for (IPAddressVO ip : publicIps) {
        if (!ip.isSourceNat()) {
          outsideIp = ip;
          break;
        }
      }
      if (outsideIp == null) { // none available, acquire one
        try {
          Account caller = CallContext.current().getCallingAccount();
          long callerUserId = CallContext.current().getCallingUserId();
          outsideIp = _ipAddrMgr.allocateIp(owner, false, caller, callerUserId, zone);
        } catch (ResourceAllocationException e) {
          s_logger.error("Unable to allocate additional public Ip address. Exception details " + e);
          return false;
        }

        try {
          outsideIp =
              _ipAddrMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true);
        } catch (ResourceAllocationException e) {
          s_logger.error(
              "Unable to assign allocated additional public Ip "
                  + outsideIp.getAddress().addr()
                  + " to network with vlan "
                  + vlanId
                  + ". Exception details "
                  + e);
          return false;
        }
      }

      // create logical edge firewall in VNMC
      String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr());
      // due to ASA limitation of allowing single subnet to be assigned to firewall interfaces,
      // all public ip addresses must be from same subnet, this essentially means single public
      // subnet in zone
      if (!createLogicalEdgeFirewall(
          vlanId,
          network.getGateway(),
          gatewayNetmask,
          outsideIp.getAddress().addr(),
          sourceNatIp.getNetmask(),
          publicGateways,
          ciscoVnmcHost.getId())) {
        s_logger.error(
            "Failed to create logical edge firewall in Cisco VNMC device for network "
                + network.getName());
        return false;
      }

      // create stuff in VSM for ASA device
      if (!configureNexusVsmForAsa(
          vlanId,
          network.getGateway(),
          vsmDevice.getUserName(),
          vsmDevice.getPassword(),
          vsmDevice.getipaddr(),
          assignedAsa.getInPortProfile(),
          ciscoVnmcHost.getId())) {
        s_logger.error(
            "Failed to configure Cisco Nexus VSM "
                + vsmDevice.getipaddr()
                + " for ASA device for network "
                + network.getName());
        return false;
      }

      // configure source NAT
      if (!configureSourceNat(vlanId, network.getCidr(), sourceNatIp, ciscoVnmcHost.getId())) {
        s_logger.error(
            "Failed to configure source NAT in Cisco VNMC device for network " + network.getName());
        return false;
      }

      // associate Asa 1000v instance with logical edge firewall
      if (!associateAsaWithLogicalEdgeFirewall(
          vlanId, assignedAsa.getManagementIp(), ciscoVnmcHost.getId())) {
        s_logger.error(
            "Failed to associate Cisco ASA 1000v ("
                + assignedAsa.getManagementIp()
                + ") with logical edge firewall in VNMC for network "
                + network.getName());
        return false;
      }

      status = true;
      txn.commit();
    } finally {
      if (!status) {
        txn.rollback();
        // FIXME: also undo changes in VNMC, VSM if anything failed
      }
    }

    return true;
  }
  @Override
  public Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd) {
    Long ipId = cmd.getIpAddressId();
    Long id = cmd.getId();
    Long networkId = null;
    Map<String, String> tags = cmd.getTags();
    FirewallRule.TrafficType trafficType = cmd.getTrafficType();

    Account caller = CallContext.current().getCallingAccount();
    List<Long> permittedAccounts = new ArrayList<Long>();

    if (ipId != null) {
      IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId);
      if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
        throw new InvalidParameterValueException(
            "Ip address id=" + ipId + " not ready for firewall rules yet");
      }
      _accountMgr.checkAccess(caller, null, true, ipAddressVO);
    }

    Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject =
        new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
            cmd.getDomainId(), cmd.isRecursive(), null);
    _accountMgr.buildACLSearchParameters(
        caller,
        id,
        cmd.getAccountName(),
        cmd.getProjectId(),
        permittedAccounts,
        domainIdRecursiveListProject,
        cmd.listAll(),
        false);
    Long domainId = domainIdRecursiveListProject.first();
    Boolean isRecursive = domainIdRecursiveListProject.second();
    ListProjectResourcesCriteria listProjectResourcesCriteria =
        domainIdRecursiveListProject.third();

    Filter filter =
        new Filter(FirewallRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal());
    SearchBuilder<FirewallRuleVO> sb = _firewallDao.createSearchBuilder();
    _accountMgr.buildACLSearchBuilder(
        sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);

    sb.and("id", sb.entity().getId(), Op.EQ);
    sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ);
    if (cmd instanceof ListEgressFirewallRulesCmd) {
      networkId = ((ListEgressFirewallRulesCmd) cmd).getNetworkId();
      sb.and("networkId", sb.entity().getNetworkId(), Op.EQ);
    } else {
      sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
    }
    sb.and("purpose", sb.entity().getPurpose(), Op.EQ);

    if (tags != null && !tags.isEmpty()) {
      SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
      for (int count = 0; count < tags.size(); count++) {
        tagSearch
            .or()
            .op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
        tagSearch.and(
            "value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
        tagSearch.cp();
      }
      tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
      sb.groupBy(sb.entity().getId());
      sb.join(
          "tagSearch",
          tagSearch,
          sb.entity().getId(),
          tagSearch.entity().getResourceId(),
          JoinBuilder.JoinType.INNER);
    }

    SearchCriteria<FirewallRuleVO> sc = sb.create();
    _accountMgr.buildACLSearchCriteria(
        sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);

    if (id != null) {
      sc.setParameters("id", id);
    }

    if (tags != null && !tags.isEmpty()) {
      int count = 0;
      sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.FirewallRule.toString());
      for (String key : tags.keySet()) {
        sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
        sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
        count++;
      }
    }

    if (ipId != null) {
      sc.setParameters("ip", ipId);
    } else if (cmd instanceof ListEgressFirewallRulesCmd) {
      if (networkId != null) {
        sc.setParameters("networkId", networkId);
      }
    }

    sc.setParameters("purpose", Purpose.Firewall);
    sc.setParameters("trafficType", trafficType);

    Pair<List<FirewallRuleVO>, Integer> result = _firewallDao.searchAndCount(sc, filter);
    return new Pair<List<? extends FirewallRule>, Integer>(result.first(), result.second());
  }
  @Override
  public LinkedHashMap<Network, List<? extends NicProfile>> configureGuestNic(
      final RouterDeploymentDefinition routerDeploymentDefinition)
      throws ConcurrentOperationException, InsufficientAddressCapacityException {

    // Form networks
    final LinkedHashMap<Network, List<? extends NicProfile>> networks =
        new LinkedHashMap<Network, List<? extends NicProfile>>(3);
    // 1) Guest network
    final Network guestNetwork = routerDeploymentDefinition.getGuestNetwork();

    if (guestNetwork != null) {
      s_logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork);
      String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null;
      if (!routerDeploymentDefinition.isPublicNetwork()) {
        final Nic placeholder =
            _networkModel.getPlaceholderNicForRouter(
                guestNetwork, routerDeploymentDefinition.getPodId());
        if (guestNetwork.getCidr() != null) {
          if (placeholder != null && placeholder.getIPv4Address() != null) {
            s_logger.debug(
                "Requesting ipv4 address "
                    + placeholder.getIPv4Address()
                    + " stored in placeholder nic for the network "
                    + guestNetwork);
            defaultNetworkStartIp = placeholder.getIPv4Address();
          } else {
            final String startIp = _networkModel.getStartIpAddress(guestNetwork.getId());
            if (startIp != null
                && _ipAddressDao
                        .findByIpAndSourceNetworkId(guestNetwork.getId(), startIp)
                        .getAllocatedTime()
                    == null) {
              defaultNetworkStartIp = startIp;
            } else if (s_logger.isDebugEnabled()) {
              s_logger.debug(
                  "First ipv4 "
                      + startIp
                      + " in network id="
                      + guestNetwork.getId()
                      + " is already allocated, can't use it for domain router; will get random ip address from the range");
            }
          }
        }

        if (guestNetwork.getIp6Cidr() != null) {
          if (placeholder != null && placeholder.getIPv6Address() != null) {
            s_logger.debug(
                "Requesting ipv6 address "
                    + placeholder.getIPv6Address()
                    + " stored in placeholder nic for the network "
                    + guestNetwork);
            defaultNetworkStartIpv6 = placeholder.getIPv6Address();
          } else {
            final String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId());
            if (startIpv6 != null
                && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) {
              defaultNetworkStartIpv6 = startIpv6;
            } else if (s_logger.isDebugEnabled()) {
              s_logger.debug(
                  "First ipv6 "
                      + startIpv6
                      + " in network id="
                      + guestNetwork.getId()
                      + " is already allocated, can't use it for domain router; will get random ipv6 address from the range");
            }
          }
        }
      }

      final NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6);
      if (routerDeploymentDefinition.isPublicNetwork()) {
        if (routerDeploymentDefinition.isRedundant()) {
          gatewayNic.setIPv4Address(_ipAddrMgr.acquireGuestIpAddress(guestNetwork, null));
        } else {
          gatewayNic.setIPv4Address(guestNetwork.getGateway());
        }
        gatewayNic.setBroadcastUri(guestNetwork.getBroadcastUri());
        gatewayNic.setBroadcastType(guestNetwork.getBroadcastDomainType());
        gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri());
        gatewayNic.setMode(guestNetwork.getMode());
        final String gatewayCidr = guestNetwork.getCidr();
        gatewayNic.setIPv4Netmask(NetUtils.getCidrNetmask(gatewayCidr));
      } else {
        gatewayNic.setDefaultNic(true);
      }

      networks.put(guestNetwork, new ArrayList<NicProfile>(Arrays.asList(gatewayNic)));
    }
    return networks;
  }
  @Override
  public RemoteAccessVpn createRemoteAccessVpn(
      long publicIpId, String ipRange, boolean openFirewall, long networkId)
      throws NetworkRuleConflictException {
    UserContext ctx = UserContext.current();
    Account caller = ctx.getCaller();

    // make sure ip address exists
    PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId);
    if (ipAddr == null) {
      throw new InvalidParameterValueException(
          "Unable to create remote access vpn, invalid public IP address id" + publicIpId);
    }

    _accountMgr.checkAccess(caller, null, true, ipAddr);

    if (!ipAddr.readyToUse()) {
      throw new InvalidParameterValueException(
          "The Ip address is not ready to be used yet: " + ipAddr.getAddress());
    }

    IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId);
    _networkMgr.checkIpForService(ipAddress, Service.Vpn, null);

    RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId);

    if (vpnVO != null) {
      // if vpn is in Added state, return it to the api
      if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
        return vpnVO;
      }
      throw new InvalidParameterValueException(
          "A Remote Access VPN already exists for this public Ip address");
    }

    // TODO: assumes one virtual network / domr per account per zone
    vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId);
    if (vpnVO != null) {
      // if vpn is in Added state, return it to the api
      if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
        return vpnVO;
      }
      throw new InvalidParameterValueException(
          "A Remote Access VPN already exists for this account");
    }

    // Verify that vpn service is enabled for the network
    Network network = _networkMgr.getNetwork(networkId);
    if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) {
      throw new InvalidParameterValueException(
          "Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId());
    }

    if (ipRange == null) {
      ipRange = _clientIpRange;
    }
    String[] range = ipRange.split("-");
    if (range.length != 2) {
      throw new InvalidParameterValueException("Invalid ip range");
    }
    if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) {
      throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange);
    }
    if (!NetUtils.validIpRange(range[0], range[1])) {
      throw new InvalidParameterValueException("Invalid ip range " + ipRange);
    }

    Pair<String, Integer> cidr = NetUtils.getCidr(network.getCidr());

    // FIXME: This check won't work for the case where the guest ip range
    // changes depending on the vlan allocated.
    String[] guestIpRange = NetUtils.getIpRangeFromCidr(cidr.first(), cidr.second());
    if (NetUtils.ipRangesOverlap(range[0], range[1], guestIpRange[0], guestIpRange[1])) {
      throw new InvalidParameterValueException(
          "Invalid ip range: "
              + ipRange
              + " overlaps with guest ip range "
              + guestIpRange[0]
              + "-"
              + guestIpRange[1]);
    }
    // TODO: check sufficient range
    // TODO: check overlap with private and public ip ranges in datacenter

    long startIp = NetUtils.ip2Long(range[0]);
    String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
    String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength);
    _rulesMgr.reservePorts(
        ipAddr,
        NetUtils.UDP_PROTO,
        Purpose.Vpn,
        openFirewall,
        caller,
        NetUtils.VPN_PORT,
        NetUtils.VPN_L2TP_PORT,
        NetUtils.VPN_NATT_PORT);
    vpnVO =
        new RemoteAccessVpnVO(
            ipAddr.getAccountId(),
            ipAddr.getDomainId(),
            ipAddr.getAssociatedWithNetworkId(),
            publicIpId,
            range[0],
            newIpRange,
            sharedSecret);
    return _remoteAccessVpnDao.persist(vpnVO);
  }
  @Override
  @DB
  public RemoteAccessVpn createRemoteAccessVpn(
      final long publicIpId, String ipRange, boolean openFirewall, final Boolean forDisplay)
      throws NetworkRuleConflictException {
    CallContext ctx = CallContext.current();
    final Account caller = ctx.getCallingAccount();

    Long networkId = null;

    // make sure ip address exists
    final PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId);
    if (ipAddr == null) {
      throw new InvalidParameterValueException(
          "Unable to create remote access vpn, invalid public IP address id" + publicIpId);
    }

    _accountMgr.checkAccess(caller, null, true, ipAddr);

    if (!ipAddr.readyToUse()) {
      throw new InvalidParameterValueException(
          "The Ip address is not ready to be used yet: " + ipAddr.getAddress());
    }

    IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId);

    networkId = ipAddress.getAssociatedWithNetworkId();
    if (networkId != null) {
      _networkMgr.checkIpForService(ipAddress, Service.Vpn, null);
    }

    final Long vpcId = ipAddress.getVpcId();
    /* IP Address used for VPC must be the source NAT IP of whole VPC */
    if (vpcId != null && ipAddress.isSourceNat()) {
      assert networkId == null;
      // No firewall setting for VPC, it would be open internally
      openFirewall = false;
    }

    final boolean openFirewallFinal = openFirewall;

    if (networkId == null && vpcId == null) {
      throw new InvalidParameterValueException(
          "Unable to create remote access vpn for the ipAddress: "
              + ipAddr.getAddress().addr()
              + " as ip is not associated with any network or VPC");
    }

    RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId);

    if (vpnVO != null) {
      // if vpn is in Added state, return it to the api
      if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
        return vpnVO;
      }
      throw new InvalidParameterValueException(
          "A Remote Access VPN already exists for this public Ip address");
    }

    if (ipRange == null) {
      ipRange = RemoteAccessVpnClientIpRange.valueIn(ipAddr.getAccountId());
    }
    final String[] range = ipRange.split("-");
    if (range.length != 2) {
      throw new InvalidParameterValueException("Invalid ip range");
    }
    if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) {
      throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange);
    }
    if (!NetUtils.validIpRange(range[0], range[1])) {
      throw new InvalidParameterValueException("Invalid ip range " + ipRange);
    }

    Pair<String, Integer> cidr = null;

    // TODO: assumes one virtual network / domr per account per zone
    if (networkId != null) {
      vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId);
      if (vpnVO != null) {
        // if vpn is in Added state, return it to the api
        if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
          return vpnVO;
        }
        throw new InvalidParameterValueException(
            "A Remote Access VPN already exists for this account");
      }
      // Verify that vpn service is enabled for the network
      Network network = _networkMgr.getNetwork(networkId);
      if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) {
        throw new InvalidParameterValueException(
            "Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId());
      }
      cidr = NetUtils.getCidr(network.getCidr());
    } else { // Don't need to check VPC because there is only one IP(source NAT IP) available for
             // VPN
      Vpc vpc = _vpcDao.findById(vpcId);
      cidr = NetUtils.getCidr(vpc.getCidr());
    }

    // FIXME: This check won't work for the case where the guest ip range
    // changes depending on the vlan allocated.
    String[] guestIpRange = NetUtils.getIpRangeFromCidr(cidr.first(), cidr.second());
    if (NetUtils.ipRangesOverlap(range[0], range[1], guestIpRange[0], guestIpRange[1])) {
      throw new InvalidParameterValueException(
          "Invalid ip range: "
              + ipRange
              + " overlaps with guest ip range "
              + guestIpRange[0]
              + "-"
              + guestIpRange[1]);
    }
    // TODO: check sufficient range
    // TODO: check overlap with private and public ip ranges in datacenter

    long startIp = NetUtils.ip2Long(range[0]);
    final String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
    final String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength);

    return Transaction.execute(
        new TransactionCallbackWithException<RemoteAccessVpn, NetworkRuleConflictException>() {
          @Override
          public RemoteAccessVpn doInTransaction(TransactionStatus status)
              throws NetworkRuleConflictException {
            if (vpcId == null) {
              _rulesMgr.reservePorts(
                  ipAddr,
                  NetUtils.UDP_PROTO,
                  Purpose.Vpn,
                  openFirewallFinal,
                  caller,
                  NetUtils.VPN_PORT,
                  NetUtils.VPN_L2TP_PORT,
                  NetUtils.VPN_NATT_PORT);
            }
            RemoteAccessVpnVO vpnVO =
                new RemoteAccessVpnVO(
                    ipAddr.getAccountId(),
                    ipAddr.getDomainId(),
                    ipAddr.getAssociatedWithNetworkId(),
                    publicIpId,
                    vpcId,
                    range[0],
                    newIpRange,
                    sharedSecret);

            if (forDisplay != null) {
              vpnVO.setDisplay(forDisplay);
            }
            return _remoteAccessVpnDao.persist(vpnVO);
          }
        });
  }
 @Override
 public void deallocate(
     Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) {
   _ipAddressDao.unassignIpAddress(new Ip(nic.getIp4Address()));
   nic.deallocate();
 }