blob: 0196af0d073692c6c28c367077cf63b0f521269c [file] [log] [blame]
Jonathan Hart8338b8d2017-08-15 15:46:14 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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 */
16
17package org.onosproject.routeservice.rest;
18
Andrea Campanella40bccdb2018-03-09 17:53:25 -080019import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.onosproject.rest.AbstractWebResource;
22import org.onosproject.routeservice.ResolvedRoute;
23import org.onosproject.routeservice.Route;
24import org.onosproject.routeservice.RouteAdminService;
25import org.onosproject.routeservice.RouteService;
Harshada Chaundkar14b62382019-02-18 17:51:14 -050026import org.onosproject.routeservice.RouteInfo;
Jonathan Hart8338b8d2017-08-15 15:46:14 -070027import javax.ws.rs.Consumes;
28import javax.ws.rs.DELETE;
29import javax.ws.rs.GET;
30import javax.ws.rs.POST;
31import javax.ws.rs.Path;
32import javax.ws.rs.Produces;
33import javax.ws.rs.core.MediaType;
34import javax.ws.rs.core.Response;
Andrea Campanella40bccdb2018-03-09 17:53:25 -080035import java.io.IOException;
36import java.io.InputStream;
Harshada Chaundkar14b62382019-02-18 17:51:14 -050037import java.util.ArrayList;
38import java.util.Collection;
Andrea Campanella40bccdb2018-03-09 17:53:25 -080039import java.util.Collections;
40import java.util.List;
41import java.util.stream.Collectors;
Jonathan Hart8338b8d2017-08-15 15:46:14 -070042
Andrea Campanella40bccdb2018-03-09 17:53:25 -080043import static org.onlab.util.Tools.nullIsIllegal;
Ray Milkey86ee5e82018-04-02 15:33:07 -070044import static org.onlab.util.Tools.readTreeFromStream;
Jonathan Hart8338b8d2017-08-15 15:46:14 -070045/**
46 * Manage the unicast routing information.
47 */
48@Path("routes")
49public class RouteServiceWebResource extends AbstractWebResource {
50
Andrea Campanella40bccdb2018-03-09 17:53:25 -080051 protected static final String ROUTES = "routes";
52 protected static final String ROUTES_KEY_ERROR = "Routes key must be present";
53
Jonathan Hart8338b8d2017-08-15 15:46:14 -070054 /**
55 * Get all unicast routes.
56 * Returns array of all known unicast routes.
57 *
58 * @return 200 OK with array of all known unicast routes
59 * @onos.rsModel RoutesGet
60 */
61 @GET
62 @Produces(MediaType.APPLICATION_JSON)
63 public Response getRoutes() {
64 RouteService service = get(RouteService.class);
65 ObjectNode root = mapper().createObjectNode();
66 service.getRouteTables().forEach(table -> {
67 List<Route> routes = service.getRoutes(table).stream()
68 .flatMap(ri -> ri.allRoutes().stream())
69 .map(ResolvedRoute::route)
70 .collect(Collectors.toList());
71 root.put(table.name(), codec(Route.class).encode(routes, this));
72 });
73 return ok(root).build();
74 }
75
Harshada Chaundkar14b62382019-02-18 17:51:14 -050076 /**
77 * Get count of all unicast routes.
78 * Returns count of all known unicast routes.
79 *
80 * @return 200 OK with count of all known unicast routes
81 * @onos.rsModel RoutesGetCount
82 */
83 @GET
84 @Produces(MediaType.APPLICATION_JSON)
85 @Path("/routes/count")
86 public Response getRoutesCount() {
87 RouteService service = get(RouteService.class);
88 ObjectNode root = mapper().createObjectNode();
89 service.getRouteTables().forEach(table -> {
90 Collection<RouteInfo> routes = service.getRoutes(table);
91 root.put(table.name() + "PrefixCount", routes.stream().count());
92 });
93 return ok(root).build();
94 }
95
96 /**
97 * Get count of all types routes .
98 * Returns count of all known route types.
99 *
100 * @return 200 OK with count of all route types
101 * @onos.rsModel RoutesGetTypeCount
102 */
103 @GET
104 @Produces(MediaType.APPLICATION_JSON)
105 @Path("/routes/types/count")
106 public Response getRoutesCountByType() {
107 RouteService service = get(RouteService.class);
108 ObjectNode root = mapper().createObjectNode();
109 service.getRouteTables().forEach(table -> {
110 List<Route> staticRoutes = new ArrayList<>();
111 List<Route> fpmRoutes = new ArrayList<>();
112 List<Route> ripRoutes = new ArrayList<>();
113 List<Route> dhcpRoutes = new ArrayList<>();
114 List<Route> dhcpLQRoutes = new ArrayList<>();
115 List<Route> bgpRoutes = new ArrayList<>();
116 List<Route> routes = service.getRoutes(table).stream()
117 .flatMap(ri -> ri.allRoutes().stream())
118 .map(ResolvedRoute::route)
119 .collect(Collectors.toList());
120 routes.forEach(route -> {
121 if (route.source() == Route.Source.STATIC) {
122 staticRoutes.add(route);
123 }
124 if (route.source() == Route.Source.FPM) {
125 fpmRoutes.add(route);
126 }
127 if (route.source() == Route.Source.RIP) {
128 ripRoutes.add(route);
129 }
130 if (route.source() == Route.Source.DHCP) {
131 dhcpRoutes.add(route);
132 }
133 if (route.source() == Route.Source.DHCPLQ) {
134 dhcpLQRoutes.add(route);
135 }
136 if (route.source() == Route.Source.BGP) {
137 bgpRoutes.add(route);
138 }
139 });
140 root.put(table.name() + "StaticRouteCount", staticRoutes.size());
141 root.put(table.name() + "FpmRouteCount", fpmRoutes.size());
142 root.put(table.name() + "RipRouteCount", ripRoutes.size());
143 root.put(table.name() + "DhcpRouteCount", dhcpRoutes.size());
144 root.put(table.name() + "DhcpLQRouteCount", dhcpLQRoutes.size());
145 root.put(table.name() + "BgpRouteCount", bgpRoutes.size());
146 root.put(table.name() + "TotalRouteCount", routes.stream().count());
147 });
148 return ok(root).build();
149 }
150
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700151 /**
152 * Create new unicast route.
psneha36b60f92018-08-29 08:56:08 -0400153 * Creates a new route in the unicast RIB. Source field is kept optional.
154 * Without Source field routes are created as STATIC routes. Otherwise as per the mentioned Source
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700155 *
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700156 * @param route unicast route JSON
157 * @return status of the request - CREATED if the JSON is correct,
158 * BAD_REQUEST if the JSON is invalid, NO_CONTENT otherwise
psneha36b60f92018-08-29 08:56:08 -0400159 * @onos.rsModel RouteTypePost
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700160 */
161 @POST
162 @Consumes(MediaType.APPLICATION_JSON)
163 @Produces(MediaType.APPLICATION_JSON)
164 public Response createRoute(InputStream route) {
165 RouteAdminService service = get(RouteAdminService.class);
166 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700167 ObjectNode jsonTree = readTreeFromStream(mapper(), route);
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700168 Route r = codec(Route.class).decode(jsonTree, this);
169 service.update(Collections.singletonList(r));
170 } catch (IOException ex) {
171 throw new IllegalArgumentException(ex);
172 }
173
174 return Response
175 .noContent()
176 .build();
177 }
178
179 /**
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800180 * Creates new unicast routes.
psneha36b60f92018-08-29 08:56:08 -0400181 * Creates a new route in the unicast RIB. Source field is kept optional.
182 * Without Source field routes are created as STATIC routes. Otherwise as per the mentioned Source
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800183 *
184 * @param routesStream unicast routes JSON array
185 * @return status of the request - CREATED if the JSON is correct,
186 * BAD_REQUEST if the JSON is invalid, NO_CONTENT otherwise
psneha36b60f92018-08-29 08:56:08 -0400187 * @onos.rsModel RoutesTypePost
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800188 */
189 @POST
190 @Consumes(MediaType.APPLICATION_JSON)
191 @Produces(MediaType.APPLICATION_JSON)
192 @Path("/bulk")
193 public Response createRoutes(InputStream routesStream) {
194 RouteAdminService service = get(RouteAdminService.class);
195 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700196 ObjectNode jsonTree = readTreeFromStream(mapper(), routesStream);
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800197 ArrayNode routesArray = nullIsIllegal((ArrayNode) jsonTree.get(ROUTES),
198 ROUTES_KEY_ERROR);
199 List<Route> routes = codec(Route.class).decode(routesArray, this);
200 service.update(routes);
201
202 } catch (IOException ex) {
203 throw new IllegalArgumentException(ex);
204 }
205
206 return Response
207 .noContent()
208 .build();
209 }
210
211 /**
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700212 * Remove a unicast route.
213 * Removes a route from the unicast RIB.
214 *
215 * @param route unicast route JSON
216 * @return 204 NO CONTENT
217 * @onos.rsModel RoutePost
218 */
219 @DELETE
220 @Consumes(MediaType.APPLICATION_JSON)
221 public Response deleteRoute(InputStream route) {
222 RouteAdminService service = get(RouteAdminService.class);
223 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700224 ObjectNode jsonTree = readTreeFromStream(mapper(), route);
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700225 Route r = codec(Route.class).decode(jsonTree, this);
226 service.withdraw(Collections.singletonList(r));
227 } catch (IOException ex) {
228 throw new IllegalArgumentException(ex);
229 }
230 return Response.noContent().build();
231 }
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800232
233 /**
234 * Removes unicast routes.
235 * Removes multiple routes from the unicast RIB.
236 *
237 * @param routesStream unicast routes array JSON
238 * @return 204 NO CONTENT
239 */
240 @DELETE
241 @Consumes(MediaType.APPLICATION_JSON)
242 @Path("/bulk")
243 public Response deleteRoutes(InputStream routesStream) {
244 RouteAdminService service = get(RouteAdminService.class);
245 try {
Ray Milkey86ee5e82018-04-02 15:33:07 -0700246 ObjectNode jsonTree = readTreeFromStream(mapper(), routesStream);
Andrea Campanella40bccdb2018-03-09 17:53:25 -0800247 ArrayNode routesArray = nullIsIllegal((ArrayNode) jsonTree.get(ROUTES),
248 ROUTES_KEY_ERROR);
249 List<Route> routes = codec(Route.class).decode(routesArray, this);
250 service.withdraw(routes);
251
252 } catch (IOException ex) {
253 throw new IllegalArgumentException(ex);
254 }
255
256 return Response
257 .noContent()
258 .build();
259 }
Jonathan Hart8338b8d2017-08-15 15:46:14 -0700260}