blob: 8c073aded999bcef1a8e57a6a2000b5aed6c7a28 [file] [log] [blame]
Thomas Vachuska96d55b12015-05-11 08:52:03 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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 */
16package org.onosproject.rest.resources;
17
Jonathan Hartb11c4d02016-03-23 09:05:44 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import org.onosproject.net.config.Config;
21import org.onosproject.net.config.NetworkConfigService;
22import org.onosproject.net.config.SubjectFactory;
23import org.onosproject.rest.AbstractWebResource;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070024
25import javax.ws.rs.Consumes;
26import javax.ws.rs.DELETE;
27import javax.ws.rs.GET;
28import javax.ws.rs.POST;
29import javax.ws.rs.Path;
30import javax.ws.rs.PathParam;
31import javax.ws.rs.Produces;
32import javax.ws.rs.core.MediaType;
33import javax.ws.rs.core.Response;
Jonathan Hartb11c4d02016-03-23 09:05:44 -070034import java.io.IOException;
35import java.io.InputStream;
36import java.util.Set;
Ray Milkey36992c82015-11-17 13:31:15 -080037
38import static org.onlab.util.Tools.emptyIsNotFound;
39import static org.onlab.util.Tools.nullIsNotFound;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070040
41/**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070042 * Manage network configurations.
Thomas Vachuska96d55b12015-05-11 08:52:03 -070043 */
44@Path("network/configuration")
45public class NetworkConfigWebResource extends AbstractWebResource {
46
Ray Milkey36992c82015-11-17 13:31:15 -080047
48 private String subjectClassNotFoundErrorString(String subjectClassKey) {
49 return "Config for '" + subjectClassKey + "' not found";
50 }
51
52 private String subjectNotFoundErrorString(String subjectClassKey,
53 String subjectKey) {
54 return "Config for '"
55 + subjectClassKey + "/" + subjectKey
56 + "' not found";
57 }
58
59 private String configKeyNotFoundErrorString(String subjectClassKey,
60 String subjectKey,
61 String configKey) {
62 return "Config for '"
63 + subjectClassKey + "/" + subjectKey + "/" + configKey
64 + "' not found";
65 }
66
Thomas Vachuska96d55b12015-05-11 08:52:03 -070067 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070068 * Get entire network configuration base.
Ray Milkey36992c82015-11-17 13:31:15 -080069 *
Thomas Vachuska96d55b12015-05-11 08:52:03 -070070 * @return network configuration JSON
71 */
72 @GET
73 @Produces(MediaType.APPLICATION_JSON)
74 @SuppressWarnings("unchecked")
75 public Response download() {
76 NetworkConfigService service = get(NetworkConfigService.class);
77 ObjectNode root = mapper().createObjectNode();
Thomas Vachuskaea5adc62015-10-07 11:52:30 -070078 service.getSubjectClasses().forEach(sc -> {
79 SubjectFactory subjectFactory = service.getSubjectFactory(sc);
80 produceJson(service, newObject(root, subjectFactory.subjectClassKey()),
81 subjectFactory, sc);
82 });
Thomas Vachuska96d55b12015-05-11 08:52:03 -070083 return ok(root).build();
84 }
85
86 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -070087 * Get all network configuration for a subject class.
Thomas Vachuska96d55b12015-05-11 08:52:03 -070088 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -070089 * @param subjectClassKey subject class key
Thomas Vachuska96d55b12015-05-11 08:52:03 -070090 * @return network configuration JSON
91 */
92 @GET
Thomas Vachuskaea5adc62015-10-07 11:52:30 -070093 @Path("{subjectClassKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -070094 @Produces(MediaType.APPLICATION_JSON)
95 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -070096 public Response download(@PathParam("subjectClassKey") String subjectClassKey) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -070097 NetworkConfigService service = get(NetworkConfigService.class);
98 ObjectNode root = mapper().createObjectNode();
Ray Milkey36992c82015-11-17 13:31:15 -080099 SubjectFactory subjectFactory =
100 nullIsNotFound(service.getSubjectFactory(subjectClassKey),
101 subjectClassNotFoundErrorString(subjectClassKey));
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700102 produceJson(service, root, subjectFactory, subjectFactory.subjectClass());
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700103 return ok(root).build();
104 }
105
106 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700107 * Get all network configuration for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700108 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700109 * @param subjectClassKey subjectKey class key
110 * @param subjectKey subjectKey key
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700111 * @return network configuration JSON
112 */
113 @GET
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700114 @Path("{subjectClassKey}/{subjectKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700115 @Produces(MediaType.APPLICATION_JSON)
116 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700117 public Response download(@PathParam("subjectClassKey") String subjectClassKey,
118 @PathParam("subjectKey") String subjectKey) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700119 NetworkConfigService service = get(NetworkConfigService.class);
120 ObjectNode root = mapper().createObjectNode();
Ray Milkey36992c82015-11-17 13:31:15 -0800121 SubjectFactory subjectFactory =
122 nullIsNotFound(service.getSubjectFactory(subjectClassKey),
123 subjectClassNotFoundErrorString(subjectClassKey));
124 produceSubjectJson(service, root, subjectFactory.createSubject(subjectKey),
125 true,
126 subjectNotFoundErrorString(subjectClassKey, subjectKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700127 return ok(root).build();
128 }
129
130 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700131 * Get specific network configuration for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700132 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700133 * @param subjectClassKey subjectKey class key
134 * @param subjectKey subjectKey key
135 * @param configKey configuration class key
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700136 * @return network configuration JSON
137 */
138 @GET
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700139 @Path("{subjectClassKey}/{subjectKey}/{configKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700140 @Produces(MediaType.APPLICATION_JSON)
141 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700142 public Response download(@PathParam("subjectClassKey") String subjectClassKey,
143 @PathParam("subjectKey") String subjectKey,
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700144 @PathParam("configKey") String configKey) {
145 NetworkConfigService service = get(NetworkConfigService.class);
Ray Milkey36992c82015-11-17 13:31:15 -0800146
147 Object subject =
148 nullIsNotFound(service.getSubjectFactory(subjectClassKey)
149 .createSubject(subjectKey),
150 subjectNotFoundErrorString(subjectClassKey, subjectKey));
151
152 Class configClass =
153 nullIsNotFound(service.getConfigClass(subjectClassKey, configKey),
154 configKeyNotFoundErrorString(subjectClassKey, subjectKey, configKey));
155 Config config =
156 nullIsNotFound(service.getConfig(subject, configClass),
157 configKeyNotFoundErrorString(subjectClassKey,
158 subjectKey,
159 configKey));
160 return ok(config.node()).build();
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700161 }
162
163 @SuppressWarnings("unchecked")
164 private void produceJson(NetworkConfigService service, ObjectNode node,
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700165 SubjectFactory subjectFactory, Class subjectClass) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700166 service.getSubjects(subjectClass).forEach(s ->
Ray Milkey36992c82015-11-17 13:31:15 -0800167 produceSubjectJson(service, newObject(node, subjectFactory.subjectKey(s)), s, false, ""));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700168 }
169
170 private void produceSubjectJson(NetworkConfigService service, ObjectNode node,
Ray Milkey36992c82015-11-17 13:31:15 -0800171 Object subject,
172 boolean emptyIsError,
173 String emptyErrorMessage) {
174 Set<? extends Config<Object>> configs = service.getConfigs(subject);
175 if (emptyIsError) {
176 // caller wants an empty set to be a 404
177 configs = emptyIsNotFound(configs, emptyErrorMessage);
178 }
179 configs.forEach(c -> node.set(c.key(), c.node()));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700180 }
181
182
183 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700184 * Upload bulk network configuration.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700185 *
186 * @param request network configuration JSON rooted at the top node
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700187 * @return empty response
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700188 * @throws IOException if unable to parse the request
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700189 */
190 @POST
191 @Consumes(MediaType.APPLICATION_JSON)
192 @SuppressWarnings("unchecked")
193 public Response upload(InputStream request) throws IOException {
194 NetworkConfigService service = get(NetworkConfigService.class);
195 ObjectNode root = (ObjectNode) mapper().readTree(request);
196 root.fieldNames()
197 .forEachRemaining(sk -> consumeJson(service, (ObjectNode) root.path(sk),
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700198 service.getSubjectFactory(sk)));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700199 return Response.ok().build();
200 }
201
202 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700203 * Upload multiple network configurations for a subject class.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700204 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700205 * @param subjectClassKey subject class key
206 * @param request network configuration JSON rooted at the top node
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700207 * @return empty response
Thomas Vachuskad894b5d2015-07-30 11:59:07 -0700208 * @throws IOException if unable to parse the request
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700209 */
210 @POST
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700211 @Path("{subjectClassKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700212 @Consumes(MediaType.APPLICATION_JSON)
213 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700214 public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700215 InputStream request) throws IOException {
216 NetworkConfigService service = get(NetworkConfigService.class);
217 ObjectNode root = (ObjectNode) mapper().readTree(request);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700218 consumeJson(service, root, service.getSubjectFactory(subjectClassKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700219 return Response.ok().build();
220 }
221
222 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700223 * Upload mutliple network configurations for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700224 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700225 * @param subjectClassKey subjectKey class key
226 * @param subjectKey subjectKey key
227 * @param request network configuration JSON rooted at the top node
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700228 * @return empty response
Thomas Vachuskad894b5d2015-07-30 11:59:07 -0700229 * @throws IOException if unable to parse the request
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700230 */
231 @POST
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700232 @Path("{subjectClassKey}/{subjectKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700233 @Consumes(MediaType.APPLICATION_JSON)
234 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700235 public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
236 @PathParam("subjectKey") String subjectKey,
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700237 InputStream request) throws IOException {
238 NetworkConfigService service = get(NetworkConfigService.class);
239 ObjectNode root = (ObjectNode) mapper().readTree(request);
240 consumeSubjectJson(service, root,
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700241 service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
242 subjectClassKey);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700243 return Response.ok().build();
244 }
245
246 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700247 * Upload specific network configuration for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700248 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700249 * @param subjectClassKey subjectKey class key
250 * @param subjectKey subjectKey key
251 * @param configKey configuration class key
252 * @param request network configuration JSON rooted at the top node
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700253 * @return empty response
Thomas Vachuskad894b5d2015-07-30 11:59:07 -0700254 * @throws IOException if unable to parse the request
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700255 */
256 @POST
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700257 @Path("{subjectClassKey}/{subjectKey}/{configKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700258 @Consumes(MediaType.APPLICATION_JSON)
259 @SuppressWarnings("unchecked")
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700260 public Response upload(@PathParam("subjectClassKey") String subjectClassKey,
261 @PathParam("subjectKey") String subjectKey,
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700262 @PathParam("configKey") String configKey,
263 InputStream request) throws IOException {
264 NetworkConfigService service = get(NetworkConfigService.class);
Jonathan Hartb11c4d02016-03-23 09:05:44 -0700265 JsonNode root = mapper().readTree(request);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800266 service.applyConfig(subjectClassKey,
267 service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
268 configKey, root);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700269 return Response.ok().build();
270 }
271
272 private void consumeJson(NetworkConfigService service, ObjectNode classNode,
273 SubjectFactory subjectFactory) {
274 classNode.fieldNames().forEachRemaining(s ->
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700275 consumeSubjectJson(service, (ObjectNode) classNode.path(s),
276 subjectFactory.createSubject(s),
277 subjectFactory.subjectClassKey()));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700278 }
279
280 private void consumeSubjectJson(NetworkConfigService service,
Jonathan Hart111b42b2015-07-14 13:28:05 -0700281 ObjectNode subjectNode, Object subject,
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800282 String subjectClassKey) {
283 subjectNode.fieldNames().forEachRemaining(configKey ->
284 service.applyConfig(subjectClassKey, subject, configKey, subjectNode.path(configKey)));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700285 }
286
287
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800288 // FIXME: Refactor to allow queued configs to be removed
289
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700290 /**
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700291 * Clear entire network configuration base.
292 *
293 * @return empty response
294 */
295 @DELETE
296 @SuppressWarnings("unchecked")
297 public Response delete() {
298 NetworkConfigService service = get(NetworkConfigService.class);
299 service.getSubjectClasses()
300 .forEach(subjectClass -> service.getSubjects(subjectClass)
301 .forEach(subject -> service.getConfigs(subject)
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700302 .forEach(config -> service.removeConfig(subject, config.getClass()))));
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700303 return Response.ok().build();
304 }
305
306 /**
307 * Clear all network configurations for a subject class.
308 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700309 * @param subjectClassKey subject class key
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700310 */
311 @DELETE
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700312 @Path("{subjectClassKey}")
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700313 @SuppressWarnings("unchecked")
Ray Milkeyb9fe25d2015-11-18 15:54:44 -0800314 public void delete(@PathParam("subjectClassKey") String subjectClassKey) {
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700315 NetworkConfigService service = get(NetworkConfigService.class);
Ray Milkeyb9fe25d2015-11-18 15:54:44 -0800316 service.getSubjects(service.getSubjectFactory(subjectClassKey).subjectClass())
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700317 .forEach(subject -> service.getConfigs(subject)
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700318 .forEach(config -> service.removeConfig(subject, config.getClass())));
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -0700319 }
320
321 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700322 * Clear all network configurations for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700323 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700324 * @param subjectClassKey subjectKey class key
325 * @param subjectKey subjectKey key
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700326 */
327 @DELETE
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700328 @Path("{subjectClassKey}/{subjectKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700329 @SuppressWarnings("unchecked")
Ray Milkeyb9fe25d2015-11-18 15:54:44 -0800330 public void delete(@PathParam("subjectClassKey") String subjectClassKey,
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700331 @PathParam("subjectKey") String subjectKey) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700332 NetworkConfigService service = get(NetworkConfigService.class);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700333 Object s = service.getSubjectFactory(subjectClassKey).createSubject(subjectKey);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700334 service.getConfigs(s).forEach(c -> service.removeConfig(s, c.getClass()));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700335 }
336
337 /**
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700338 * Clear specific network configuration for a subjectKey.
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700339 *
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700340 * @param subjectClassKey subjectKey class key
341 * @param subjectKey subjectKey key
342 * @param configKey configuration class key
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700343 */
344 @DELETE
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700345 @Path("{subjectClassKey}/{subjectKey}/{configKey}")
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700346 @SuppressWarnings("unchecked")
Ray Milkeyb9fe25d2015-11-18 15:54:44 -0800347 public void delete(@PathParam("subjectClassKey") String subjectClassKey,
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700348 @PathParam("subjectKey") String subjectKey,
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700349 @PathParam("configKey") String configKey) {
350 NetworkConfigService service = get(NetworkConfigService.class);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700351 service.removeConfig(service.getSubjectFactory(subjectClassKey).createSubject(subjectKey),
352 service.getConfigClass(subjectClassKey, configKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700353 }
354
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700355}