blob: f49e6be1e0aa4d312c8387bfd27a1f97e331d4e2 [file] [log] [blame]
Ray Milkey2b217142014-12-15 09:24:24 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Ray Milkey2b217142014-12-15 09:24:24 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jonathan Hart9bb32ab2015-05-05 18:17:31 -070016package org.onosproject.rest.resources;
Ray Milkey2b217142014-12-15 09:24:24 -080017
Ray Milkey67c22722015-03-09 15:48:57 -070018import java.util.Objects;
19import java.util.concurrent.CountDownLatch;
20import java.util.concurrent.TimeUnit;
21
22import javax.ws.rs.DELETE;
Ray Milkey2b217142014-12-15 09:24:24 -080023import javax.ws.rs.GET;
24import javax.ws.rs.Path;
25import javax.ws.rs.PathParam;
26import javax.ws.rs.Produces;
27import javax.ws.rs.core.MediaType;
28import javax.ws.rs.core.Response;
29
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
Ray Milkeyc95bb9d2015-01-06 10:28:24 -080032import org.onosproject.net.intent.HostToHostIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080033import org.onosproject.net.intent.Intent;
Ray Milkey67c22722015-03-09 15:48:57 -070034import org.onosproject.net.intent.IntentEvent;
35import org.onosproject.net.intent.IntentListener;
Ray Milkey2b217142014-12-15 09:24:24 -080036import org.onosproject.net.intent.IntentService;
Ray Milkey67c22722015-03-09 15:48:57 -070037import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080038import org.onosproject.net.intent.Key;
Ray Milkeyc95bb9d2015-01-06 10:28:24 -080039import org.onosproject.net.intent.PointToPointIntent;
Jonathan Hart9bb32ab2015-05-05 18:17:31 -070040import org.onosproject.rest.AbstractWebResource;
Ray Milkey67c22722015-03-09 15:48:57 -070041import org.slf4j.Logger;
Ray Milkey2b217142014-12-15 09:24:24 -080042
43import com.fasterxml.jackson.databind.node.ObjectNode;
44
Thomas Vachuskaf8cac482015-04-08 19:40:12 -070045import static org.onlab.util.Tools.nullIsNotFound;
Ray Milkey67c22722015-03-09 15:48:57 -070046import static org.onosproject.net.intent.IntentState.FAILED;
47import static org.onosproject.net.intent.IntentState.WITHDRAWN;
48import static org.slf4j.LoggerFactory.getLogger;
49
Ray Milkey2b217142014-12-15 09:24:24 -080050/**
51 * REST resource for interacting with the inventory of intents.
52 */
53
54@Path("intents")
55public class IntentsWebResource extends AbstractWebResource {
Ray Milkey67c22722015-03-09 15:48:57 -070056 private static final Logger log = getLogger(IntentsWebResource.class);
57 private static final int WITHDRAW_EVENT_TIMEOUT_SECONDS = 5;
58
Ray Milkey2b217142014-12-15 09:24:24 -080059 public static final String INTENT_NOT_FOUND = "Intent is not found";
60
61 /**
62 * Gets an array containing all the intents in the system.
63 *
64 * @return array of all the intents in the system
65 */
66 @GET
67 @Produces(MediaType.APPLICATION_JSON)
68 public Response getIntents() {
69 final Iterable<Intent> intents = get(IntentService.class).getIntents();
70 final ObjectNode root = encodeArray(Intent.class, "intents", intents);
Ray Milkey3f025692015-01-26 11:15:41 -080071 return ok(root).build();
Ray Milkey2b217142014-12-15 09:24:24 -080072 }
73
74 /**
75 * Gets a single intent by Id.
76 *
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080077 * @param appId the Application ID
78 * @param key the Intent key value to look up
Ray Milkey2b217142014-12-15 09:24:24 -080079 * @return intent data
80 */
81 @GET
82 @Produces(MediaType.APPLICATION_JSON)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080083 @Path("{appId}/{key}")
84 public Response getIntentById(@PathParam("appId") Short appId,
85 @PathParam("key") String key) {
86 final ApplicationId app = get(CoreService.class).getAppId(appId);
87
88 Intent intent = get(IntentService.class).getIntent(Key.of(key, app));
89 if (intent == null) {
90 intent = get(IntentService.class)
Yuta HIGUCHI179f3772015-02-18 17:28:39 +090091 .getIntent(Key.of(Long.parseLong(key), app));
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080092 }
93 nullIsNotFound(intent, INTENT_NOT_FOUND);
94
Ray Milkeyc95bb9d2015-01-06 10:28:24 -080095 final ObjectNode root;
96 if (intent instanceof HostToHostIntent) {
97 root = codec(HostToHostIntent.class).encode((HostToHostIntent) intent, this);
98 } else if (intent instanceof PointToPointIntent) {
99 root = codec(PointToPointIntent.class).encode((PointToPointIntent) intent, this);
100 } else {
101 root = codec(Intent.class).encode(intent, this);
102 }
Ray Milkey3f025692015-01-26 11:15:41 -0800103 return ok(root).build();
Ray Milkey2b217142014-12-15 09:24:24 -0800104 }
Ray Milkey67c22722015-03-09 15:48:57 -0700105
106 class DeleteListener implements IntentListener {
107 final Key key;
108 final CountDownLatch latch;
109
110 DeleteListener(Key key, CountDownLatch latch) {
111 this.key = key;
112 this.latch = latch;
113 }
114
115 @Override
116 public void event(IntentEvent event) {
117 if (Objects.equals(event.subject().key(), key) &&
118 (event.type() == IntentEvent.Type.WITHDRAWN ||
119 event.type() == IntentEvent.Type.FAILED)) {
120 latch.countDown();
121 }
122 }
123 }
124
125 /**
126 * Uninstalls a single intent by Id.
127 *
128 * @param appId the Application ID
129 * @param keyString the Intent key value to look up
130 */
131 @DELETE
132 @Path("{appId}/{key}")
133 public void deleteIntentById(@PathParam("appId") Short appId,
134 @PathParam("key") String keyString) {
135 final ApplicationId app = get(CoreService.class).getAppId(appId);
136
137 Intent intent = get(IntentService.class).getIntent(Key.of(keyString, app));
138 IntentService service = get(IntentService.class);
139
140 if (intent == null) {
141 intent = service
142 .getIntent(Key.of(Long.parseLong(keyString), app));
143 }
144 if (intent == null) {
145 // No such intent. REST standards recommend a positive status code
146 // in this case.
147 return;
148 }
149
150
151 Key key = intent.key();
152
153 // set up latch and listener to track uninstall progress
154 CountDownLatch latch = new CountDownLatch(1);
155
156 IntentListener listener = new DeleteListener(key, latch);
157 service.addListener(listener);
158
159 try {
160 // request the withdraw
161 service.withdraw(intent);
162
163 try {
164 latch.await(WITHDRAW_EVENT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
165 } catch (InterruptedException e) {
166 log.info("REST Delete operation timed out waiting for intent {}", key);
167 }
168 // double check the state
169 IntentState state = service.getIntentState(key);
170 if (state == WITHDRAWN || state == FAILED) {
171 service.purge(intent);
172 }
173
174 } finally {
175 // clean up the listener
176 service.removeListener(listener);
177 }
178 }
179
Ray Milkey2b217142014-12-15 09:24:24 -0800180}