package es.tid.tedb.controllers;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.metaparadigm.jsonrpc.JSONSerializer;
import es.tid.tedb.DomainTEDB;
import es.tid.tedb.IntraDomainEdge;
import es.tid.tedb.SimpleTEDB;
import es.tid.tedb.TE_Information;
import es.tid.tedb.controllers.TEDUpdaterController.MyEdge;
import es.tid.tedb.elements.RouterInfoPM;
public class TEDUpdaterTREMA extends TEDUpdaterController
{
public static String controllerName = "TREMA";
private Hashtable<Integer,MyEdge> interDomainLinks = new Hashtable<Integer,MyEdge>();
//Overwritten father variables and fixing the topology urls in code
private String topologyPathNodes = "/get_topology/";
private String topologyPathLinks = "/get_graph/";//??
public TEDUpdaterTREMA(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log)
{
super( ip, port, topologyPathLinks, topologyPathNodes, ted, log);
}
public TEDUpdaterTREMA(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock)
{
super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock);
}
public TEDUpdaterTREMA(ArrayList<String> ips, ArrayList<String>ports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log)
{
super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log);
}
@Override
public void run()
{
if(interDomainFile != null)
{
interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile);
}
String responseLinks = "";
String responseNodes = "";
try
{
Hashtable<String,RouterInfoPM> nodes = new Hashtable<String,RouterInfoPM>();
for (int i = 0; i < ips.size(); i++)
{
responseNodes = queryForNodes(ips.get(i), ports.get(i));//query for topology
parseNodes(responseNodes, nodes, ips.get(i), ports.get(i));
log.info("responseNodes:::"+responseNodes);
}
}
catch (Exception e)
{
log.info(e.toString());
}
}
private String KDDItoFloodlight(String BristolFormat)
{
String floodFormat = new String(BristolFormat);
//Por algo se me conoce como el hacker
for (int i = 2; i < floodFormat.length(); i += 3)
{
floodFormat = floodFormat.substring(0, i) + ":" + floodFormat.substring(i, floodFormat.length());
}
log.info("BristolFormat--> " + BristolFormat + ", floodFormat-->" + floodFormat);
return floodFormat;
}
private void parseNodes(String response, Hashtable<String,RouterInfoPM> routerInfoList, String ip, String port)
{
try
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(response);
JSONObject jsonaux=(JSONObject) obj;
String host=(String)jsonaux.get("hostConfig").toString();
obj=parser.parse(host);
JSONObject jsonhost=(JSONObject) obj;
//FIXME: This info has been taken from TREMA controller but is not used. Take a look if it's necessary
String OPS_Label=(String)jsonhost.get("OPS label");
String Port_id=(String)jsonhost.get("Port_id");
String reach_nodes=(String)jsonhost.get("Reachable nodes");
String node_type=(String)jsonhost.get("nodeType");//Used for RouterType
RouterInfoPM rInfo = new RouterInfoPM();
String dpid=((String)jsonhost.get("Virtual_node_id")).replace("-", ":");
rInfo.setRouterID(dpid);//Bristol to floodlight?
rInfo.setConfigurationMode("Openflow");
rInfo.setControllerType(TEDUpdaterNOX.controllerName);
rInfo.setRouterType(node_type);
rInfo.setReachable_nodes(parseReachability(reach_nodes));
rInfo.setControllerIdentifier(ip, port);
rInfo.setControllerIP(ip);
rInfo.setControllerPort(port);
routerInfoList.put(rInfo.getRouterID(),rInfo);
((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo);
//Getting Links
//parseLinks(???);
//parseLinks(dpid, jsonarray)
}
catch (Exception e)
{
log.info(e.toString());
}
}
private LinkedList<String> parseReachability(String reach_nodes) {
boolean end=false;
int beginIndex=0;
LinkedList<String> nodes= new LinkedList<String>();
reach_nodes=reach_nodes.replace(" ", "");
System.out.println("Reachable Nodes:"+reach_nodes);
while (!end){
int pointer=reach_nodes.indexOf(",");
if (pointer==-1)
end=true;
else {
String node=reach_nodes.substring(beginIndex, pointer);
System.out.println("Reachable Node:"+node);
reach_nodes=reach_nodes.substring(pointer+1);
nodes.add(node);
}
}
if (reach_nodes.length()>0){
System.out.println("Reachable Node:"+reach_nodes);
nodes.add(reach_nodes);
}
return nodes;
}
private void parseLinks(String dpid,String links, Hashtable<String,RouterInfoPM> nodes) //NOX Parse Links. it's not used in TREMA
{
try {
//log.info("Inside parseJSON");
JSONParser parser = new JSONParser();
Object obj = parser.parse(links);
JSONArray msg = (JSONArray) obj;
Iterator<JSONObject> iterator = msg.iterator();
while (iterator.hasNext())
{
JSONObject jsonObject = (JSONObject) iterator.next();
//System.out.println(jsonObject.get("src-switch"));
IntraDomainEdge edge= new IntraDomainEdge();
String labels = (String) jsonObject.get("labels");//??
String destnode = ((String) jsonObject.get("peer_node")).replace("-", ":");
String type = (String) jsonObject.get("port_type");
RouterInfoPM source = nodes.get(dpid);
RouterInfoPM dest = nodes.get(destnode);
//((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source);
//((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest);
System.out.println("Srcnode: "+dpid);
System.out.println("Dstnode: "+destnode);
System.out.println("Srcport: "+jsonObject.get("port_id"));
System.out.println("Dstport: "+jsonObject.get("peer_port"));
if ((dest!= null)&&(source!=null)){
edge.setSrc_if_id(Long.parseLong((String)jsonObject.get("port_id")));
edge.setDst_if_id(Long.parseLong((String)jsonObject.get("peer_port")));
edge.setType(type);
// This is a big problem because info is not initialized from file
// and the controller doesn't give information about how many wlans
// the are
TE_Information tE_info = new TE_Information();
System.out.println("Labels: Original ("+labels+") and Parsed ("+labels.substring(labels.indexOf(",")+1,labels.indexOf("]"))+")");
tE_info.setNumberWLANs(Integer.parseInt(labels.substring(labels.indexOf(",")+1,labels.indexOf("]"))));
tE_info.initWLANs();
if (interDomainFile != null)
{
completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID());
}
edge.setTE_info(tE_info);
edge.setDirectional(true);
//Bidirectional case? See other TEDUpdaters.
((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge);
} else {
System.out.println("Link with an unknown node. Ingnoring...");
}
//log.info("Edge added:"+edge);
//log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString());
}
//parseRemainingLinksFromXML(nodes);
}
catch (Exception e)
{
log.info(e.toString());
}
}
// private void parseLinks(String links,Hashtable<String,RouterInfoPM> nodes)
// {
// try {
// //log.info("Inside parseJSON");
// JSONParser parser = new JSONParser();
// Object obj = parser.parse(links);
//
// JSONArray msg = (JSONArray) obj;
// Iterator<JSONObject> iterator = msg.iterator();
// while (iterator.hasNext())
// {
// JSONObject jsonObject = (JSONObject) iterator.next();
// //System.out.println(jsonObject.get("src-switch"));
// IntraDomainEdge edge= new IntraDomainEdge();
//
// JSONObject jsonObject_src = (JSONObject) jsonObject.get("src");
// JSONObject jsonObject_dst = (JSONObject) jsonObject.get("dst");
//
// RouterInfoPM source = nodes.get(BristoltoFloodlight((String)jsonObject_src.get("dpid")));
// RouterInfoPM dest = nodes.get(BristoltoFloodlight((String)jsonObject_dst.get("dpid")));
//
// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source);
// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest);
//
// log.info("Adding Vertex->"+source+" hashcode:"+source.hashCode());
// log.info("Adding Vertex->"+dest+" hashcode:"+dest.hashCode());
//
// edge.setSrc_if_id((Long)jsonObject_src.get("port_no"));
// edge.setDst_if_id((Long)jsonObject_dst.get("port_no"));
//
//
// // This is a big problem because info is not initialized from file
// // and the controller doesn't give information about how many wlans
// // the are
//
// TE_Information tE_info = new TE_Information();
// tE_info.setNumberWLANs(15);
// tE_info.initWLANs();
//
// if (interDomainFile != null)
// {
// completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID());
// }
//
// edge.setTE_info(tE_info);
//
// String isBidirectional = (String)jsonObject.get("direction");
//
//
// // En Bristol los enlaces son unidirecctionales, pero asumimos que hay uno en una direccion
// // esta el otro
// isBidirectional = "bidirectional";
//
// //log.info("isBidirectional::"+isBidirectional);
//
// if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional")))
// {
// //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge);
//
// TE_Information tE_infoOtherWay = new TE_Information();
// tE_infoOtherWay.setNumberWLANs(15);
// tE_infoOtherWay.initWLANs();
// IntraDomainEdge edgeOtherWay= new IntraDomainEdge();
//
// edgeOtherWay.setSrc_if_id((Long)jsonObject_src.get("port_no"));
// edgeOtherWay.setDst_if_id((Long)jsonObject_dst.get("port_no"));
// edgeOtherWay.setTE_info(tE_infoOtherWay);
//
// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge);
// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay);
//
// completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID());
//
// log.info("source::"+source);
// log.info("dest::"+dest);
// log.info("edgeOtherWay::"+edgeOtherWay);
// log.info("edge::"+edge);
// //log.info("Adding two!");
// }
// else
// {
// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge);
// }
//
// //log.info("Edge added:"+edge);
// //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString());
// }
// //parseRemainingLinksFromXML(nodes);
//
//
// }
// catch (Exception e)
// {
// log.info(UtilsFunctions.exceptionToString(e));
// }
// }
private void completeTE_Information(TE_Information tE_info, String source, String dest)
{
MyEdge auxEdge = new MyEdge(source, dest);
MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode());
if ((completEdge != null)&&(completEdge.vlan != null))
{
tE_info.setVlanLink(true);
tE_info.setVlan(completEdge.vlan);
//If it has been found it will be removed so the rest can be proccessed later
interDomainLinks.remove(completEdge.vlan);
}
else
{
tE_info.setVlanLink(false);
}
}
private String queryForLinks(String ip, String port)
{
String response = "";
try
{
URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathLinks);
log.info("URL::"+"http://"+ip+":"+port+topologyPathLinks);
URLConnection yc = topoplogyURL.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
response = response + inputLine;
}
}
catch (Exception e)
{
log.info(e.toString());
}
return response;
}
private String queryForNodes(String ip, String port)
{
String response = "";
try
{
URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathNodes);
log.info("http://+port+topologyPathNodes:::"+"http://"+ip+":"+port+topologyPathNodes);
URLConnection yc = topoplogyURL.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
response = response + inputLine;
}
in.close();
}
catch (Exception e)
{
log.info(e.toString());
}
return response;
}
public String getInterDomainFile()
{
return interDomainFile;
}
public void setInterDomainFile(String interDomainFile)
{
this.interDomainFile = interDomainFile;
}
private void lock()
{
if (lock != null)
{
lock.lock();
}
}
private void unlock()
{
if (lock != null)
{
lock.unlock();
}
}
}