/**
* Copyright (c) <2013> <Radware Ltd.> and others. All rights reserved.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License
* v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
* @author Gera Goft
* @version 0.1
*/
package org.opendaylight.defense4all.core;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import me.prettyprint.cassandra.serializers.IntegerSerializer;
import me.prettyprint.cassandra.serializers.StringSerializer;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.opendaylight.defense4all.framework.core.ExceptionControlApp;
import org.opendaylight.defense4all.framework.core.FMHolder;
import org.opendaylight.defense4all.framework.core.HealthTracker;
import org.opendaylight.defense4all.framework.core.PropertiesSerializer;
import org.opendaylight.defense4all.framework.core.RepoCD;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author gerag
*
*/
@JsonIgnoreProperties({"amsConnections","trafficPorts","protectedLinks"})
public class NetNode {
public static final String ITEMS_DELIMITER = ":";
public static final String LIST_ITEMS_DELIMITER = "::";
static Logger log = LoggerFactory.getLogger(NetNode.class);
public enum SDNNodeMode {
sdnenablednative, sdnenabledhybrid
}
public enum Status {
INVALID,
ACTIVE,
REMOVED
}
/* NetNode types to conform with ODL Node types. Omitting PE=PCEP and PR=Production */
public static final String OF = "OF";
public static final String PK = "PK";
/* NetNode Repo common columns */
public static final String ID = "id";
public static final String LABEL = "label";
public static final String TYPE = "type";
public static final String MGMT_IP_ADDR_STRING = "mgmt_ip_addr_string";
public static final String MGMT_PORT = "mgmt_port";
public static final String OF_MODE = "of_mode";
public static final String HEALTH_CHECK_FREQUENCY = "health_check_frequency";
public static final String STATUS = "status";
public static final String AMS_CONNECTION_PREFIX = "ams_connection_";
public static final String PORT_PREFIX = "port_";
public static final String PORTS_LINK_PREFIX = "ports_link_";
public static final String PROPS = "props";
public static final int DEFAULT_HEALTH_CHECK_FREQUENCY = 10;
protected static ArrayList<RepoCD> netNodeRepoCDs = null;
public String label; // Record key.
public String id; // For OpenFlow NetNodes this is the DPID
public String type; // Covers ODL Node types and beyond
public String mgmtAddr;
public int mgmtPort;
public SDNNodeMode sdnNodeMode;
public int healthCheckFrequency; // When in-path in secs. When out of path - decrease frequency by X 10
public Status status;
public Properties props;
public Hashtable<String,AMSConnection> amsConnections; public String amsConnectionsStr;
public Hashtable<String,TrafficPort> trafficPorts; public String trafficPortsStr;
public Hashtable<String,ProtectedLink> protectedLinks; public String protectedLinksStr;
public String getAmsConnectionsStr() {return amsConnectionsStr;}
public void setAmsConnectionsStr(String amsConnectionsStr) {
this.amsConnectionsStr = amsConnectionsStr;
this.amsConnections = fromAmsConnectionsStr(amsConnectionsStr);
}
public String getTrafficPortsStr() {return trafficPortsStr;}
public void setTrafficPortsStr(String trafficPortsStr) {
this.trafficPortsStr = trafficPortsStr;
this.trafficPorts = fromTrafficPortsStr(trafficPortsStr);
}
public String getProtectedLinksStr() {return protectedLinksStr;}
public void setProtectedLinksStr(String protectedLinksStr) {
this.protectedLinksStr = protectedLinksStr;
this.protectedLinks = fromProtectedLinksStr(protectedLinksStr);
}
public static String generateAMSConnColName(String amsConnLabel) {return AMS_CONNECTION_PREFIX + amsConnLabel; }
/* ### Description ###
* @param param_name
*/
public NetNode() {
label = null; id = null; type = null; mgmtAddr = null; mgmtPort = 0; sdnNodeMode = SDNNodeMode.sdnenablednative;
healthCheckFrequency = DEFAULT_HEALTH_CHECK_FREQUENCY; status = Status.INVALID;
amsConnectionsStr = null; amsConnections = new Hashtable<String,AMSConnection>();
trafficPortsStr = null; trafficPorts = new Hashtable<String,TrafficPort>();
protectedLinksStr = null; protectedLinks = new Hashtable<String,ProtectedLink>();
props = new Properties();
}
/* ### Description ###
* @param param_name
*/
public NetNode(String label, String id, String type, String mgmtAddr, int port, SDNNodeMode sdnNodeMode,
int healthCheckFrequency) {
this();
this.label = (label == null || label.isEmpty()) ? "label_" + id : label;
this.id = id; this.type = type; this.mgmtAddr = mgmtAddr; this.mgmtPort = port;
this.sdnNodeMode = sdnNodeMode; this.healthCheckFrequency = healthCheckFrequency;
}
/* ### Description ###
* @param param_name
*/
public NetNode(String label, String id, String type, String mgmtAddr, int port, SDNNodeMode sdnNodeMode,
int healthCheckFrequency, String amsConnectionsStr, String trafficPortsStr, String protectedLinksStr) {
this(label, id, type, mgmtAddr, port, sdnNodeMode, healthCheckFrequency);
if ( amsConnections != null && ! amsConnections.isEmpty())
this.amsConnections = fromAmsConnectionsStr(amsConnectionsStr);
if ( trafficPorts != null && ! trafficPorts.isEmpty())
this.trafficPorts = fromTrafficPortsStr(trafficPortsStr);
if ( protectedLinks != null && ! protectedLinks.isEmpty())
this.protectedLinks = fromProtectedLinksStr(protectedLinksStr);
}
public void toJacksonFriendly() {
setAmsConnectionsStr();
setTrafficPortsStr();
setProtectedLinksStr();
}
protected Hashtable<String, AMSConnection> fromAmsConnectionsStr(String amsConnectionsStr) {
String[] split = amsConnectionsStr.split(LIST_ITEMS_DELIMITER);
if(split == null) return null;
Hashtable<String, AMSConnection> inflatedAmsConnections = new Hashtable<String, AMSConnection>();
AMSConnection amsConnection;
for(int i=0;i<split.length;i++) {
try {
amsConnection = new AMSConnection(split[i]);
inflatedAmsConnections.put(amsConnection.label, amsConnection);
} catch ( Throwable e) {continue;}
}
return inflatedAmsConnections;
}
protected void setAmsConnectionsStr() {
if(amsConnections == null || amsConnections.isEmpty()) {
amsConnectionsStr = "";
return;
}
Iterator<Map.Entry<String,AMSConnection>> iter = amsConnections.entrySet().iterator();
StringBuilder sb = new StringBuilder();
AMSConnection amsConnection; String amsConnectionStr;
while(iter.hasNext()) {
amsConnection = iter.next().getValue();
amsConnectionStr = amsConnection.toString();
sb.append(amsConnectionStr); sb.append(LIST_ITEMS_DELIMITER);
}
sb.setLength(sb.length() - LIST_ITEMS_DELIMITER.length()); // Remove the last LIST_ITEMS_DELIMITER
amsConnectionsStr = sb.toString();
}
protected Hashtable<String, TrafficPort> fromTrafficPortsStr(String trafficPortsStr) {
String[] split = trafficPortsStr.split(LIST_ITEMS_DELIMITER);
if(split == null) return null;
Hashtable<String, TrafficPort> InflatedTrafficPorts = new Hashtable<String, TrafficPort>();
TrafficPort trafficPort;
for(int i=0;i<split.length;i++) {
try {
trafficPort = new TrafficPort(split[i]);
InflatedTrafficPorts.put(trafficPort.label, trafficPort);
} catch ( Throwable e) {continue;}
}
return InflatedTrafficPorts;
}
protected void setTrafficPortsStr() {
if(trafficPorts == null || trafficPorts.isEmpty()) {
trafficPortsStr = "";
return;
}
Iterator<Map.Entry<String,TrafficPort>> iter = trafficPorts.entrySet().iterator();
StringBuilder sb = new StringBuilder();
TrafficPort trafficPort; String trafficPortStr;
while(iter.hasNext()) {
trafficPort = iter.next().getValue();
trafficPortStr = trafficPort.toString();
sb.append(trafficPortStr); sb.append(LIST_ITEMS_DELIMITER);
}
sb.setLength(sb.length() - LIST_ITEMS_DELIMITER.length()); // Remove the last LIST_ITEMS_DELIMITER
trafficPortsStr = sb.toString();
}
protected Hashtable<String, ProtectedLink> fromProtectedLinksStr(String protectedLinksStr) {
String[] split = protectedLinksStr.split(LIST_ITEMS_DELIMITER);
if(split == null) return null;
Hashtable<String, ProtectedLink> InflatedProtectedLinks = new Hashtable<String, ProtectedLink>();
ProtectedLink protectedLink;
for(int i=0;i<split.length;i++) {
protectedLink = new ProtectedLink(split[i]);
InflatedProtectedLinks.put(protectedLink.label, protectedLink);
}
return InflatedProtectedLinks;
}
protected void setProtectedLinksStr() {
if(protectedLinks == null || protectedLinks.isEmpty()) {
protectedLinksStr = "";
return;
}
Iterator<Map.Entry<String,ProtectedLink>> iter = protectedLinks.entrySet().iterator();
StringBuilder sb = new StringBuilder();
ProtectedLink protectedLink; String protectedLinkStr;
while(iter.hasNext()) {
protectedLink = iter.next().getValue();
protectedLinkStr = protectedLink.toString();
sb.append(protectedLinkStr); sb.append(LIST_ITEMS_DELIMITER);
}
sb.setLength(sb.length() - LIST_ITEMS_DELIMITER.length()); // Remove the last LIST_ITEMS_DELIMITER
protectedLinksStr = sb.toString();
}
public NetNode(Hashtable<String, Object> netNodeRow) throws ExceptionControlApp {
this();
label = (String) netNodeRow.get(LABEL);
id = (String) netNodeRow.get(ID);
type = (String) netNodeRow.get(TYPE);
mgmtAddr = (String) netNodeRow.get(MGMT_IP_ADDR_STRING);
mgmtPort = (Integer) netNodeRow.get(MGMT_PORT);
sdnNodeMode = SDNNodeMode.valueOf((String) netNodeRow.get(OF_MODE));
healthCheckFrequency = (Integer) netNodeRow.get(HEALTH_CHECK_FREQUENCY);
status = Status.valueOf((String) netNodeRow.get(STATUS));
props = (Properties) netNodeRow.get(PROPS);
Iterator<Map.Entry<String,Object>> iter = netNodeRow.entrySet().iterator();
Map.Entry<String,Object> entry; String columnName;
AMSConnection amsConnection; TrafficPort port; ProtectedLink portsLink;
while(iter.hasNext()) {
entry = iter.next();
columnName = (String) entry.getKey();
if(columnName.startsWith(AMS_CONNECTION_PREFIX)) {
try {
amsConnection = new AMSConnection((String) entry.getValue());
amsConnections.put(amsConnection.label, amsConnection);
} catch (Throwable e) {
log.error("Failed to instantiate AMSConnection using " + entry.getValue().toString());
throw new ExceptionControlApp("Failed to instantiate AMSConnection using "+entry.getValue().toString(),e);
}
} else if(columnName.startsWith(PORT_PREFIX)) {
try {
port = new TrafficPort((String) entry.getValue());
trafficPorts.put(port.label, port);
} catch (Throwable e) {
log.error("Failed to instantiate TrafficPort using " + entry.getValue().toString());
throw new ExceptionControlApp("Failed to instantiate TrafficPort using "+entry.getValue().toString(),e);
}
} else if(columnName.startsWith(PORTS_LINK_PREFIX)) {
try {
portsLink = new ProtectedLink((String) entry.getValue());
protectedLinks.put(portsLink.label, portsLink);
} catch (Throwable e) {
log.error("Failed to instantiate ProtectedLink using " + entry.getValue().toString());
throw new ExceptionControlApp("Failed to instantiate ProtectedLink using "+entry.getValue().toString(),e);
}
}
}
}
public Hashtable<String, Object> toRow() {
/* Change any null value to empty, otherwise Hashtable.put() will throw an exception */
if(label == null) label = "";
if(id == null) id = "";
if(props == null) props = new Properties();
String mgmtAddrStr = mgmtAddr == null ? "" : mgmtAddr;
Hashtable<String, Object> row = new Hashtable<String, Object>();
row.put(LABEL, label);
row.put(ID, id);
row.put(TYPE, type);
row.put(MGMT_IP_ADDR_STRING, mgmtAddrStr);
row.put(MGMT_PORT, mgmtPort);
row.put(OF_MODE, sdnNodeMode.name());
row.put(HEALTH_CHECK_FREQUENCY, healthCheckFrequency);
row.put(STATUS, status.name());
row.put(PROPS, props);
String columnName; String cellValue;
Iterator<Map.Entry<String,AMSConnection>> amdConnectionIter = amsConnections.entrySet().iterator();
Map.Entry<String,AMSConnection> amsConnectionEntry;
while(amdConnectionIter.hasNext()) {
amsConnectionEntry = amdConnectionIter.next();
columnName = generateAMSConnColName( amsConnectionEntry.getKey());
cellValue = amsConnectionEntry.getValue().toString();
row.put(columnName, cellValue);
}
Iterator<Map.Entry<String,TrafficPort>> portIter = trafficPorts.entrySet().iterator();
Map.Entry<String,TrafficPort> portEntry;
while(portIter.hasNext()) {
portEntry = portIter.next();
columnName = PORT_PREFIX + (String) portEntry.getKey();
cellValue = portEntry.getValue().toString();
row.put(columnName, cellValue);
}
Iterator<Map.Entry<String,ProtectedLink>> portsLinkIter = protectedLinks.entrySet().iterator();
Map.Entry<String,ProtectedLink> portsLinkEntry;
while(portsLinkIter.hasNext()) {
portsLinkEntry = portsLinkIter.next();
columnName = PORTS_LINK_PREFIX + (String) portsLinkEntry.getKey();
cellValue = portsLinkEntry.getValue().toString();
row.put(columnName, cellValue);
}
return row;
}
public String getId() {return id;}
public void setId(String id) {this.id = id;}
public String getType() {return type;}
public void setType(String type) {this.type = type;}
public String getMgmtAddr() {return mgmtAddr;}
public void setMgmtAddr(String mgmtAddr) {this.mgmtAddr = mgmtAddr;}
public SDNNodeMode getOfType() {return sdnNodeMode;}
public void setOfType(SDNNodeMode ofMode) {this.sdnNodeMode = ofMode;}
public Hashtable<String, AMSConnection> getAmsConnections() {return amsConnections;}
public void setAmsConnections(Hashtable<String, AMSConnection> connections) {this.amsConnections = connections;}
public Hashtable<String, TrafficPort> getPorts() {return trafficPorts;}
public void setPorts(Hashtable<String, TrafficPort> ports) {this.trafficPorts = ports;}
public Hashtable<String, ProtectedLink> getPortsLinks() {return protectedLinks;}
public void setPortsLinks(Hashtable<String, ProtectedLink> portsLinks) {this.protectedLinks = portsLinks;}
public String getLabel() {return label;}
public void setLabel(String label) {this.label = label;}
public int getMgmtPort() {return mgmtPort;}
public void setMgmtPort(int mgmtPort) {this.mgmtPort = mgmtPort;}
public int getHealthCheckFrequency() {return healthCheckFrequency;}
public void setHealthCheckFrequency(int healthCheckFrequency) {this.healthCheckFrequency = healthCheckFrequency;}
public Status getStatus() {return status;}
public void setStatus(Status status) {this.status = status;}
public Properties getProps() {return props;}
public void setProps(Properties props) {this.props = props;}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("NetNode [label="); sb.append(label); sb.append(", ");
sb.append("id="); sb.append(id); sb.append(", ");
sb.append("type="); sb.append(type); sb.append(", ");
sb.append("mgmtAddr="); sb.append(mgmtAddr); sb.append(", ");
sb.append("mgmtPort="); sb.append(mgmtPort); sb.append(", ");
sb.append("sdnNodeMode="); sb.append(sdnNodeMode); sb.append(", ");
sb.append("healthCheckFrequency="); sb.append(healthCheckFrequency); sb.append(", ");
Iterator<Map.Entry<String,AMSConnection>> iter1 = amsConnections.entrySet().iterator();
while(iter1.hasNext()) {
sb.append("amsConnection="); sb.append(iter1.next().getValue().toString()); sb.append(", ");
}
Iterator<Map.Entry<String,TrafficPort>> iter2 = trafficPorts.entrySet().iterator();
while(iter2.hasNext()) {
sb.append("trafficPort="); sb.append(iter2.next().getValue().toString()); sb.append(", ");
}
Iterator<Map.Entry<String,ProtectedLink>> iter3 = protectedLinks.entrySet().iterator();
while(iter3.hasNext()) {
sb.append("protectedLink="); sb.append(iter3.next().getValue().toString()); sb.append(", ");
}
if ( status == Status.REMOVED ) {
sb.append("status="); sb.append(status); sb.append(", ");
}
sb.append("props="); sb.append(props.toString());
sb.append("]");
return sb.toString();
}
public static List<RepoCD> getNetNodeRCDs() {
if(netNodeRepoCDs == null) {
RepoCD rcd;
netNodeRepoCDs = new ArrayList<RepoCD>();
rcd = new RepoCD(LABEL, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(ID, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(TYPE, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(MGMT_IP_ADDR_STRING, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(MGMT_PORT, IntegerSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(OF_MODE, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(STATUS, StringSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(HEALTH_CHECK_FREQUENCY, IntegerSerializer.get(), null); netNodeRepoCDs.add(rcd);
rcd = new RepoCD(PROPS, PropertiesSerializer.get(), null); netNodeRepoCDs.add(rcd);
}
return netNodeRepoCDs;
}
public void validate() throws Exception {
if(label == null || label.isEmpty()) throw new Exception("Invalid netnode label.");
// Iterator<Map.Entry<String,AMSConnection>> iter1 = amsConnections.entrySet().iterator();
// while(iter1.hasNext()) {
// iter1.next().getValue().validate();
// }
Iterator<Map.Entry<String,TrafficPort>> iter2 = trafficPorts.entrySet().iterator();
while(iter2.hasNext()) {
iter2.next().getValue().validate();
}
Iterator<Map.Entry<String,ProtectedLink>> iter3 = protectedLinks.entrySet().iterator();
while(iter3.hasNext()) {
iter3.next().getValue().validate();
}
}
public static boolean isRemoved(String netNodeLabel) {
try {
String netNodeStatusStr = (String) DFHolder.get().netNodesRepo.getCellValue(netNodeLabel, NetNode.STATUS);
Status netNodeStatus = Status.valueOf(netNodeStatusStr);
if(netNodeStatus == Status.REMOVED) return true;
return false;
} catch (Throwable e) {return false;}
}
public static boolean isRemoved(Hashtable<String,Object> netNodeRow) {
try {
String netNodeStatusStr = (String) netNodeRow.get(STATUS);
Status netNodeStatus = Status.valueOf(netNodeStatusStr);
if(netNodeStatus == Status.REMOVED) return true;
return false;
} catch (Throwable e) {return false;}
}
/**
*
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public static NetNode getNetNode(String netNodeKey) {
try {
Hashtable<String, Object> netNodeRow = DFHolder.get().netNodesRepo.getRow(netNodeKey);
if(netNodeRow == null) {
log.error("Got null netNodeRow for key " + netNodeKey);
return null;
}
NetNode netNode = new NetNode(netNodeRow);
return netNode;
} catch (Throwable e) {
log.error("Failed to getNetNode : "+netNodeKey, e);
FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
return null;
}
}
}