blob: 764c93f5bc64bda7bc820834b2b031af7d1fd698 [file] [log] [blame]
Pavlin Radoslavov13669052014-05-13 10:33:39 -07001package net.onrc.onos.core.intent.runtime.web;
2
Pavlin Radoslavovc097fdf2014-05-23 17:40:57 -07003import java.io.IOException;
4import java.util.Collection;
5
Pavlin Radoslavov13669052014-05-13 10:33:39 -07006import net.floodlightcontroller.util.MACAddress;
7import net.onrc.onos.api.intent.ApplicationIntent;
Ray Milkeya8091b12014-05-16 14:42:47 -07008import net.onrc.onos.api.rest.RestError;
9import net.onrc.onos.api.rest.RestErrorCodes;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070010import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
11import net.onrc.onos.core.intent.Intent;
12import net.onrc.onos.core.intent.IntentMap;
13import net.onrc.onos.core.intent.IntentOperation;
14import net.onrc.onos.core.intent.IntentOperationList;
15import net.onrc.onos.core.intent.ShortestPathIntent;
16import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
17import net.onrc.onos.core.util.Dpid;
Pavlin Radoslavovc097fdf2014-05-23 17:40:57 -070018
Pavlin Radoslavov13669052014-05-13 10:33:39 -070019import org.codehaus.jackson.map.ObjectMapper;
Ray Milkeya8091b12014-05-16 14:42:47 -070020import org.restlet.data.Status;
Ray Milkey3aeda4f2014-05-21 14:38:58 -070021import org.restlet.representation.Representation;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070022import org.restlet.resource.Delete;
23import org.restlet.resource.Get;
24import org.restlet.resource.Post;
25import org.restlet.resource.ServerResource;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29/**
30 * A class to access the high-level intents.
31 */
32public class IntentHighResource extends ServerResource {
33 private static final Logger log = LoggerFactory.getLogger(IntentHighResource.class);
34 // TODO need to assign proper application id.
35 private static final String APPLN_ID = "1";
36
37 /**
38 * Gets all high-level intents.
39 *
Ray Milkey3aeda4f2014-05-21 14:38:58 -070040 * @return a Representation for a collection with all of the high-level intents.
Pavlin Radoslavov13669052014-05-13 10:33:39 -070041 */
42 @Get("json")
Ray Milkey3aeda4f2014-05-21 14:38:58 -070043 public Representation retrieve() throws IOException {
Pavlin Radoslavovc097fdf2014-05-23 17:40:57 -070044 IPathCalcRuntimeService pathRuntime =
45 (IPathCalcRuntimeService) getContext().getAttributes()
46 .get(IPathCalcRuntimeService.class.getCanonicalName());
Pavlin Radoslavov13669052014-05-13 10:33:39 -070047
48 IntentMap intentMap = pathRuntime.getHighLevelIntents();
49 Collection<Intent> intents = intentMap.getAllIntents();
50
Ray Milkey3aeda4f2014-05-21 14:38:58 -070051 return toRepresentation(intents, null);
Pavlin Radoslavov13669052014-05-13 10:33:39 -070052 }
53
54 /**
55 * Adds a collection of high-level intents.
56 *
Ray Milkey3aeda4f2014-05-21 14:38:58 -070057 * @param jsonIntent JSON representation of the intents to add.
58 * @return a Representation of a collection containing the intents that were
59 * created.
Pavlin Radoslavov13669052014-05-13 10:33:39 -070060 */
61 @Post("json")
Ray Milkey3aeda4f2014-05-21 14:38:58 -070062 public Representation store(String jsonIntent) {
Pavlin Radoslavovc097fdf2014-05-23 17:40:57 -070063 IPathCalcRuntimeService pathRuntime =
64 (IPathCalcRuntimeService) getContext().getAttributes()
65 .get(IPathCalcRuntimeService.class.getCanonicalName());
Pavlin Radoslavov13669052014-05-13 10:33:39 -070066 if (pathRuntime == null) {
67 log.warn("Failed to get path calc runtime");
Ray Milkey3aeda4f2014-05-21 14:38:58 -070068 return null;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070069 }
70
Pavlin Radoslavov13669052014-05-13 10:33:39 -070071 ObjectMapper mapper = new ObjectMapper();
72 ApplicationIntent[] addOperations = null;
73 try {
Ray Milkeya8091b12014-05-16 14:42:47 -070074 if (jsonIntent != null) {
75 addOperations = mapper.readValue(jsonIntent, ApplicationIntent[].class);
76 }
Pavlin Radoslavov13669052014-05-13 10:33:39 -070077 } catch (IOException ex) {
Ray Milkeya8091b12014-05-16 14:42:47 -070078 log.error("Exception occurred parsing inbound JSON", ex);
Pavlin Radoslavov13669052014-05-13 10:33:39 -070079 }
Ray Milkeya8091b12014-05-16 14:42:47 -070080
Pavlin Radoslavov13669052014-05-13 10:33:39 -070081 if (addOperations == null) {
Ray Milkeya8091b12014-05-16 14:42:47 -070082 setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
83 final RestError error =
84 RestError.createRestError(RestErrorCodes.RestErrorCode.INTENT_INVALID);
Ray Milkey3aeda4f2014-05-21 14:38:58 -070085 return toRepresentation(error, null);
Pavlin Radoslavov13669052014-05-13 10:33:39 -070086 }
87
88 //
89 // Process all intents one-by-one
90 //
91 // TODO: The Intent Type should be enum instead of a string,
92 // and we should use a switch statement below to process the
93 // different type of intents.
94 //
95 IntentOperationList intentOperations = new IntentOperationList();
96 for (ApplicationIntent oper : addOperations) {
97 String applnIntentId = APPLN_ID + ":" + oper.intentId();
98
99 IntentOperation.Operator operator = IntentOperation.Operator.ADD;
100 Dpid srcSwitchDpid = new Dpid(oper.srcSwitchDpid());
101 Dpid dstSwitchDpid = new Dpid(oper.dstSwitchDpid());
102
103 if (oper.intentType().equals("SHORTEST_PATH")) {
104 //
105 // Process Shortest-Path Intent
106 //
107 ShortestPathIntent spi =
108 new ShortestPathIntent(applnIntentId,
109 srcSwitchDpid.value(),
110 oper.srcSwitchPort(),
111 MACAddress.valueOf(oper.matchSrcMac()).toLong(),
112 dstSwitchDpid.value(),
113 oper.dstSwitchPort(),
114 MACAddress.valueOf(oper.matchDstMac()).toLong());
115 spi.setPathFrozen(oper.isStaticPath());
116 intentOperations.add(operator, spi);
117 } else {
118 //
119 // Process Constrained Shortest-Path Intent
120 //
121 ConstrainedShortestPathIntent cspi =
122 new ConstrainedShortestPathIntent(applnIntentId,
123 srcSwitchDpid.value(),
124 oper.srcSwitchPort(),
125 MACAddress.valueOf(oper.matchSrcMac()).toLong(),
126 dstSwitchDpid.value(),
127 oper.dstSwitchPort(),
128 MACAddress.valueOf(oper.matchDstMac()).toLong(),
129 oper.bandwidth());
130 cspi.setPathFrozen(oper.isStaticPath());
131 intentOperations.add(operator, cspi);
132 }
133 }
134 // Apply the Intent Operations
135 pathRuntime.executeIntentOperations(intentOperations);
136
Ray Milkeya8091b12014-05-16 14:42:47 -0700137 setStatus(Status.SUCCESS_CREATED);
138
Ray Milkey3aeda4f2014-05-21 14:38:58 -0700139 return toRepresentation(intentOperations, null);
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700140 }
141
142 /**
143 * Deletes all high-level intents.
144 *
Ray Milkey3aeda4f2014-05-21 14:38:58 -0700145 * @return a null Representation.
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700146 */
147 @Delete("json")
Ray Milkey3aeda4f2014-05-21 14:38:58 -0700148 public Representation remove() {
Pavlin Radoslavovc097fdf2014-05-23 17:40:57 -0700149 IPathCalcRuntimeService pathRuntime =
150 (IPathCalcRuntimeService) getContext().getAttributes()
151 .get(IPathCalcRuntimeService.class.getCanonicalName());
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700152
153 // Delete all intents
154 // TODO: The implementation below is broken - waiting for the Java API
155 // TODO: The deletion should use synchronous Java API?
156 pathRuntime.purgeIntents();
Ray Milkeya8091b12014-05-16 14:42:47 -0700157 setStatus(Status.SUCCESS_NO_CONTENT);
Ray Milkey3aeda4f2014-05-21 14:38:58 -0700158 return null; // TODO no reply yet from the purge intents call
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700159 }
160}