@Test
  public void test() throws ApiSenderException {
    EipInventory eip = deployer.eips.get("eip");
    VmInstanceInventory vm = deployer.vms.get("TestVm");
    VmNicInventory nic = vm.getVmNics().get(0);
    IpRangeInventory ipr = deployer.ipRanges.get("GuestIpRange");

    String newIp = null;
    long s = NetworkUtils.ipv4StringToLong(ipr.getStartIp());
    long e = NetworkUtils.ipv4StringToLong(ipr.getEndIp());

    for (long l = s; s < e; s++) {
      String ip = NetworkUtils.longToIpv4String(l);
      if (!ip.equals(nic.getIp())) {
        newIp = ip;
        break;
      }
    }
    Assert.assertNotNull(newIp);

    api.stopVmInstance(vm.getUuid());
    api.setStaticIp(vm.getUuid(), nic.getL3NetworkUuid(), newIp);
    EipVO eipvo = dbf.findByUuid(eip.getUuid(), EipVO.class);
    Assert.assertEquals(newIp, eipvo.getGuestIp());
  }
  private String allocateIp(IpRangeVO vo) {
    int total = vo.size();
    Random random = new Random();
    long s = random.nextInt(total) + NetworkUtils.ipv4StringToLong(vo.getStartIp());
    long e = NetworkUtils.ipv4StringToLong(vo.getEndIp());
    String ret = steppingAllocate(s, e, total, vo.getUuid());
    if (ret != null) {
      return ret;
    }

    e = s;
    s = NetworkUtils.ipv4StringToLong(vo.getStartIp());
    return steppingAllocate(s, e, total, vo.getUuid());
  }
  private String steppingAllocate(long s, long e, int total, String rangeUuid) {
    int step = 254;
    int failureCount = 0;
    int failureCheckPoint = 5;

    while (s < e) {
      // if failing failureCheckPoint times, the range is probably full,
      // we check the range.
      // why don't we check before steppingAllocate()? because in that case we
      // have to count the used IP every time allocating a IP, and count operation
      // is a full scan in DB, which is very costly
      if (failureCheckPoint == failureCount++) {
        SimpleQuery<UsedIpVO> q = dbf.createQuery(UsedIpVO.class);
        q.add(UsedIpVO_.ipRangeUuid, Op.EQ, rangeUuid);
        long count = q.count();
        if (count == total) {
          logger.debug(
              String.format("ip range[uuid:%s] has no ip available, try next one", rangeUuid));
          return null;
        } else {
          failureCount = 0;
        }
      }

      long te = s + step;
      te = te > e ? e : te;
      SimpleQuery<UsedIpVO> q = dbf.createQuery(UsedIpVO.class);
      q.select(UsedIpVO_.ipInLong);
      q.add(UsedIpVO_.ipInLong, Op.GTE, s);
      q.add(UsedIpVO_.ipInLong, Op.LTE, te);
      q.add(UsedIpVO_.ipRangeUuid, Op.EQ, rangeUuid);
      List<Long> used = q.listValue();
      if (te - s + 1 == used.size()) {
        s += step;
        continue;
      }

      Collections.sort(used);

      return NetworkUtils.randomAllocateIpv4Address(s, te, used);
    }

    return null;
  }