/***************************************************************************
* Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package com.vmware.bdd.dal;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.vmware.bdd.apitypes.NetworkDnsType;
import com.vmware.bdd.entity.IpBlockEntity;
import com.vmware.bdd.entity.IpBlockEntity.BlockType;
import com.vmware.bdd.entity.NetworkEntity;
import com.vmware.bdd.entity.NetworkEntity.AllocType;
import com.vmware.bdd.exception.NetworkException;
import com.vmware.bdd.utils.IpAddressUtil;
public class TestNetworkDAO {
private static final Logger logger = Logger.getLogger(TestNetworkDAO.class);
ApplicationContext ctx;
private INetworkDAO networkDao;
@BeforeMethod
public void setup() {
ctx = new ClassPathXmlApplicationContext("META-INF/spring/*-context.xml");
networkDao = ctx.getBean(INetworkDAO.class);
}
@AfterMethod
public void tearDown() {
}
@AfterClass
public static void deleteAll() {
}
private String collectionToString(Collection<?> c) {
String str = "";
for (Object o : c) {
str += "\n" + o;
}
return str;
}
public static void main(String[] args) throws UnknownHostException {
TestNetworkDAO test = new TestNetworkDAO();
test.setup();
test.testInsert();
}
@Test(groups = { "testNetworkEntity" })
public void testInsert() throws UnknownHostException {
final String portGroup = "VM Network " + Math.random();
final AllocType allocType = AllocType.IP_POOL;
final String netmask = "255.255.255.0";
final String gateway = "192.168.1.254";
final String dns1 = "8.8.8.8";
final String dns2 = "4.4.4.4";
NetworkEntity network = new NetworkEntity(portGroup, portGroup, allocType,
netmask, gateway, dns1, dns2, NetworkDnsType.NORMAL);
networkDao.insert(network);
Long ipBase = IpAddressUtil.getAddressAsLong(InetAddress.getByName("192.168.1.1"));
List<IpBlockEntity> ipBlocks = new ArrayList<IpBlockEntity>();
for (int i = 0; i < 10; i++) {
ipBlocks.add(new IpBlockEntity(network, IpBlockEntity.FREE_BLOCK_OWNER_ID,
BlockType.FREE, ipBase + i * 10, ipBase + i * 10 + 10));
}
networkDao.addIpBlocks(network, ipBlocks);
logger.info(network);
NetworkEntity network2 = networkDao.findById(network.getId());
assertNotNull(network2);
NetworkEntity net = networkDao.findById(network.getId());
networkDao.delete(net);
assertNull(networkDao.findById(network.getId()));
}
/**
* First initialize the network with a whole IP block. And randomly do alloc
* and free request until an 'out of IP' exception thrown (P(alloc) >
* P(free), then the process will eventually converge). And then free all the
* allocated IPs for all the requesters.
*
* The expected result is: the final IP blocks in the table should have only
* one b block which match the original one.
*
* @throws UnknownHostException
*/
@Test(groups = { "testNetworkEntity" }, dependsOnMethods = { "testInsert" })
public void testAllocFreeRandom() throws UnknownHostException {
final String portGroup = "VM Network " + Math.random();
final AllocType allocType = AllocType.IP_POOL;
final String netmask = "255.0.0.0";
final String gateway = "0.0.0.1";
final String dns1 = "8.8.8.8";
final String dns2 = null;
final Long beginIp = IpAddressUtil.getAddressAsLong(InetAddress
.getByName("0.0.0.2"));
final Long endIp = IpAddressUtil
.getAddressAsLong(InetAddress.getByName("0.2.0.0"));
NetworkEntity network = new NetworkEntity(portGroup, portGroup, allocType,
netmask, gateway, dns1, dns2, NetworkDnsType.NORMAL);
IpBlockEntity originalBlock = new IpBlockEntity(network,
IpBlockEntity.FREE_BLOCK_OWNER_ID, BlockType.FREE, beginIp, endIp);
networkDao.insert(network);
List<IpBlockEntity> ipBlocks = new ArrayList<IpBlockEntity>();
ipBlocks.add(originalBlock);
networkDao.addIpBlocks(network, ipBlocks);
logger.info(network);
List<List<IpBlockEntity>> allocLists = new ArrayList<List<IpBlockEntity>>();
List<Integer> allocSizes = new ArrayList<Integer>();
List<Long> allocOwners = new ArrayList<Long>();
long totalAssigned = 0L;
Long maxOwnerId = 100L; // min is 0L
int minAllocSize = 1;
int maxAllocSize = 1000;
final Long totalIps = endIp - beginIp + 1;
long nextLogTimeMs = System.currentTimeMillis() + 1000;
logger.info("strart random alloc/free stress test");
/**
* try to alloc until out of IPs
*/
while (true) {
long now = System.currentTimeMillis();
if (nextLogTimeMs < now) {
nextLogTimeMs = now + 1000;
logger.info("allocated: " + totalAssigned + "/" + totalIps + " ("
+ totalAssigned / (double) totalIps + ")");
}
if (Math.random() < 0.8) { // alloc
final Long ownerId = (long) (Math.random() * maxOwnerId) % maxOwnerId;
int rndCount = (int) (Math.random() * maxAllocSize) % maxAllocSize;
final int count = Math.max(minAllocSize, rndCount);
try {
List<IpBlockEntity> allocated = networkDao.alloc(network, ownerId, count);
allocLists.add(allocated);
allocSizes.add(count);
allocOwners.add(ownerId);
totalAssigned += totalAssigned + count;
logger.debug("alloc: "
+ collectionToString(allocLists.get(allocLists.size() - 1)));
} catch (NetworkException ex) {
assertTrue("out of ip resource", network.getFree() < count);
break;
}
} else { // free
if (!allocLists.isEmpty()) {
int idx = (int) (Math.random() * allocLists.size()) % allocLists.size();
final List<IpBlockEntity> toBeFreed = allocLists.remove(idx);
final Long ownerId = allocOwners.remove(idx);
logger.debug("to free: " + collectionToString(toBeFreed));
networkDao.free(network, ownerId, toBeFreed);
totalAssigned -= allocSizes.remove(idx);
}
}
}
// free all by cluster
for (long id = 0; id < maxOwnerId; ++id) {
final Long ownerId = id;
networkDao.free(network, ownerId);
}
originalBlock = new IpBlockEntity(network, IpBlockEntity.FREE_BLOCK_OWNER_ID,
BlockType.FREE, beginIp, endIp);
assertEquals(1, network.getIpBlocks().size());
assertEquals(originalBlock, network.getIpBlocks().get(0));
NetworkEntity net = networkDao.findById(network.getId());
networkDao.delete(net);
logger.info("alloc/free test done");
}
}