blob: 3787113dd9c41efde28af4286705c2c795032191 [file] [log] [blame]
Thomas Vachuska02aeb032015-01-06 22:36:30 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska02aeb032015-01-06 22:36:30 -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;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080017
alshabib20a070b2016-06-03 14:44:05 -070018import com.fasterxml.jackson.databind.node.ObjectNode;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080019import org.onosproject.app.ApplicationAdminService;
Ray Milkey16570322018-04-17 10:26:54 -070020import org.onosproject.app.ApplicationException;
Charles Chan416ef142020-08-10 16:34:32 -070021import org.onosproject.cluster.ComponentsMonitorService;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080022import org.onosproject.core.Application;
23import org.onosproject.core.ApplicationId;
Jian Lie1c1c8d2016-05-09 16:24:40 -070024import org.onosproject.core.CoreService;
Jonathan Hart9bb32ab2015-05-05 18:17:31 -070025import org.onosproject.rest.AbstractWebResource;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080026
27import javax.ws.rs.Consumes;
28import javax.ws.rs.DELETE;
Thomas Vachuska62ad95f2015-02-18 12:11:36 -080029import javax.ws.rs.DefaultValue;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080030import javax.ws.rs.GET;
31import javax.ws.rs.POST;
32import javax.ws.rs.Path;
33import javax.ws.rs.PathParam;
34import javax.ws.rs.Produces;
Thomas Vachuska62ad95f2015-02-18 12:11:36 -080035import javax.ws.rs.QueryParam;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080036import javax.ws.rs.core.MediaType;
37import javax.ws.rs.core.Response;
alshabib20a070b2016-06-03 14:44:05 -070038import java.io.IOException;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080039import java.io.InputStream;
alshabib20a070b2016-06-03 14:44:05 -070040import java.net.URL;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080041import java.util.Set;
Andrea Campanella8f6594c2021-10-25 12:33:01 +020042import org.slf4j.Logger;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080043
Andrea Campanella8f6594c2021-10-25 12:33:01 +020044import static org.slf4j.LoggerFactory.getLogger;
Jian Licbf49892016-05-10 14:54:44 -070045import static org.onlab.util.Tools.nullIsNotFound;
Ray Milkey86ee5e82018-04-02 15:33:07 -070046import static org.onlab.util.Tools.readTreeFromStream;
Jian Licbf49892016-05-10 14:54:44 -070047
Thomas Vachuska02aeb032015-01-06 22:36:30 -080048/**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070049 * Manage inventory of applications.
Thomas Vachuska02aeb032015-01-06 22:36:30 -080050 */
51@Path("applications")
52public class ApplicationsWebResource extends AbstractWebResource {
53
Andrea Campanella8f6594c2021-10-25 12:33:01 +020054 private static final Logger log = getLogger(ApplicationsWebResource.class);
55
56
Jian Licbf49892016-05-10 14:54:44 -070057 private static final String APP_ID_NOT_FOUND = "Application ID is not found";
58 private static final String APP_NOT_FOUND = "Application is not found";
Charles Chan416ef142020-08-10 16:34:32 -070059 private static final String APP_READY = "ready";
60 private static final String APP_PENDING = "pending";
Jian Licbf49892016-05-10 14:54:44 -070061
alshabib20a070b2016-06-03 14:44:05 -070062 private static final String URL = "url";
63 private static final String ACTIVATE = "activate";
64
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070065 /**
66 * Get all installed applications.
67 * Returns array of all installed applications.
68 *
69 * @return 200 OK
Jian Lie1c1c8d2016-05-09 16:24:40 -070070 * @onos.rsModel Applications
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070071 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -080072 @GET
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070073 public Response getApps() {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080074 ApplicationAdminService service = get(ApplicationAdminService.class);
75 Set<Application> apps = service.getApplications();
76 return ok(encodeArray(Application.class, "applications", apps)).build();
77 }
78
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070079 /**
80 * Get application details.
81 * Returns details of the specified application.
Jian Lie1c1c8d2016-05-09 16:24:40 -070082 *
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070083 * @param name application name
84 * @return 200 OK; 404; 401
Jian Lie1c1c8d2016-05-09 16:24:40 -070085 * @onos.rsModel Application
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070086 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -080087 @GET
88 @Path("{name}")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070089 public Response getApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080090 ApplicationAdminService service = get(ApplicationAdminService.class);
Andrea Campanella8f6594c2021-10-25 12:33:01 +020091 ApplicationId appId = nullIsNotFound(service.getId(name), APP_NOT_FOUND + ":" + name);
Thomas Vachuska02aeb032015-01-06 22:36:30 -080092 return response(service, appId);
93 }
94
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070095 /**
Charles Chan416ef142020-08-10 16:34:32 -070096 * Get application health.
97 *
98 * @param name application name
99 * @return 200 OK with app health in the body; 404 if app is not found
100 */
101 @GET
102 @Path("{name}/health")
103 public Response health(@PathParam("name") String name) {
104 ApplicationAdminService service = get(ApplicationAdminService.class);
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200105 ApplicationId appId = service.getId(name);
106 nullIsNotFound(appId, APP_ID_NOT_FOUND + ": " + name);
107
108 Application app = service.getApplication(appId);
109 nullIsNotFound(app, APP_NOT_FOUND + ": " + appId);
Charles Chan416ef142020-08-10 16:34:32 -0700110
111 ComponentsMonitorService componentsMonitorService = get(ComponentsMonitorService.class);
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200112 boolean ready = componentsMonitorService.isFullyStarted(app.features());
Charles Chan416ef142020-08-10 16:34:32 -0700113 return Response.ok(mapper().createObjectNode().put("message", ready ? APP_READY : APP_PENDING)).build();
114 }
115
116 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700117 * Install a new application.
118 * Uploads application archive stream and optionally activates the
119 * application.
alshabib20a070b2016-06-03 14:44:05 -0700120
121 * @param raw json object containing location (url) of application oar
122 * @return 200 OK; 404; 401
123 */
124 @POST
125 @Consumes(MediaType.APPLICATION_JSON)
126 @Produces(MediaType.APPLICATION_JSON)
127 public Response installApp(InputStream raw) {
128 Application app;
129 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700130 ObjectNode jsonTree = readTreeFromStream(mapper(), raw);
alshabib20a070b2016-06-03 14:44:05 -0700131 URL url = new URL(jsonTree.get(URL).asText());
132 boolean activate = false;
133 if (jsonTree.has(ACTIVATE)) {
134 activate = jsonTree.get(ACTIVATE).asBoolean();
135 }
136
137 ApplicationAdminService service = get(ApplicationAdminService.class);
138 app = service.install(url.openStream());
139 if (activate) {
140 service.activate(app.id());
141 }
142 } catch (IOException ex) {
143 throw new IllegalArgumentException(ex);
144 }
145 return ok(codec(Application.class).encode(app, this)).build();
146 }
147
148 /**
149 * Install a new application.
150 * Uploads application archive stream and optionally activates the
151 * application.
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700152 *
153 * @param activate true to activate app also
154 * @param stream application archive stream
155 * @return 200 OK; 404; 401
156 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800157 @POST
158 @Consumes(MediaType.APPLICATION_OCTET_STREAM)
159 @Produces(MediaType.APPLICATION_JSON)
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700160 public Response installApp(@QueryParam("activate")
161 @DefaultValue("false") boolean activate,
162 InputStream stream) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800163 ApplicationAdminService service = get(ApplicationAdminService.class);
Ray Milkey16570322018-04-17 10:26:54 -0700164 try {
165 Application app = service.install(stream);
166 if (activate) {
167 service.activate(app.id());
168 }
169 return ok(codec(Application.class).encode(app, this)).build();
170 } catch (ApplicationException appEx) {
171 throw new IllegalArgumentException(appEx);
Thomas Vachuska62ad95f2015-02-18 12:11:36 -0800172 }
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800173 }
174
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700175 /**
176 * Uninstall application.
177 * Uninstalls the specified application deactivating it first if necessary.
178 *
179 * @param name application name
Jian Lic2a542b2016-05-10 11:48:19 -0700180 * @return 204 NO CONTENT
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700181 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800182 @DELETE
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800183 @Path("{name}")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700184 public Response uninstallApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800185 ApplicationAdminService service = get(ApplicationAdminService.class);
186 ApplicationId appId = service.getId(name);
dvaddiree113b652017-08-04 14:58:06 +0530187 if (appId != null) {
188 service.uninstall(appId);
189 }
Jian Lic2a542b2016-05-10 11:48:19 -0700190 return Response.noContent().build();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800191 }
192
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700193 /**
194 * Activate application.
195 * Activates the specified application.
196 *
197 * @param name application name
198 * @return 200 OK; 404; 401
199 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800200 @POST
201 @Produces(MediaType.APPLICATION_JSON)
202 @Path("{name}/active")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700203 public Response activateApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800204 ApplicationAdminService service = get(ApplicationAdminService.class);
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200205 ApplicationId appId = nullIsNotFound(service.getId(name), APP_NOT_FOUND + ": " + name);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800206 service.activate(appId);
207 return response(service, appId);
208 }
209
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700210 /**
211 * De-activate application.
212 * De-activates the specified application.
213 *
214 * @param name application name
dvaddiree113b652017-08-04 14:58:06 +0530215 * @return 204 NO CONTENT
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700216 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800217 @DELETE
218 @Produces(MediaType.APPLICATION_JSON)
219 @Path("{name}/active")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700220 public Response deactivateApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800221 ApplicationAdminService service = get(ApplicationAdminService.class);
222 ApplicationId appId = service.getId(name);
dvaddiree113b652017-08-04 14:58:06 +0530223 if (appId != null) {
224 service.deactivate(appId);
225 }
226 return Response.noContent().build();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800227 }
228
Jian Lie1c1c8d2016-05-09 16:24:40 -0700229 /**
230 * Registers an on or off platform application.
231 *
232 * @param name application name
233 * @return 200 OK; 404; 401
234 * @onos.rsModel ApplicationId
235 */
236 @POST
237 @Produces(MediaType.APPLICATION_JSON)
238 @Path("{name}/register")
239 public Response registerAppId(@PathParam("name") String name) {
240 CoreService service = get(CoreService.class);
241 ApplicationId appId = service.registerApplication(name);
242 return response(appId);
243 }
244
245 /**
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700246 * Get application OAR/JAR file.
247 * Returns the OAR/JAR file used to install the specified application.
248 *
249 * @param name application name
250 * @return 200 OK; 404; 401
251 */
252 @GET
253 @Produces(MediaType.APPLICATION_OCTET_STREAM)
254 @Path("{name}/bits")
255 public Response getAppBits(@PathParam("name") String name) {
256 ApplicationAdminService service = get(ApplicationAdminService.class);
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200257 ApplicationId appId = nullIsNotFound(service.getId(name), APP_ID_NOT_FOUND + ": " + name);
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700258 InputStream bits = service.getApplicationArchive(appId);
259 return ok(bits).build();
260 }
261
262 /**
Jian Li847242b2016-05-11 18:58:53 -0700263 * Gets applicationId entry by either id or name.
Jian Lie1c1c8d2016-05-09 16:24:40 -0700264 *
Jian Li847242b2016-05-11 18:58:53 -0700265 * @param id id of application
Jian Lie1c1c8d2016-05-09 16:24:40 -0700266 * @param name name of application
267 * @return 200 OK; 404; 401
268 * @onos.rsModel ApplicationId
269 */
270 @GET
271 @Produces(MediaType.APPLICATION_JSON)
Jian Li847242b2016-05-11 18:58:53 -0700272 @Path("ids/entry")
Jian Lia3e4c7a2016-05-12 13:15:40 -0700273 public Response getAppIdByName(@QueryParam("id") String id,
Jian Li847242b2016-05-11 18:58:53 -0700274 @QueryParam("name") String name) {
Jian Lie1c1c8d2016-05-09 16:24:40 -0700275 CoreService service = get(CoreService.class);
Jian Li847242b2016-05-11 18:58:53 -0700276 ApplicationId appId = null;
277 if (id != null) {
Jian Lia3e4c7a2016-05-12 13:15:40 -0700278 appId = service.getAppId(Short.valueOf(id));
Jian Li847242b2016-05-11 18:58:53 -0700279 } else if (name != null) {
280 appId = service.getAppId(name);
281 }
Jian Lie1c1c8d2016-05-09 16:24:40 -0700282 return response(appId);
283 }
284
285 /**
286 * Gets a collection of application ids.
287 * Returns array of all registered application ids.
288 *
289 * @return 200 OK; 404; 401
290 * @onos.rsModel ApplicationIds
291 */
292 @GET
293 @Produces(MediaType.APPLICATION_JSON)
294 @Path("ids")
295 public Response getAppIds() {
296 CoreService service = get(CoreService.class);
297 Set<ApplicationId> appIds = service.getAppIds();
298 return ok(encodeArray(ApplicationId.class, "applicationIds", appIds)).build();
299 }
300
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800301 private Response response(ApplicationAdminService service, ApplicationId appId) {
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200302 Application app = nullIsNotFound(service.getApplication(appId),
303 APP_NOT_FOUND + ": " + appId);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800304 return ok(codec(Application.class).encode(app, this)).build();
305 }
306
Jian Lie1c1c8d2016-05-09 16:24:40 -0700307 private Response response(ApplicationId appId) {
Andrea Campanella8f6594c2021-10-25 12:33:01 +0200308 ApplicationId checkedAppId = nullIsNotFound(appId, APP_ID_NOT_FOUND + ": " + appId);
Jian Licbf49892016-05-10 14:54:44 -0700309 return ok(codec(ApplicationId.class).encode(checkedAppId, this)).build();
Jian Lie1c1c8d2016-05-09 16:24:40 -0700310 }
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800311}