blob: b2ee977ff8ded426700d5bd131c715f7cc757a7f [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 Chan5bdaf102020-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;
42
Jian Licbf49892016-05-10 14:54:44 -070043import static org.onlab.util.Tools.nullIsNotFound;
Ray Milkey86ee5e82018-04-02 15:33:07 -070044import static org.onlab.util.Tools.readTreeFromStream;
Jian Licbf49892016-05-10 14:54:44 -070045
Thomas Vachuska02aeb032015-01-06 22:36:30 -080046/**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070047 * Manage inventory of applications.
Thomas Vachuska02aeb032015-01-06 22:36:30 -080048 */
49@Path("applications")
50public class ApplicationsWebResource extends AbstractWebResource {
51
Jian Licbf49892016-05-10 14:54:44 -070052 private static final String APP_ID_NOT_FOUND = "Application ID is not found";
53 private static final String APP_NOT_FOUND = "Application is not found";
Charles Chan5bdaf102020-08-10 16:34:32 -070054 private static final String APP_READY = "ready";
55 private static final String APP_PENDING = "pending";
Jian Licbf49892016-05-10 14:54:44 -070056
alshabib20a070b2016-06-03 14:44:05 -070057 private static final String URL = "url";
58 private static final String ACTIVATE = "activate";
59
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070060 /**
61 * Get all installed applications.
62 * Returns array of all installed applications.
63 *
64 * @return 200 OK
Jian Lie1c1c8d2016-05-09 16:24:40 -070065 * @onos.rsModel Applications
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070066 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -080067 @GET
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070068 public Response getApps() {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080069 ApplicationAdminService service = get(ApplicationAdminService.class);
70 Set<Application> apps = service.getApplications();
71 return ok(encodeArray(Application.class, "applications", apps)).build();
72 }
73
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070074 /**
75 * Get application details.
76 * Returns details of the specified application.
Jian Lie1c1c8d2016-05-09 16:24:40 -070077 *
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070078 * @param name application name
79 * @return 200 OK; 404; 401
Jian Lie1c1c8d2016-05-09 16:24:40 -070080 * @onos.rsModel Application
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070081 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -080082 @GET
83 @Path("{name}")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070084 public Response getApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080085 ApplicationAdminService service = get(ApplicationAdminService.class);
Jayasree Ghoshe6213cf2016-09-28 07:55:55 +053086 ApplicationId appId = nullIsNotFound(service.getId(name), APP_NOT_FOUND);
Thomas Vachuska02aeb032015-01-06 22:36:30 -080087 return response(service, appId);
88 }
89
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070090 /**
Charles Chan5bdaf102020-08-10 16:34:32 -070091 * Get application health.
92 *
93 * @param name application name
94 * @return 200 OK with app health in the body; 404 if app is not found
95 */
96 @GET
97 @Path("{name}/health")
98 public Response health(@PathParam("name") String name) {
99 ApplicationAdminService service = get(ApplicationAdminService.class);
100 ApplicationId appId = nullIsNotFound(service.getId(name), APP_NOT_FOUND);
101
102 ComponentsMonitorService componentsMonitorService = get(ComponentsMonitorService.class);
103 boolean ready = componentsMonitorService.isFullyStarted(service.getApplication(appId).features());
104 return Response.ok(mapper().createObjectNode().put("message", ready ? APP_READY : APP_PENDING)).build();
105 }
106
107 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700108 * Install a new application.
109 * Uploads application archive stream and optionally activates the
110 * application.
alshabib20a070b2016-06-03 14:44:05 -0700111
112 * @param raw json object containing location (url) of application oar
113 * @return 200 OK; 404; 401
114 */
115 @POST
116 @Consumes(MediaType.APPLICATION_JSON)
117 @Produces(MediaType.APPLICATION_JSON)
118 public Response installApp(InputStream raw) {
119 Application app;
120 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700121 ObjectNode jsonTree = readTreeFromStream(mapper(), raw);
alshabib20a070b2016-06-03 14:44:05 -0700122 URL url = new URL(jsonTree.get(URL).asText());
123 boolean activate = false;
124 if (jsonTree.has(ACTIVATE)) {
125 activate = jsonTree.get(ACTIVATE).asBoolean();
126 }
127
128 ApplicationAdminService service = get(ApplicationAdminService.class);
129 app = service.install(url.openStream());
130 if (activate) {
131 service.activate(app.id());
132 }
133 } catch (IOException ex) {
134 throw new IllegalArgumentException(ex);
135 }
136 return ok(codec(Application.class).encode(app, this)).build();
137 }
138
139 /**
140 * Install a new application.
141 * Uploads application archive stream and optionally activates the
142 * application.
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700143 *
144 * @param activate true to activate app also
145 * @param stream application archive stream
146 * @return 200 OK; 404; 401
147 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800148 @POST
149 @Consumes(MediaType.APPLICATION_OCTET_STREAM)
150 @Produces(MediaType.APPLICATION_JSON)
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700151 public Response installApp(@QueryParam("activate")
152 @DefaultValue("false") boolean activate,
153 InputStream stream) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800154 ApplicationAdminService service = get(ApplicationAdminService.class);
Ray Milkey16570322018-04-17 10:26:54 -0700155 try {
156 Application app = service.install(stream);
157 if (activate) {
158 service.activate(app.id());
159 }
160 return ok(codec(Application.class).encode(app, this)).build();
161 } catch (ApplicationException appEx) {
162 throw new IllegalArgumentException(appEx);
Thomas Vachuska62ad95f2015-02-18 12:11:36 -0800163 }
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800164 }
165
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700166 /**
167 * Uninstall application.
168 * Uninstalls the specified application deactivating it first if necessary.
169 *
170 * @param name application name
Jian Lic2a542b2016-05-10 11:48:19 -0700171 * @return 204 NO CONTENT
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700172 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800173 @DELETE
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800174 @Path("{name}")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700175 public Response uninstallApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800176 ApplicationAdminService service = get(ApplicationAdminService.class);
177 ApplicationId appId = service.getId(name);
dvaddiree113b652017-08-04 14:58:06 +0530178 if (appId != null) {
179 service.uninstall(appId);
180 }
Jian Lic2a542b2016-05-10 11:48:19 -0700181 return Response.noContent().build();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800182 }
183
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700184 /**
185 * Activate application.
186 * Activates the specified application.
187 *
188 * @param name application name
189 * @return 200 OK; 404; 401
190 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800191 @POST
192 @Produces(MediaType.APPLICATION_JSON)
193 @Path("{name}/active")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700194 public Response activateApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800195 ApplicationAdminService service = get(ApplicationAdminService.class);
Hyunsun Moon14998642016-06-10 12:54:26 -0700196 ApplicationId appId = nullIsNotFound(service.getId(name), APP_NOT_FOUND);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800197 service.activate(appId);
198 return response(service, appId);
199 }
200
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700201 /**
202 * De-activate application.
203 * De-activates the specified application.
204 *
205 * @param name application name
dvaddiree113b652017-08-04 14:58:06 +0530206 * @return 204 NO CONTENT
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700207 */
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800208 @DELETE
209 @Produces(MediaType.APPLICATION_JSON)
210 @Path("{name}/active")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700211 public Response deactivateApp(@PathParam("name") String name) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800212 ApplicationAdminService service = get(ApplicationAdminService.class);
213 ApplicationId appId = service.getId(name);
dvaddiree113b652017-08-04 14:58:06 +0530214 if (appId != null) {
215 service.deactivate(appId);
216 }
217 return Response.noContent().build();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800218 }
219
Jian Lie1c1c8d2016-05-09 16:24:40 -0700220 /**
221 * Registers an on or off platform application.
222 *
223 * @param name application name
224 * @return 200 OK; 404; 401
225 * @onos.rsModel ApplicationId
226 */
227 @POST
228 @Produces(MediaType.APPLICATION_JSON)
229 @Path("{name}/register")
230 public Response registerAppId(@PathParam("name") String name) {
231 CoreService service = get(CoreService.class);
232 ApplicationId appId = service.registerApplication(name);
233 return response(appId);
234 }
235
236 /**
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700237 * Get application OAR/JAR file.
238 * Returns the OAR/JAR file used to install the specified application.
239 *
240 * @param name application name
241 * @return 200 OK; 404; 401
242 */
243 @GET
244 @Produces(MediaType.APPLICATION_OCTET_STREAM)
245 @Path("{name}/bits")
246 public Response getAppBits(@PathParam("name") String name) {
247 ApplicationAdminService service = get(ApplicationAdminService.class);
248 ApplicationId appId = nullIsNotFound(service.getId(name), APP_ID_NOT_FOUND);
249 InputStream bits = service.getApplicationArchive(appId);
250 return ok(bits).build();
251 }
252
253 /**
Jian Li847242b2016-05-11 18:58:53 -0700254 * Gets applicationId entry by either id or name.
Jian Lie1c1c8d2016-05-09 16:24:40 -0700255 *
Jian Li847242b2016-05-11 18:58:53 -0700256 * @param id id of application
Jian Lie1c1c8d2016-05-09 16:24:40 -0700257 * @param name name of application
258 * @return 200 OK; 404; 401
259 * @onos.rsModel ApplicationId
260 */
261 @GET
262 @Produces(MediaType.APPLICATION_JSON)
Jian Li847242b2016-05-11 18:58:53 -0700263 @Path("ids/entry")
Jian Lia3e4c7a2016-05-12 13:15:40 -0700264 public Response getAppIdByName(@QueryParam("id") String id,
Jian Li847242b2016-05-11 18:58:53 -0700265 @QueryParam("name") String name) {
Jian Lie1c1c8d2016-05-09 16:24:40 -0700266 CoreService service = get(CoreService.class);
Jian Li847242b2016-05-11 18:58:53 -0700267 ApplicationId appId = null;
268 if (id != null) {
Jian Lia3e4c7a2016-05-12 13:15:40 -0700269 appId = service.getAppId(Short.valueOf(id));
Jian Li847242b2016-05-11 18:58:53 -0700270 } else if (name != null) {
271 appId = service.getAppId(name);
272 }
Jian Lie1c1c8d2016-05-09 16:24:40 -0700273 return response(appId);
274 }
275
276 /**
277 * Gets a collection of application ids.
278 * Returns array of all registered application ids.
279 *
280 * @return 200 OK; 404; 401
281 * @onos.rsModel ApplicationIds
282 */
283 @GET
284 @Produces(MediaType.APPLICATION_JSON)
285 @Path("ids")
286 public Response getAppIds() {
287 CoreService service = get(CoreService.class);
288 Set<ApplicationId> appIds = service.getAppIds();
289 return ok(encodeArray(ApplicationId.class, "applicationIds", appIds)).build();
290 }
291
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800292 private Response response(ApplicationAdminService service, ApplicationId appId) {
Jian Licbf49892016-05-10 14:54:44 -0700293 Application app = nullIsNotFound(service.getApplication(appId), APP_NOT_FOUND);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800294 return ok(codec(Application.class).encode(app, this)).build();
295 }
296
Jian Lie1c1c8d2016-05-09 16:24:40 -0700297 private Response response(ApplicationId appId) {
Jian Licbf49892016-05-10 14:54:44 -0700298 ApplicationId checkedAppId = nullIsNotFound(appId, APP_ID_NOT_FOUND);
299 return ok(codec(ApplicationId.class).encode(checkedAppId, this)).build();
Jian Lie1c1c8d2016-05-09 16:24:40 -0700300 }
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800301}