blob: f8ae77f128d11696b3c8587c18a4431f56cb3623 [file] [log] [blame]
psnehab7109092018-10-10 08:26:02 -04001/*
2 * Copyright 2018-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 */
17
18package org.onosproject.dhcprelay.rest;
19
20import org.onlab.packet.IpAddress;
21import org.onlab.packet.IpPrefix;
anjalikk072e7912018-11-02 08:25:20 -040022import org.onlab.util.Tools;
23import com.fasterxml.jackson.databind.ObjectMapper;
24import com.fasterxml.jackson.databind.node.ArrayNode;
25import com.fasterxml.jackson.databind.node.ObjectNode;
psnehab7109092018-10-10 08:26:02 -040026import org.onosproject.dhcprelay.api.DhcpRelayService;
anjalikk072e7912018-11-02 08:25:20 -040027import org.onosproject.dhcprelay.api.DhcpServerInfo;
28import org.onosproject.dhcprelay.cli.DhcpRelayCommand;
29import org.onosproject.dhcprelay.store.DhcpRecord;
30import org.onosproject.dhcprelay.store.DhcpRelayCounters;
Anjali K Kf15ec4a2018-11-21 08:39:01 -050031import org.onosproject.dhcprelay.store.DhcpRelayCountersStore;
psnehab7109092018-10-10 08:26:02 -040032import org.onosproject.rest.AbstractWebResource;
33import org.onosproject.routeservice.Route;
34import org.onosproject.routeservice.RouteStore;
35import org.onosproject.routing.fpm.api.FpmRecord;
36import org.slf4j.Logger;
37
38import javax.ws.rs.DELETE;
anjalikk072e7912018-11-02 08:25:20 -040039import javax.ws.rs.GET;
psnehab7109092018-10-10 08:26:02 -040040import javax.ws.rs.Path;
41import javax.ws.rs.PathParam;
anjalikk072e7912018-11-02 08:25:20 -040042import javax.ws.rs.Produces;
43import javax.ws.rs.core.MediaType;
psnehab7109092018-10-10 08:26:02 -040044import javax.ws.rs.core.Response;
45
anjalikk072e7912018-11-02 08:25:20 -040046import java.util.Collection;
anjalikk072e7912018-11-02 08:25:20 -040047import java.util.List;
Anjali K Kf15ec4a2018-11-21 08:39:01 -050048import java.util.Map;
psnehab7109092018-10-10 08:26:02 -040049import java.util.Optional;
50
51import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * DHCP Relay agent REST API.
55 */
Anjali K Kf15ec4a2018-11-21 08:39:01 -050056@Path("dhcp-relay")
psnehab7109092018-10-10 08:26:02 -040057public class DhcpRelayWebResource extends AbstractWebResource {
58 private static final Logger LOG = getLogger(DhcpRelayWebResource.class);
anjalikk072e7912018-11-02 08:25:20 -040059 private final ObjectMapper mapper = new ObjectMapper();
60 private final DhcpRelayService dhcpDelayService = get(DhcpRelayService.class);
61 private static final String NA = "N/A";
Anjali K Kf15ec4a2018-11-21 08:39:01 -050062 private static final String HEADER_A_COUNTERS = "DHCP-Relay-Aggregate-Counters";
63 private static final String GCOUNT_KEY = "global";
anjalikk072e7912018-11-02 08:25:20 -040064 List<DhcpServerInfo> defaultDhcpServerInfoList = dhcpDelayService.getDefaultDhcpServerInfoList();
65 List<DhcpServerInfo> indirectDhcpServerInfoList = dhcpDelayService.getIndirectDhcpServerInfoList();
66 Collection<DhcpRecord> records = dhcpDelayService.getDhcpRecords();
Anjali K Kf15ec4a2018-11-21 08:39:01 -050067 DhcpRelayCountersStore counterStore = get(DhcpRelayCountersStore.class);
68 Optional<DhcpRelayCounters> perClassCounters = counterStore.getCounters(GCOUNT_KEY);
69 private static final String DIRECTLY = "[D]";
70 private static final String EMPTY = "";
anjalikk072e7912018-11-02 08:25:20 -040071
psnehab7109092018-10-10 08:26:02 -040072
73 /**
74 * Deletes the fpm route from fpm record.
75 * Corresponding route from the route store
76 *
77 * @param prefix IpPrefix
pierc9539e62018-12-12 19:00:29 +010078 * @return 204 NO CONTENT, 404; 401
psnehab7109092018-10-10 08:26:02 -040079 */
80 @DELETE
Anjali K Kf15ec4a2018-11-21 08:39:01 -050081 @Path("fpm/{prefix}")
psnehab7109092018-10-10 08:26:02 -040082 public Response dhcpFpmDelete(@PathParam("prefix") String prefix) {
83 DhcpRelayService dhcpRelayService = get(DhcpRelayService.class);
84 RouteStore routeStore = get(RouteStore.class);
85
86 try {
87 // removes fpm route from fpm record
88 Optional<FpmRecord> fpmRecord = dhcpRelayService.removeFpmRecord(IpPrefix.valueOf(prefix));
89 if (fpmRecord.isPresent()) {
90 IpAddress nextHop = fpmRecord.get().nextHop();
91 Route route = new Route(Route.Source.DHCP, IpPrefix.valueOf(prefix), nextHop);
92 // removes DHCP route from route store
93 routeStore.removeRoute(route);
94 } else {
95 LOG.warn("fpmRecord is not present");
96 }
97 } catch (IllegalArgumentException ex) {
98 throw new IllegalArgumentException(ex);
99 }
100
101 return Response.noContent().build();
102 }
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500103
anjalikk072e7912018-11-02 08:25:20 -0400104 /**
105 * Returns the response object with list of dhcp servers without counters.
106 *
107 * @return 200 OK with component properties of given component and variable
108 */
109 @GET
110 @Produces(MediaType.APPLICATION_JSON)
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500111 public Response getDhcpRelayServers() {
112 ObjectNode node = getDhcpRelayServersJsonOutput();
anjalikk072e7912018-11-02 08:25:20 -0400113 return Response.status(200).entity(node).build();
114 }
115
116 /**
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500117 * Returns dhcp counters details.
anjalikk072e7912018-11-02 08:25:20 -0400118 *
anjalikk072e7912018-11-02 08:25:20 -0400119 * @return 200 OK with component properties of given component and variable
120 */
121 @GET
122 @Produces(MediaType.APPLICATION_JSON)
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500123 @Path("counters")
124 public Response getDhcpRelayCounters() {
125 ObjectNode node = getDhcpRelayCountersJsonOutput();
anjalikk072e7912018-11-02 08:25:20 -0400126 return Response.status(200).entity(node).build();
127 }
128
129 /**
130 * To reset the dhcp relay counters.
131 *
anjalikk072e7912018-11-02 08:25:20 -0400132 * @return 200 OK with component properties of given component and variable
133 */
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500134 @DELETE
135 @Path("counters")
136 public Response resetDhcpRelayCounters() {
137 resetDhcpRelayCountersInternal();
138 return Response.status(200).build();
139 }
140
141 /**
142 * Returns results with aggregate of counters.
143 *
144 * @return 200 OK with component properties of given component and variable
145 */
146 @GET
anjalikk072e7912018-11-02 08:25:20 -0400147 @Produces(MediaType.APPLICATION_JSON)
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500148 @Path("aggregate-counters")
149 public Response getDhcpRelayAggCounters() {
150 ObjectNode node = getDhcpRelayAggCountersJsonOutput();
anjalikk072e7912018-11-02 08:25:20 -0400151 return Response.status(200).entity(node).build();
152 }
153
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500154 /**
155 * Reset dhcp relay aggregate counters.
156 *
157 * @return 200 OK with component properties of given component and variable
158 */
159 @DELETE
160 @Produces(MediaType.APPLICATION_JSON)
161 @Path("aggregate-counters")
162 public Response resetDhcpRelayAggCounters() {
163 resetDhcpRelayAggCountersInternal();
164 return Response.status(200).build();
165 }
anjalikk072e7912018-11-02 08:25:20 -0400166
167 /**
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500168 * To create json output of Dhcp Relay servers.
anjalikk072e7912018-11-02 08:25:20 -0400169 *
anjalikk072e7912018-11-02 08:25:20 -0400170 * @return node type ObjectNode.
171 */
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500172 private ObjectNode getDhcpRelayServersJsonOutput() {
anjalikk072e7912018-11-02 08:25:20 -0400173 ObjectNode node = mapper.createObjectNode();
anjalikk072e7912018-11-02 08:25:20 -0400174
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500175 if (!defaultDhcpServerInfoList.isEmpty()) {
176 ArrayNode defaultDhcpServers = getDefaultDhcpServers();
177 node.put("Default-DHCP-Servers", defaultDhcpServers);
178 }
179
180 if (!indirectDhcpServerInfoList.isEmpty()) {
181 ArrayNode indirectDhcpServers = getIndirectDhcpServers();
182 node.put("Indirect-DHCP-Servers", indirectDhcpServers);
183 }
184 if (!records.isEmpty()) {
185 ArrayNode dhcpRelayRecords = dhcpRelayRecords();
186 node.put("DHCP-Relay-Records([D]:Directly-Connected)", dhcpRelayRecords);
187 }
anjalikk072e7912018-11-02 08:25:20 -0400188
189 return node;
190
191 }
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500192
anjalikk072e7912018-11-02 08:25:20 -0400193 /**
194 * To get the liset of dhcp servers.
195 *
196 * @param dhcpServerInfoList type List
197 * @return servers type ArrayNode.
198 */
199 private ArrayNode listServers(List<DhcpServerInfo> dhcpServerInfoList) {
200 ArrayNode servers = mapper.createArrayNode();
201 dhcpServerInfoList.forEach(dhcpServerInfo -> {
202 ObjectNode serverNode = mapper.createObjectNode();
203 String connectPoint = dhcpServerInfo.getDhcpServerConnectPoint()
204 .map(cp -> cp.toString()).orElse(NA);
205 String serverMac = dhcpServerInfo.getDhcpConnectMac()
206 .map(mac -> mac.toString()).orElse(NA);
207 String gatewayAddress;
208 String serverIp;
209
210 switch (dhcpServerInfo.getVersion()) {
211 case DHCP_V4:
212 gatewayAddress = dhcpServerInfo.getDhcpGatewayIp4()
213 .map(gw -> gw.toString()).orElse(null);
214 serverIp = dhcpServerInfo.getDhcpServerIp4()
215 .map(ip -> ip.toString()).orElse(NA);
216 break;
217 case DHCP_V6:
218 gatewayAddress = dhcpServerInfo.getDhcpGatewayIp6()
219 .map(gw -> gw.toString()).orElse(null);
220 serverIp = dhcpServerInfo.getDhcpServerIp6()
221 .map(ip -> ip.toString()).orElse(NA);
222 break;
223 default:
224 return;
225 }
226
227 serverNode.put("connectPoint", connectPoint);
228 if (gatewayAddress != null) {
229 serverNode.put("server", serverIp.concat(" via ").concat(gatewayAddress));
230 } else {
231 serverNode.put("server", serverIp);
232 }
233 serverNode.put("mac", serverMac);
234 servers.add(serverNode);
235 });
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500236 return servers;
237 }
anjalikk072e7912018-11-02 08:25:20 -0400238
239 /**
240 * To get the list of dhcp relay records.
241 *
anjalikk072e7912018-11-02 08:25:20 -0400242 * @return dhcpRelayRecords type ArrayNode.
243 */
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500244 private ArrayNode dhcpRelayRecords() {
anjalikk072e7912018-11-02 08:25:20 -0400245 DhcpRelayCommand dhcpRelayCommand = new DhcpRelayCommand();
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500246 ObjectNode node = mapper.createObjectNode();
anjalikk072e7912018-11-02 08:25:20 -0400247 ArrayNode dhcpRelayRecords = mapper.createArrayNode();
248 records.forEach(record -> {
249 ObjectNode dhcpRecord = mapper.createObjectNode();
250 dhcpRecord.put("id", record.macAddress() + "/" + record.vlanId());
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500251 dhcpRecord.put("locations", record.locations().toString()
252 .concat(record.directlyConnected() ? DIRECTLY : EMPTY));
anjalikk072e7912018-11-02 08:25:20 -0400253 dhcpRecord.put("last-seen", Tools.timeAgo(record.lastSeen()));
254 dhcpRecord.put("IPv4", dhcpRelayCommand.ip4State(record));
255 dhcpRecord.put("IPv6", dhcpRelayCommand.ip6State(record));
256 dhcpRelayRecords.add(dhcpRecord);
257 });
258 return dhcpRelayRecords;
259 }
260
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500261 /**
anjalikk072e7912018-11-02 08:25:20 -0400262 * To get the details of dhcp relay counters.
263 *
anjalikk072e7912018-11-02 08:25:20 -0400264 * @return counterArray type ArrayNode.
265 */
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500266 private ObjectNode getDhcpRelayCountersJsonOutput() {
267 ObjectNode node = mapper.createObjectNode();
anjalikk072e7912018-11-02 08:25:20 -0400268 ObjectNode counters = mapper.createObjectNode();
anjalikk072e7912018-11-02 08:25:20 -0400269 ArrayNode counterArray = mapper.createArrayNode();
270 records.forEach(record -> {
271 DhcpRelayCounters v6Counters = record.getV6Counters();
anjalikk072e7912018-11-02 08:25:20 -0400272 Map<String, Integer> countersMap = v6Counters.getCounters();
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500273 ObjectNode counterPackets = mapper.createObjectNode();
anjalikk072e7912018-11-02 08:25:20 -0400274 countersMap.forEach((name, value) -> {
275 counterPackets.put(name, value);
anjalikk072e7912018-11-02 08:25:20 -0400276 });
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500277 counters.put(record.macAddress() + "/" + record.vlanId().toString(), counterPackets);
anjalikk072e7912018-11-02 08:25:20 -0400278 });
Anjali K Kf15ec4a2018-11-21 08:39:01 -0500279 counterArray.add(counters);
280 node.put("v6-DHCP-Relay-Counter", counterArray);
281 return node;
282 }
283
284 /**
285 * To get the list of default dhcp servers.
286 *
287 * @return node type ObjectNode.
288 */
289 private ArrayNode getDefaultDhcpServers() {
290 ObjectNode node = mapper.createObjectNode();
291 ArrayNode defaultDhcpServers = listServers(defaultDhcpServerInfoList);
292 return defaultDhcpServers;
293 }
294
295 /**
296 * To get the list of indirect dhcp servers.
297 *
298 * @return node type ObjectNode.
299 */
300 private ArrayNode getIndirectDhcpServers() {
301 ArrayNode indirectDhcpServers = listServers(indirectDhcpServerInfoList);
302 return indirectDhcpServers;
303 }
304
305 /**
306 * To reset dhcp relay counters.
307 *
308 * @return counterArray type ArrayNode.
309 */
310 private void resetDhcpRelayCountersInternal() {
311 records.forEach(record -> {
312 DhcpRelayCounters v6Counters = record.getV6Counters();
313 v6Counters.resetCounters();
314 });
315 }
316
317 /**
318 * To get dhcp relay aggregate counters.
319 *
320 * @return counterPackets type ObjectNode.
321 */
322 private ObjectNode getDhcpRelayAggCountersJsonOutput() {
323 ObjectNode counterPackets = mapper.createObjectNode();
324 ObjectNode dhcpRelayAggCounterNode = mapper.createObjectNode();
325 if (perClassCounters.isPresent()) {
326 Map<String, Integer> counters = perClassCounters.get().getCounters();
327 if (counters.size() > 0) {
328 counters.forEach((name, value) -> {
329 counterPackets.put(name, value);
330 });
331 }
332 }
333 dhcpRelayAggCounterNode.put(HEADER_A_COUNTERS, counterPackets);
334 return dhcpRelayAggCounterNode;
335 }
336
337 /**
338 * To reset aggregate counters.
339 *
340 * @return counterPackets type ObjectNode.
341 */
342 private void resetDhcpRelayAggCountersInternal() {
343 if (perClassCounters.isPresent()) {
344 counterStore.resetCounters(GCOUNT_KEY);
345 }
anjalikk072e7912018-11-02 08:25:20 -0400346 }
psnehab7109092018-10-10 08:26:02 -0400347
348}