/**
* 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
* @author Pozdeev Konstantin
* @version 0.1
*/
package org.opendaylight.defense4all.core;
import java.lang.IllegalArgumentException;
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.BooleanSerializer;
import me.prettyprint.cassandra.serializers.StringSerializer;
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;
public class DvsnInfo {
static Logger log = LoggerFactory.getLogger(DvsnInfo.class);
/* AMS Repo common columns */
public static final String KEY = "key";
public static final String NETNODE_LABEL = "netnode_label";
public static final String TRAFFIC_FLOOR_KEY = "traffic_floor_key";
public static final String MITIGATION_KEY = "mitigation_key";
public static final String CONFIG_PROPS = "config_props";
public static final String AMS_DIVERSION_INFO_PREFIX = "ams_diversion_info_";
public static final String TRAFFIC_DIVERTED = "traffic_diverted";
/* Config props common fields. */
public static final String INBOUND_BANDWIDTH = "inbound_bandwidth";
public static class AMSDvsnInfo {
public String label;
public Properties amsDvsnProps; // Information related to the act of traffic diversion to this AMS
public AMSDvsnInfo() {label = null; amsDvsnProps = null;}
public AMSDvsnInfo(String amsLabel, Properties configProps, Properties dvsnProps) {
this.label = amsLabel;
if(dvsnProps == null)
this.amsDvsnProps = null;
else {
this.amsDvsnProps = new Properties();
this.amsDvsnProps.putAll(dvsnProps);
}
}
public AMSDvsnInfo(String amsDvsnInfoStr) throws IllegalArgumentException {
if(amsDvsnInfoStr == null) throw new IllegalArgumentException("Null amsDvsnInfoStr param.");
String[] split = null;
try {
split = amsDvsnInfoStr.split(":::");
if(split.length < 2) throw new IllegalArgumentException("missing spit parts.");
label = split[0];
amsDvsnProps = split[1] == null ? null : PropertiesSerializer.get().fromString(split[1]);
} catch (Throwable e) {
log.error("Invalid format of amsDvsnInfoStr", e);
throw new IllegalArgumentException("Invalid format of amsDvsnInfoStr", e);
}
}
public AMSDvsnInfo(AMSDvsnInfo other) {
this.label = other.label;
this.amsDvsnProps = new Properties(); this.amsDvsnProps.putAll(other.amsDvsnProps);
}
public String toString() {
StringBuilder sb = new StringBuilder();
String s;
sb.append(label); sb.append(":::");
s = PropertiesSerializer.get().toString(amsDvsnProps);
sb.append(s);
return sb.toString();
}
}
public String key;
public String netNodeLabel; // netNode from which to divert traffic to the selected set of AMSs
public String tFloorKey; // Traffic floor containing the details of this diversion.
public String mitigationKey; // Relation to the mitigation for which diversion is triggered
public Properties configProps; // NetNode level configuration params. Different from dvsnProps per AMS
public boolean trafficDiverted; // Indicator whether the traffic has been diverted
public List<AMSDvsnInfo> amsDvsnInfos; // Diversion and configuration information of each AMS used for this diversion
protected static ArrayList<RepoCD> repoCDs = null;
public static String generateDvsnInfoKey(String netNodeLabel, String mitigationKey) {
StringBuilder sb = new StringBuilder();
sb.append(netNodeLabel); sb.append("_"); sb.append(mitigationKey);
return sb.toString();
}
public DvsnInfo(String key ) {
// placeholder for return incomplete object
this.key = key;
}
public DvsnInfo(String netNodeLabel, String tFloorKey, String mitigationKey, List<AMSDvsnInfo> amsDvsnInfos,
Properties configProps) {
this.key = generateDvsnInfoKey(netNodeLabel, mitigationKey);
this.netNodeLabel = netNodeLabel; this.tFloorKey = tFloorKey; this.mitigationKey = mitigationKey;
this.amsDvsnInfos = amsDvsnInfos;
this.configProps = new Properties();
if(configProps != null)
this.configProps.putAll(configProps);
trafficDiverted = false;
}
public DvsnInfo(DvsnInfo other) {
this.key = other.key; this.netNodeLabel = other.netNodeLabel; this.tFloorKey = other.tFloorKey;
this.mitigationKey = other.mitigationKey;
this.amsDvsnInfos = other.amsDvsnInfos;
this.trafficDiverted = other.trafficDiverted;
if(other.configProps == null)
this.configProps = null;
else {
this.configProps = new Properties();
this.configProps.putAll(other.configProps);
}
}
public DvsnInfo(Hashtable<String, Object> row) throws IllegalArgumentException {
try {
key = (String) row.get(KEY);
netNodeLabel = (String) row.get(NETNODE_LABEL);
tFloorKey = (String) row.get(TRAFFIC_FLOOR_KEY);
mitigationKey = (String) row.get(MITIGATION_KEY);
amsDvsnInfos = new ArrayList<AMSDvsnInfo>();
configProps = (Properties) row.get(CONFIG_PROPS);
trafficDiverted = (Boolean) row.get(TRAFFIC_DIVERTED);
Iterator<Map.Entry<String,Object>> iter = row.entrySet().iterator();
Map.Entry<String,Object> entry; String amsDvsnInfoStr; AMSDvsnInfo amsDvsnInfo;
while(iter.hasNext()) {
entry = iter.next();
if(!entry.getKey().startsWith(DvsnInfo.AMS_DIVERSION_INFO_PREFIX)) continue;
amsDvsnInfoStr = (String)entry.getValue();
if(amsDvsnInfoStr == null) {
log.error("AMS diversion info cell " + entry.getKey() + " in NetNodeDiversionInfo " + amsDvsnInfoStr + " has null value.");
FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
continue;
}
amsDvsnInfo = new AMSDvsnInfo(amsDvsnInfoStr);
amsDvsnInfos.add(amsDvsnInfo);
}
if(amsDvsnInfos.isEmpty()) amsDvsnInfos = null;
} catch (Throwable e) {
log.error("Failed to inflate NetNodeDvsnInfo from row " + key + ".", e);
throw new IllegalArgumentException("Failed to inflate NetNodeDvsnInfo from row " + key + ".", e);
}
}
public Hashtable<String, Object> toRow() {
/* Change any null value to empty, otherwise Hashtable.put() will throw an exception */
if(key == null) key = "";
if(netNodeLabel == null) netNodeLabel = "";
if(tFloorKey == null) tFloorKey = "";
if(mitigationKey == null ) mitigationKey = "";
if(configProps == null ) configProps = new Properties();
Hashtable<String, Object> row = new Hashtable<String, Object>();
row.put(KEY, key);
row.put(NETNODE_LABEL, netNodeLabel);
row.put(TRAFFIC_FLOOR_KEY, tFloorKey);
row.put(MITIGATION_KEY, mitigationKey);
row.put(CONFIG_PROPS, configProps);
row.put(TRAFFIC_DIVERTED, trafficDiverted);
if(amsDvsnInfos != null) {
for(AMSDvsnInfo amsDvsnInfo : amsDvsnInfos) {
String amsDvsnInfoStr = amsDvsnInfo.toString();
//row.put(AMS_DIVERSION_INFO_PREFIX+amsDvsnInfo.label, amsDvsnInfo.toString());
row.put(AMS_DIVERSION_INFO_PREFIX+amsDvsnInfo.label, amsDvsnInfoStr);
}
}
return row;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Diversion Info [netNodeLabel="); sb.append(netNodeLabel);
sb.append(", mitigationKey="); sb.append(mitigationKey);
sb.append(", configProperties="); sb.append(configProps.toString());
for(AMSDvsnInfo amsDvsnInfo : amsDvsnInfos) {
sb.append(", ams diversion info ["); sb.append(amsDvsnInfo.toString()); sb.append("]");
}
return sb.toString();
}
public static List<RepoCD> getRCDs() {
if(repoCDs == null) {
RepoCD rcd;
repoCDs = new ArrayList<RepoCD>();
rcd = new RepoCD(KEY, StringSerializer.get(), null); repoCDs.add(rcd);
rcd = new RepoCD(NETNODE_LABEL, StringSerializer.get(), null); repoCDs.add(rcd);
rcd = new RepoCD(TRAFFIC_FLOOR_KEY, StringSerializer.get(), null); repoCDs.add(rcd);
rcd = new RepoCD(MITIGATION_KEY, StringSerializer.get(), null); repoCDs.add(rcd);
rcd = new RepoCD(CONFIG_PROPS, PropertiesSerializer.get(), null); repoCDs.add(rcd);
rcd = new RepoCD(TRAFFIC_DIVERTED, BooleanSerializer.get(), null); repoCDs.add(rcd);
}
return repoCDs;
}
public static DvsnInfo getDvsnInfo(String dvsnInfoKey) {
try {
Hashtable<String, Object> dvsnInfoRow = DFHolder.get().dvsnInfosRepo.getRow(dvsnInfoKey);
if(dvsnInfoRow == null) {
log.error("Got null dvsnInfoRow for key " + dvsnInfoKey);
return null;
}
DvsnInfo dvsnInfo = new DvsnInfo(dvsnInfoRow);
return dvsnInfo;
} catch (Throwable e) {
log.error("Failed to get DvsInfo : "+dvsnInfoKey, e);
FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
return null;
}
}
public static DvsnInfo getDvsnInfo(String netNodeLabel, String amsLabel) {
try {
Hashtable<String,Hashtable<String, Object>> dvsnInfoTable = DFHolder.get().dvsnInfosRepo.getTable();
Iterator<Map.Entry<String, Hashtable<String, Object>>> dvsnInfoIter = dvsnInfoTable.entrySet().iterator();
Hashtable<String, Object> dvsnInfoRow; DvsnInfo dvsnInfo = null; String currentNetNodeLabel;
while(dvsnInfoIter.hasNext()) {
dvsnInfoRow = dvsnInfoIter.next().getValue();
if(dvsnInfoRow == null) continue;
currentNetNodeLabel = (String) dvsnInfoRow.get(DvsnInfo.NETNODE_LABEL);
if(currentNetNodeLabel.equals(netNodeLabel)) {
dvsnInfo = new DvsnInfo(dvsnInfoRow);
break;
}
}
return dvsnInfo;
} catch (Throwable e) {
String msg = "Failed to retrieve AMS diversion information " + amsLabel;
log.error(msg, e);
FMHolder.get().getFR().logRecord(DFAppRoot.FR_DF_FAILURE, msg);
FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
return null;
}
}
public boolean containsDvsnToAMSs(List<String> failedAMSs) {
for(AMSDvsnInfo amsDvsnInfo : amsDvsnInfos) {
if(failedAMSs.contains(amsDvsnInfo.label))
return true;
}
return false;
}
}