@Override
  public void CheckAndDestroyTunnel(VirtualMachine vm) {
    if (!_isEnabled) {
      return;
    }

    List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getAccountId(), vm.getHostId());
    if (vm.getType() == VirtualMachine.Type.User) {
      if (userVms.size() > 1) {
        return;
      }

      List<DomainRouterVO> routers =
          _routerDao.findBy(vm.getAccountId(), vm.getDataCenterIdToDeployIn());
      for (DomainRouterVO router : routers) {
        if (router.getHostId() == vm.getHostId()) {
          return;
        }
      }
    } else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
      return;
    }

    try {
      /* Now we are last one on host, destroy all tunnels of my account */
      Command cmd = new OvsDestroyTunnelCommand(vm.getAccountId(), "[]");
      Answer ans = _agentMgr.send(vm.getHostId(), cmd);
      handleDestroyTunnelAnswer(ans, vm.getHostId(), 0, vm.getAccountId());

      /* Then ask hosts have peer tunnel with me to destroy them */
      List<OvsTunnelAccountVO> peers =
          _tunnelAccountDao.listByToAccount(vm.getHostId(), vm.getAccountId());
      for (OvsTunnelAccountVO p : peers) {
        cmd = new OvsDestroyTunnelCommand(p.getAccount(), p.getPortName());
        ans = _agentMgr.send(p.getFrom(), cmd);
        handleDestroyTunnelAnswer(ans, p.getFrom(), p.getTo(), p.getAccount());
      }
    } catch (Exception e) {
      s_logger.warn(
          String.format(
              "Destroy tunnel(account:%1$s, hostId:%2$s) failed",
              vm.getAccountId(), vm.getHostId()),
          e);
    }
  }
  @DB
  protected void CheckAndCreateTunnel(VirtualMachine instance, DeployDestination dest) {
    if (!_isEnabled) {
      return;
    }

    if (instance.getType() != VirtualMachine.Type.User
        && instance.getType() != VirtualMachine.Type.DomainRouter) {
      return;
    }

    long hostId = dest.getHost().getId();
    long accountId = instance.getAccountId();
    List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
    List<DomainRouterVO> routers =
        _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn());
    List<VMInstanceVO> ins = new ArrayList<VMInstanceVO>();
    if (vms != null) {
      ins.addAll(vms);
    }
    if (routers.size() != 0) {
      ins.addAll(routers);
    }
    List<Pair<Long, Integer>> toHosts = new ArrayList<Pair<Long, Integer>>();
    List<Pair<Long, Integer>> fromHosts = new ArrayList<Pair<Long, Integer>>();
    int key;

    for (VMInstanceVO v : ins) {
      Long rh = v.getHostId();
      if (rh == null || rh.longValue() == hostId) {
        continue;
      }

      OvsTunnelAccountVO ta =
          _tunnelAccountDao.getByFromToAccount(hostId, rh.longValue(), accountId);
      if (ta == null) {
        key = getGreKey(hostId, rh.longValue(), accountId);
        if (key == -1) {
          s_logger.warn(
              String.format(
                  "Cannot get GRE key for from=%1$s to=%2$s accountId=%3$s, tunnel create failed",
                  hostId, rh.longValue(), accountId));
          continue;
        }

        Pair<Long, Integer> p = new Pair<Long, Integer>(rh, Integer.valueOf(key));
        if (!toHosts.contains(p)) {
          toHosts.add(p);
        }
      }

      ta = _tunnelAccountDao.getByFromToAccount(rh.longValue(), hostId, accountId);
      if (ta == null) {
        key = getGreKey(rh.longValue(), hostId, accountId);
        if (key == -1) {
          s_logger.warn(
              String.format(
                  "Cannot get GRE key for from=%1$s to=%2$s accountId=%3$s, tunnel create failed",
                  rh.longValue(), hostId, accountId));
          continue;
        }

        Pair<Long, Integer> p = new Pair<Long, Integer>(rh, Integer.valueOf(key));
        if (!fromHosts.contains(p)) {
          fromHosts.add(p);
        }
      }
    }

    try {
      String myIp = dest.getHost().getPrivateIpAddress();
      for (Pair<Long, Integer> i : toHosts) {
        HostVO rHost = _hostDao.findById(i.first());
        Commands cmds =
            new Commands(
                new OvsCreateTunnelCommand(
                    rHost.getPrivateIpAddress(),
                    i.second().toString(),
                    Long.valueOf(hostId),
                    i.first(),
                    accountId,
                    myIp));
        s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i.first());
        Answer[] answers = _agentMgr.send(hostId, cmds);
        handleCreateTunnelAnswer(answers);
      }

      for (Pair<Long, Integer> i : fromHosts) {
        HostVO rHost = _hostDao.findById(i.first());
        Commands cmd2s =
            new Commands(
                new OvsCreateTunnelCommand(
                    myIp,
                    i.second().toString(),
                    i.first(),
                    Long.valueOf(hostId),
                    accountId,
                    rHost.getPrivateIpAddress()));
        s_logger.debug("Ask host " + i.first() + " to create gre tunnel to " + hostId);
        Answer[] answers = _agentMgr.send(i.first(), cmd2s);
        handleCreateTunnelAnswer(answers);
      }
    } catch (Exception e) {
      s_logger.debug("Ovs Tunnel network created tunnel failed", e);
    }
  }