@Override
  public boolean stopRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRouter router)
      throws ResourceUnavailableException {
    boolean result = true;

    if (router.getState() == State.Running) {
      final Commands cmds = new Commands(Command.OnError.Continue);
      _commandSetupHelper.createApplyVpnCommands(false, vpn, router, cmds);
      result = result && _nwHelper.sendCommandsToRouter(router, cmds);
    } else if (router.getState() == State.Stopped) {
      s_logger.debug(
          "Router "
              + router
              + " is in Stopped state, not sending deleteRemoteAccessVpn command to it");
    } else {
      s_logger.warn(
          "Failed to delete remote access VPN: domR "
              + router
              + " is not in right state "
              + router.getState());
      throw new ResourceUnavailableException(
          "Failed to delete remote access VPN: domR is not in right state " + router.getState(),
          DataCenter.class,
          router.getDataCenterId());
    }
    return true;
  }
  @Override
  protected void finalizeIpAssocForNetwork(
      final Commands cmds,
      final VirtualRouter domainRouterVO,
      final Provider provider,
      final Long guestNetworkId,
      final Map<String, String> vlanMacAddress) {

    if (domainRouterVO.getVpcId() == null) {
      super.finalizeIpAssocForNetwork(
          cmds, domainRouterVO, provider, guestNetworkId, vlanMacAddress);
      return;
    }

    if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) {
      final ArrayList<? extends PublicIpAddress> publicIps =
          getPublicIpsToApply(domainRouterVO, provider, guestNetworkId, IpAddress.State.Releasing);

      if (publicIps != null && !publicIps.isEmpty()) {
        s_logger.debug(
            "Found "
                + publicIps.size()
                + " ip(s) to apply as a part of domR "
                + domainRouterVO
                + " start.");
        // Re-apply public ip addresses - should come before PF/LB/VPN
        _commandSetupHelper.createVpcAssociatePublicIPCommands(
            domainRouterVO, publicIps, cmds, vlanMacAddress);
      }
    }
  }
  @Override
  public boolean stopSite2SiteVpn(final Site2SiteVpnConnection conn, final VirtualRouter router)
      throws ResourceUnavailableException {
    if (router.getState() != State.Running) {
      s_logger.warn(
          "Unable to apply site-to-site VPN configuration, virtual router is not in the right state "
              + router.getState());
      throw new ResourceUnavailableException(
          "Unable to apply site 2 site VPN configuration,"
              + " virtual router is not in the right state",
          DataCenter.class,
          router.getDataCenterId());
    }

    return applySite2SiteVpn(false, router, conn);
  }
  protected boolean setupVpcGuestNetwork(
      final Network network,
      final VirtualRouter router,
      final boolean add,
      final NicProfile guestNic)
      throws ConcurrentOperationException, ResourceUnavailableException {

    boolean result = true;
    if (router.getState() == State.Running) {
      final SetupGuestNetworkCommand setupCmd =
          _commandSetupHelper.createSetupGuestNetworkCommand(
              (DomainRouterVO) router, add, guestNic);

      final Commands cmds = new Commands(Command.OnError.Stop);
      cmds.addCommand("setupguestnetwork", setupCmd);
      _nwHelper.sendCommandsToRouter(router, cmds);

      final Answer setupAnswer = cmds.getAnswer("setupguestnetwork");
      final String setup = add ? "set" : "destroy";
      if (!(setupAnswer != null && setupAnswer.getResult())) {
        s_logger.warn("Unable to " + setup + " guest network on router " + router);
        result = false;
      }
      return result;
    } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
      s_logger.debug(
          "Router "
              + router.getInstanceName()
              + " is in "
              + router.getState()
              + ", so not sending setup guest network command to the backend");
      return true;
    } else {
      s_logger.warn(
          "Unable to setup guest network on virtual router "
              + router
              + " is not in the right state "
              + router.getState());
      throw new ResourceUnavailableException(
          "Unable to setup guest network on the backend,"
              + " virtual router "
              + router
              + " is not in the right state",
          DataCenter.class,
          router.getDataCenterId());
    }
  }
  @Override
  public boolean startRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRouter router)
      throws ResourceUnavailableException {
    if (router.getState() != State.Running) {
      s_logger.warn(
          "Unable to apply remote access VPN configuration, virtual router is not in the right state "
              + router.getState());
      throw new ResourceUnavailableException(
          "Unable to apply remote access VPN configuration,"
              + " virtual router is not in the right state",
          DataCenter.class,
          router.getDataCenterId());
    }

    final Commands cmds = new Commands(Command.OnError.Stop);
    _commandSetupHelper.createApplyVpnCommands(true, vpn, router, cmds);

    try {
      _agentMgr.send(router.getHostId(), cmds);
    } catch (final OperationTimedoutException e) {
      s_logger.debug("Failed to start remote access VPN: ", e);
      throw new AgentUnavailableException(
          "Unable to send commands to virtual router ", router.getHostId(), e);
    }
    Answer answer = cmds.getAnswer("users");
    if (!answer.getResult()) {
      s_logger.error(
          "Unable to start vpn: unable add users to vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails());
      throw new ResourceUnavailableException(
          "Unable to start vpn: Unable to add users to vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails(),
          DataCenter.class,
          router.getDataCenterId());
    }
    answer = cmds.getAnswer("startVpn");
    if (!answer.getResult()) {
      s_logger.error(
          "Unable to start vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails());
      throw new ResourceUnavailableException(
          "Unable to start vpn in zone "
              + router.getDataCenterId()
              + " for account "
              + vpn.getAccountId()
              + " on domR: "
              + router.getInstanceName()
              + " due to "
              + answer.getDetails(),
          DataCenter.class,
          router.getDataCenterId());
    }

    return true;
  }
  /**
   * @param router
   * @param add
   * @param privateNic
   * @return
   * @throws ResourceUnavailableException
   */
  protected boolean setupVpcPrivateNetwork(
      final VirtualRouter router, final boolean add, final NicProfile privateNic)
      throws ResourceUnavailableException {

    if (router.getState() == State.Running) {
      final PrivateIpVO ipVO =
          _privateIpDao.findByIpAndSourceNetworkId(
              privateNic.getNetworkId(), privateNic.getIPv4Address());
      final Network network = _networkDao.findById(privateNic.getNetworkId());
      final String netmask = NetUtils.getCidrNetmask(network.getCidr());
      final PrivateIpAddress ip =
          new PrivateIpAddress(
              ipVO,
              network.getBroadcastUri().toString(),
              network.getGateway(),
              netmask,
              privateNic.getMacAddress());

      final List<PrivateIpAddress> privateIps = new ArrayList<PrivateIpAddress>(1);
      privateIps.add(ip);
      final Commands cmds = new Commands(Command.OnError.Stop);
      _commandSetupHelper.createVpcAssociatePrivateIPCommands(router, privateIps, cmds, add);

      try {
        if (_nwHelper.sendCommandsToRouter(router, cmds)) {
          s_logger.debug(
              "Successfully applied ip association for ip " + ip + " in vpc network " + network);
          return true;
        } else {
          s_logger.warn("Failed to associate ip address " + ip + " in vpc network " + network);
          return false;
        }
      } catch (final Exception ex) {
        s_logger.warn(
            "Failed to send  "
                + (add ? "add " : "delete ")
                + " private network "
                + network
                + " commands to rotuer ");
        return false;
      }
    } else if (router.getState() == State.Stopped || router.getState() == State.Stopping) {
      s_logger.debug(
          "Router "
              + router.getInstanceName()
              + " is in "
              + router.getState()
              + ", so not sending setup private network command to the backend");
    } else {
      s_logger.warn(
          "Unable to setup private gateway, virtual router "
              + router
              + " is not in the right state "
              + router.getState());

      throw new ResourceUnavailableException(
          "Unable to setup Private gateway on the backend,"
              + " virtual router "
              + router
              + " is not in the right state",
          DataCenter.class,
          router.getDataCenterId());
    }
    return true;
  }