package net.floodlightcontroller.hand; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.map.MappingJsonFactory; import org.restlet.resource.Delete; import org.restlet.resource.Get; import org.restlet.resource.Post; import org.restlet.resource.ServerResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HANDRulesResource extends ServerResource { public static Logger logger = LoggerFactory.getLogger(HANDGangliaHostsResource.class); @Get("json") public Object handleRequest(){ IHANDService hand = (IHANDService)getContext().getAttributes(). get(IHANDService.class.getCanonicalName()); String status = null; if(hand.isHANDEnabled()){ return hand.getRules(); } else{ status = "Please enable Host Aware Networking Decisions"; return ("{\"status\" : \"" + status + "\"}"); } } /** * * @param ruleJson * @return */ @Post public String addRule(String ruleJson){ IHANDService hand = (IHANDService)getContext().getAttributes(). get(IHANDService.class.getCanonicalName()); HANDRule rule; String status = null; try{ rule = jsonToGangliaRule(ruleJson); } catch(IOException e){ logger.error("Error parsing rule to JSON: {}, Error: {}", ruleJson, e); e.printStackTrace(); return "{\"status\" : \"Error! Could not parse rule, see log for details.\"}"; } if(ruleExists(rule, hand.getRules())){ status = "Error!, This rule already exists!"; logger.error(status); } else{ if(hand.isHANDEnabled()){ /** * Add Code to handle checks * e.g * * is firewall rule, is the firewall enabled? * is a qos rule, is QoS enabled? * is the polling time good? make sense? * * *Host Assoc is check in json parse * *ActionType is checked in json parse * *Metrics are parsed in json parse * * * Then add the rule * * TODO !!!!!!************** */ } } return "{\"status\" : "+ status +"}"; } /** * * @param ruleJson * @return */ @Delete public String deleteRule(String ruleJson){ //TODO /** * * !!!!!!!!!!!!!!!!!!!! * * */ return null; } private static HANDRule jsonToGangliaRule(String ruleJson) throws IOException{ HANDRule rule = new HANDRule(); MappingJsonFactory jsonFactory = new MappingJsonFactory(); JsonParser parser; try{ parser = jsonFactory.createJsonParser(ruleJson); }catch(JsonParseException e){ throw new IOException (e); } JsonToken token = parser.getCurrentToken(); if(token != JsonToken.START_OBJECT){ parser.nextToken(); if(parser.getCurrentToken() != JsonToken.START_OBJECT){ logger.error("did not recieve json start token, current token is: {}" + parser.getCurrentToken()); } } //Start parsing while(parser.nextToken() != JsonToken.END_OBJECT){ if(parser.getCurrentToken() != JsonToken.FIELD_NAME){ throw new IOException("FIELD_NAME expected"); } try{ String name = parser.getCurrentName(); parser.nextToken(); //current text in parser String jsonText = parser.getText(); logger.info("JSON Parser text is: {}", jsonText); //DEBUG if(jsonText.equals("")){ //ignore empty string, return to loop continue; } else if(name == "rule_name"){ rule.name = jsonText; } else if(name == "priority"){ //TODO } else if(name == "polling_time"){ //TODO } else if(name == "active"){ //TODO } else if(name == "check_limit"){ //TODO } else if(name == "attached_to"){ //TODO given host X, get the ID from the list of //hosts known by HAND } else if(name == "metrics"){ //"metrics":{"<m1>":"<threshold>"}....(list assumes "and" ) //TODO store key value pars in a json string. //Call parseMetrics //Return HashMap<String, HANDThreshold> //e.g a {"load_one":"gt-5"} should result in a // rule that tracks Load of 1 Min that triggers when it is >5 Load/Procs //Also, make sure ganglia can see this metric //TODO checkGangliaMetrics(HashMap<String, HANDThreshold> metrics) } else if(name == "action_type"){ //TODO /** Can be one of the following from * net.floodlightcontroller.hand.HandRule.java * RPRT, //Report threshold is reported AFR, //Add Firewall Rule DFW, //Delete Firewall Rule LB, //LoadBalance (placeholder for now //TODO ) PSF, //Push Static Flow AQOS, //Add QoS Rule DQOS, //Delete QoS Rule KR, //Kill Route */ //TODO call boolean checkActionType from HandRule // change the string to ALL CAPS. } else if(name == "action_string"){ //TODO /** * This is an odd one, depending on the * ActionType, we will need different information from * the actionString. I.E a Adding a Firewall Rule needs * specific info rather than Pushing a Static Flow */ //TODO Call parseActionString(rule.action, rule.actionString) //parsing the action string first looks at the ActionType, //depending on the ActionType, the functions will determine //what information it needs to call to the correct //controller API and checl the action_string if has given the //correct information via key:value pairs. rule.actionString = jsonText; } }catch(JsonParseException e){ logger.debug("Error getting current FIELD_NAME {}", e); }catch(IOException e){ logger.debug("Error procession Json {}", e); } } //Return the HANDGangliaHost Object to the GangliaHostResource return rule; } /** * * @param rule * @param ruleList * @return */ public static boolean ruleExists(HANDRule rule, ArrayList<HANDRule> ruleList){ Iterator<HANDRule> ruleIter = ruleList.iterator(); while(ruleIter.hasNext()){ HANDRule r = ruleIter.next(); if(rule.isSameAs(r) || rule.name == r.name || rule.equals(r)){ return true; } } return false; } }