Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 1 | package net.onrc.onos.core.intent.runtime.web; |
| 2 | |
Pavlin Radoslavov | c097fdf | 2014-05-23 17:40:57 -0700 | [diff] [blame^] | 3 | import java.io.IOException; |
| 4 | import java.util.Collection; |
| 5 | |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 6 | import net.floodlightcontroller.util.MACAddress; |
| 7 | import net.onrc.onos.api.intent.ApplicationIntent; |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 8 | import net.onrc.onos.api.rest.RestError; |
| 9 | import net.onrc.onos.api.rest.RestErrorCodes; |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 10 | import net.onrc.onos.core.intent.ConstrainedShortestPathIntent; |
| 11 | import net.onrc.onos.core.intent.Intent; |
| 12 | import net.onrc.onos.core.intent.IntentMap; |
| 13 | import net.onrc.onos.core.intent.IntentOperation; |
| 14 | import net.onrc.onos.core.intent.IntentOperationList; |
| 15 | import net.onrc.onos.core.intent.ShortestPathIntent; |
| 16 | import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService; |
| 17 | import net.onrc.onos.core.util.Dpid; |
Pavlin Radoslavov | c097fdf | 2014-05-23 17:40:57 -0700 | [diff] [blame^] | 18 | |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 19 | import org.codehaus.jackson.map.ObjectMapper; |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 20 | import org.restlet.data.Status; |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 21 | import org.restlet.representation.Representation; |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 22 | import org.restlet.resource.Delete; |
| 23 | import org.restlet.resource.Get; |
| 24 | import org.restlet.resource.Post; |
| 25 | import org.restlet.resource.ServerResource; |
| 26 | import org.slf4j.Logger; |
| 27 | import org.slf4j.LoggerFactory; |
| 28 | |
| 29 | /** |
| 30 | * A class to access the high-level intents. |
| 31 | */ |
| 32 | public 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 Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 40 | * @return a Representation for a collection with all of the high-level intents. |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 41 | */ |
| 42 | @Get("json") |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 43 | public Representation retrieve() throws IOException { |
Pavlin Radoslavov | c097fdf | 2014-05-23 17:40:57 -0700 | [diff] [blame^] | 44 | IPathCalcRuntimeService pathRuntime = |
| 45 | (IPathCalcRuntimeService) getContext().getAttributes() |
| 46 | .get(IPathCalcRuntimeService.class.getCanonicalName()); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 47 | |
| 48 | IntentMap intentMap = pathRuntime.getHighLevelIntents(); |
| 49 | Collection<Intent> intents = intentMap.getAllIntents(); |
| 50 | |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 51 | return toRepresentation(intents, null); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | /** |
| 55 | * Adds a collection of high-level intents. |
| 56 | * |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 57 | * @param jsonIntent JSON representation of the intents to add. |
| 58 | * @return a Representation of a collection containing the intents that were |
| 59 | * created. |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 60 | */ |
| 61 | @Post("json") |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 62 | public Representation store(String jsonIntent) { |
Pavlin Radoslavov | c097fdf | 2014-05-23 17:40:57 -0700 | [diff] [blame^] | 63 | IPathCalcRuntimeService pathRuntime = |
| 64 | (IPathCalcRuntimeService) getContext().getAttributes() |
| 65 | .get(IPathCalcRuntimeService.class.getCanonicalName()); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 66 | if (pathRuntime == null) { |
| 67 | log.warn("Failed to get path calc runtime"); |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 68 | return null; |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 69 | } |
| 70 | |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 71 | ObjectMapper mapper = new ObjectMapper(); |
| 72 | ApplicationIntent[] addOperations = null; |
| 73 | try { |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 74 | if (jsonIntent != null) { |
| 75 | addOperations = mapper.readValue(jsonIntent, ApplicationIntent[].class); |
| 76 | } |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 77 | } catch (IOException ex) { |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 78 | log.error("Exception occurred parsing inbound JSON", ex); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 79 | } |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 80 | |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 81 | if (addOperations == null) { |
Ray Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 82 | setStatus(Status.CLIENT_ERROR_BAD_REQUEST); |
| 83 | final RestError error = |
| 84 | RestError.createRestError(RestErrorCodes.RestErrorCode.INTENT_INVALID); |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 85 | return toRepresentation(error, null); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 86 | } |
| 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 Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 137 | setStatus(Status.SUCCESS_CREATED); |
| 138 | |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 139 | return toRepresentation(intentOperations, null); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Deletes all high-level intents. |
| 144 | * |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 145 | * @return a null Representation. |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 146 | */ |
| 147 | @Delete("json") |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 148 | public Representation remove() { |
Pavlin Radoslavov | c097fdf | 2014-05-23 17:40:57 -0700 | [diff] [blame^] | 149 | IPathCalcRuntimeService pathRuntime = |
| 150 | (IPathCalcRuntimeService) getContext().getAttributes() |
| 151 | .get(IPathCalcRuntimeService.class.getCanonicalName()); |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 152 | |
| 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 Milkey | a8091b1 | 2014-05-16 14:42:47 -0700 | [diff] [blame] | 157 | setStatus(Status.SUCCESS_NO_CONTENT); |
Ray Milkey | 3aeda4f | 2014-05-21 14:38:58 -0700 | [diff] [blame] | 158 | return null; // TODO no reply yet from the purge intents call |
Pavlin Radoslavov | 1366905 | 2014-05-13 10:33:39 -0700 | [diff] [blame] | 159 | } |
| 160 | } |