package com.github.kaitoy.sneo.network;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mx4j.log.Log4JLogger;
import org.pcap4j.util.MacAddress;
import org.snmp4j.SNMP4JSettings;
import org.snmp4j.log.Log4jLogFactory;
import org.snmp4j.log.LogFactory;
import com.github.kaitoy.sneo.agent.FileMibAgent;
import com.github.kaitoy.sneo.agent.FileMibCiscoAgent;
import com.github.kaitoy.sneo.jmx.JmxAgent;
import com.github.kaitoy.sneo.network.dto.IpAddressDto;
import com.github.kaitoy.sneo.network.dto.IpV4RouteDto;
import com.github.kaitoy.sneo.network.dto.IpV6RouteDto;
import com.github.kaitoy.sneo.network.dto.L2ConnectionDto;
import com.github.kaitoy.sneo.network.dto.LagDto;
import com.github.kaitoy.sneo.network.dto.NetworkDto;
import com.github.kaitoy.sneo.network.dto.NodeDto;
import com.github.kaitoy.sneo.network.dto.PhysicalNetworkInterfaceDto;
import com.github.kaitoy.sneo.network.dto.RealNetworkInterfaceDto;
import com.github.kaitoy.sneo.network.dto.SnmpAgentDto;
import com.github.kaitoy.sneo.network.dto.TrapTargetDto;
import com.github.kaitoy.sneo.network.dto.TrapTargetGroupDto;
import com.github.kaitoy.sneo.network.dto.VlanDto;
import com.github.kaitoy.sneo.network.dto.VlanMemberDto;
import com.github.kaitoy.sneo.smi.SmiSyntaxesPropertiesManager;
import com.github.kaitoy.sneo.transport.TransportsPropertiesManager;
import com.github.kaitoy.sneo.util.ColonSeparatedOidTypeValueVariableTextFormat;
public class Network {
static {
LogFactory.setLogFactory(new Log4jLogFactory());
mx4j.log.Log.redirectTo(new Log4JLogger());
SmiSyntaxesPropertiesManager.getInstance().useExtendedSmi();
TransportsPropertiesManager.getInstance().extendTransportMappings();
SNMP4JSettings.setVariableTextFormat(
ColonSeparatedOidTypeValueVariableTextFormat.getInstance()
);
}
private final String name;
private List<FileMibAgent> agents = new ArrayList<FileMibAgent>();
private List<Node> nodes = new ArrayList<Node>();
private List<L2Connection> l2conns = new ArrayList<L2Connection>();
private Map<Integer, PhysicalNetworkInterface> physNifs
= new HashMap<Integer, PhysicalNetworkInterface>();
public Network(NetworkDto networkDto) {
this.name = networkDto.getName();
for (NodeDto nodeDto: networkDto.getNodes()) {
nodes.add(newNode(nodeDto));
}
for (L2ConnectionDto l2Dto: networkDto.getL2Connections()) {
l2conns.add(newL2Connection(l2Dto));
}
}
public void start(String domain, JmxAgent jmxAgent) {
for (Node node: nodes) {
node.start(false);
jmxAgent.registerPojo(node, formObjectName(domain, node));
}
for (L2Connection l2conn: l2conns) {
l2conn.start();
}
for (FileMibAgent agent: agents) {
agent.start();
}
}
public void stop(String domain, JmxAgent jmxAgent) {
for (Node node: nodes) {
jmxAgent.unregisterMBean(formObjectName(domain, node));
node.shutdown();
}
for (L2Connection l2conn: l2conns) {
l2conn.shutdown();
}
}
private String formObjectName(String domain, Node node) {
// Don't quote both domain and properties
// so users can easily twiddle mbeans by command line tools.
StringBuilder sb = new StringBuilder(200);
sb.append(domain).append(":")
.append("network=").append(name)
.append(",type=").append(node.getClass().getSimpleName())
.append(",name=").append(node.getName());
return sb.toString();
}
private FileMibAgent newSnmpAgent(SnmpAgentDto snmpAgentDto) {
FileMibAgent.Builder vAgentBuilder;
List<String> communityStringIndexes
= snmpAgentDto.getCommunityStringIndexes();
if (communityStringIndexes != null && communityStringIndexes.size() != 0) {
vAgentBuilder
= new FileMibCiscoAgent.Builder()
.communityStringIndexes(communityStringIndexes);
}
else {
vAgentBuilder = new FileMibAgent.Builder();
}
String address = snmpAgentDto.getAddress();
vAgentBuilder
.address("udp:" + address + "/" + snmpAgentDto.getPort())
.bcConfigFilePath("conf" + File.separator + address + "_bc.conf")
.configFilePath("conf" + File.separator + address + ".conf")
.communityName(snmpAgentDto.getCommunityName())
.securityName(snmpAgentDto.getSecurityName())
.fileMibPath(snmpAgentDto.getFileMibPath())
.format(snmpAgentDto.getFileMibFormat());
TrapTargetGroupDto trapTargetGroup = snmpAgentDto.getTrapTargetGroup();
if (trapTargetGroup != null) {
List<TrapTargetDto> trapTargets = trapTargetGroup.getTrapTargets();
if (trapTargets != null && trapTargets.size() != 0) {
TrapTargetDto tt = trapTargets.get(0);
vAgentBuilder.trapTarget(tt.getAddress() + "/" + tt.getPort());
}
}
FileMibAgent agent = vAgentBuilder.build();
try {
agent.init();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return agent;
}
private Node newNode(NodeDto nodeDto) {
SnmpAgentDto agentDto = nodeDto.getAgent();
FileMibAgent agent = null;
if (agentDto != null) {
agent = newSnmpAgent(agentDto);
agents.add(agent);
}
Node node = new Node(nodeDto.getName(), agent, nodeDto.getTtl());
for (PhysicalNetworkInterfaceDto nifDto: nodeDto.getPhysicalNetworkInterfaces()) {
node.addNif(nifDto.getName(), nifDto.isTrunk());
for (IpAddressDto ipAddrDto: nifDto.getIpAddresses()) {
node.addIpAddress(
nifDto.getName(),
ipAddrDto.getAddress(),
ipAddrDto.getPrefixLength()
);
}
physNifs.put(
nifDto.getId(),
(PhysicalNetworkInterface)node.getNif(nifDto.getName())
);
}
for (RealNetworkInterfaceDto nifDto: nodeDto.getRealNetworkInterfaces()) {
node.addRealNif(
nifDto.getName(),
MacAddress.getByName(nifDto.getMacAddress()),
nifDto.getDeviceName()
);
for (IpAddressDto ipAddrDto: nifDto.getIpAddresses()) {
node.addIpAddress(
nifDto.getName(),
ipAddrDto.getAddress(),
ipAddrDto.getPrefixLength()
);
}
}
for (LagDto lagDto: nodeDto.getLags()) {
node.addLag(lagDto.getName(), lagDto.getChannelGroupNumber());
for (IpAddressDto ipAddrDto: lagDto.getIpAddresses()) {
node.addIpAddress(
lagDto.getName(),
ipAddrDto.getAddress(),
ipAddrDto.getPrefixLength()
);
}
for (PhysicalNetworkInterfaceDto nifDto: lagDto.getPhysicalNetworkInterfaces()) {
node.addNifToLag(nifDto.getName(), lagDto.getChannelGroupNumber());
}
}
for (VlanDto vlanDto: nodeDto.getVlans()) {
node.addVlan(vlanDto.getName(), vlanDto.getVid());
for (IpAddressDto ipAddrDto: vlanDto.getIpAddresses()) {
node.addIpAddress(
vlanDto.getName(),
ipAddrDto.getAddress(),
ipAddrDto.getPrefixLength()
);
}
for (VlanMemberDto nifDto: vlanDto.getVlanMembers()) {
String aggregatorName = null;
if (nifDto instanceof PhysicalNetworkInterfaceDto) {
aggregatorName
= ((PhysicalNetworkInterfaceDto)nifDto).getAggregatorName();
}
if (aggregatorName != null) {
// Add an aggregater instead of a NIF itself
// so forwarding done in VlanInterface works well.
node.addNifToVlan(aggregatorName, vlanDto.getVid());
}
else {
node.addNifToVlan(nifDto.getName(), vlanDto.getVid());
}
}
}
for (IpV4RouteDto routeDto: nodeDto.getIpV4Routes()) {
node.addIpV4Route(
routeDto.getNetworkDestination(),
routeDto.getNetmask(),
routeDto.getGateway(),
routeDto.getMetric()
);
}
for (IpV6RouteDto routeDto: nodeDto.getIpV6Routes()) {
node.addIpV6Route(
routeDto.getNetworkDestination(),
routeDto.getPrefixLength(),
routeDto.getGateway(),
routeDto.getMetric()
);
}
return node;
}
private L2Connection newL2Connection(L2ConnectionDto l2Dto) {
List<PhysicalNetworkInterface> vnifs
= new ArrayList<PhysicalNetworkInterface>();
for (PhysicalNetworkInterfaceDto nifDto: l2Dto.getPhysicalNetworkInterfaces()) {
vnifs.add(physNifs.get(nifDto.getId()));
}
return L2Connection.connect(
l2Dto.getName(),
vnifs.toArray(new PhysicalNetworkInterface[0])
);
}
}