package org.zstack.test.multinodes;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Configurable;
import org.zstack.core.thread.AsyncThread;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.logging.CLogger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.zstack.utils.CollectionDSL.e;
import static org.zstack.utils.CollectionDSL.map;
import static org.zstack.utils.ExceptionDSL.throwableSafe;
import static org.zstack.utils.StringDSL.s;
/**
*/
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class NodeManager {
private static final CLogger logger = Utils.getLogger(NodeManager.class);
private List<NodeRunner> nodes = new ArrayList<NodeRunner>();
private String properties;
private int portStart = 8100;
private int nodeStart = 0;
private String properties(int port) {
return s(
"-DRESTFacade.port={port} ",
"-DKVMHostFactory.agentPort={port} ",
"-DSftpBackupStorageFactory.agentPort={port} ",
"-DVirtualRouterManager.agentPort={port} ",
"-DManagementServerConsoleProxyBackend.agentPort={port} "
).formatByMap(map(e("port", port)));
}
public NodeManager setProperties(String prop) {
properties = prop;
return this;
}
public List<NodeRunner> getNodes() {
return nodes;
}
public void stopNode(final int index, int timeout) {
NodeRunner node = CollectionUtils.find(nodes, new Function<NodeRunner, NodeRunner>() {
@Override
public NodeRunner call(NodeRunner arg) {
if (arg.getUuid() == index) {
return arg;
}
return null;
}
});
stopNode(node, timeout);
}
public void stopNode(final String managementNodeId, int timeout) {
NodeRunner node = CollectionUtils.find(nodes, new Function<NodeRunner, NodeRunner>() {
@Override
public NodeRunner call(NodeRunner arg) {
if (arg.getManagementNodeId().equals(managementNodeId)) {
return arg;
}
return null;
}
});
stopNode(node, timeout);
}
public void asyncStopNode(final int index, final int timeout) {
new Runnable() {
@Override
@AsyncThread
public void run() {
stopNode(index, timeout);
}
}.run();
}
public void createLightWeightNodeWithCore(int num, final int timeout, List<String> springConfigs) {
List<NodeRunner> ns = new ArrayList<NodeRunner>();
for (int i = 0; i < num; i++) {
NodeRunner node = new NodeRunner();
int port = 8100 + i;
node.setPort(port);
node.setSpringConfigs(springConfigs);
node.setServiceId("node" + i);
node.setUuid(i);
List<String> sconfs = new ArrayList<String>();
sconfs.addAll(springConfigs);
sconfs.addAll(Arrays.asList("PortalForUnitTest.xml", "AccountManager.xml"));
node.setSpringConfigs(sconfs);
if (properties != null) {
node.setPropertyString(properties);
}
node.run();
ns.add(node);
}
final CountDownLatch latch = new CountDownLatch(num);
final List<String> lst = new ArrayList<String>();
for (final NodeRunner node : ns) {
new Runnable() {
@Override
@AsyncThread
public void run() {
throwableSafe(new Runnable() {
@Override
public void run() {
if (!node.waitNodeStart(timeout)) {
lst.add(String.format("node[%s] start timeout after %s seconds", node.getServiceId(), timeout));
}
}
});
latch.countDown();
}
}.run();
}
try {
latch.await();
} catch (InterruptedException e) {
throw new CloudRuntimeException(e);
}
if (!lst.isEmpty()) {
throw new CloudRuntimeException(StringUtils.join(lst, "\n"));
}
nodes.addAll(ns);
}
public void createNodes(int num, final int timeout) {
List<NodeRunner> ns = new ArrayList<NodeRunner>();
for (int i = 0; i < num; i++) {
NodeRunner node = new NodeRunner();
int port = portStart++;
node.setLoadAll(true);
node.setPort(port);
node.setServiceId("node" + nodeStart++);
node.setUuid(i);
if (properties != null) {
properties = properties(port) + properties;
} else {
properties = properties(port);
}
node.setPropertyString(properties);
node.run();
ns.add(node);
}
final CountDownLatch latch = new CountDownLatch(num);
final List<String> lst = new ArrayList<String>();
for (final NodeRunner node : ns) {
new Runnable() {
@Override
@AsyncThread
public void run() {
throwableSafe(new Runnable() {
@Override
public void run() {
if (!node.waitNodeStart(timeout)) {
lst.add(String.format("node[%s] start timeout after %s seconds", node.getServiceId(), timeout));
}
}
});
latch.countDown();
}
}.run();
}
try {
latch.await();
} catch (InterruptedException e) {
throw new CloudRuntimeException(e);
}
if (!lst.isEmpty()) {
throw new CloudRuntimeException(StringUtils.join(lst, "\n"));
}
nodes.addAll(ns);
}
private void stopNode(final NodeRunner node, final int timeout) {
throwableSafe(new Runnable() {
@Override
public void run() {
if (!node.waitNodeExit(timeout)) {
logger.debug(String.format("failed to stop node[%s] in %s seconds, kill it", node.getServiceId(), timeout));
node.kill();
}
}
});
}
public void stopNodes(final int timeout) {
final CountDownLatch latch = new CountDownLatch(nodes.size());
for (final NodeRunner node : nodes) {
new Runnable() {
@Override
@AsyncThread
public void run() {
stopNode(node, timeout);
latch.countDown();
}
}.run();
}
try {
latch.await(timeout, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new CloudRuntimeException(e);
}
}
}