Added insertControllerRow and fixed getSerializedRow. getRows still need to return...
[ovsdb.git] / northbound / ovsdb / src / main / java / org / opendaylight / ovsdb / northbound / OVSDBNorthbound.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.ovsdb.northbound;
9
10 import java.util.List;
11
12 import javax.ws.rs.Consumes;
13 import javax.ws.rs.DELETE;
14 import javax.ws.rs.GET;
15 import javax.ws.rs.POST;
16 import javax.ws.rs.PUT;
17 import javax.ws.rs.Path;
18 import javax.ws.rs.PathParam;
19 import javax.ws.rs.core.Context;
20 import javax.ws.rs.core.MediaType;
21 import javax.ws.rs.core.Response;
22 import javax.ws.rs.core.SecurityContext;
23 import javax.ws.rs.core.UriInfo;
24
25 import org.codehaus.enunciate.jaxrs.ResponseCode;
26 import org.codehaus.enunciate.jaxrs.StatusCodes;
27 import org.codehaus.enunciate.jaxrs.TypeHint;
28 import org.opendaylight.controller.northbound.commons.RestMessages;
29 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
30 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
31 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
32 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
33 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
34 import org.opendaylight.controller.sal.authorization.Privilege;
35 import org.opendaylight.controller.sal.core.Node;
36 import org.opendaylight.controller.sal.utils.ServiceHelper;
37 import org.opendaylight.controller.sal.utils.Status;
38 import org.opendaylight.controller.sal.utils.StatusCode;
39 import org.opendaylight.ovsdb.lib.table.internal.Table;
40 import org.opendaylight.ovsdb.lib.table.internal.Tables;
41 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * This class provides REST APIs to Create, Read, Update and Delete OVSDB Row in any of the ovsdb table
47  * database one at a time.
48  */
49
50 @Path("/")
51 public class OVSDBNorthbound {
52     protected static final Logger logger = LoggerFactory.getLogger(OVSDBNorthbound.class);
53
54     @Context
55     private UriInfo _uriInfo;
56     private String username;
57
58     @Context
59     public void setSecurityContext(SecurityContext context) {
60         if (context != null && context.getUserPrincipal() != null) {
61             username = context.getUserPrincipal().getName();
62         }
63     }
64
65     protected String getUserName() {
66         return username;
67     }
68
69     private void handleNameMismatch(String name, String nameinURL) {
70         if (name == null || nameinURL == null) {
71             throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : Name is null");
72         }
73
74         if (name.equalsIgnoreCase(nameinURL)) {
75             return;
76         }
77         throw new ResourceConflictException(RestMessages.INVALIDDATA.toString()
78                 + " : Table Name in URL does not match the row name in request body");
79     }
80
81     private String getOVSTableName(String tableName) {
82         List<Table> tables = Tables.getTables();
83         for (Table table : tables) {
84             if (table.getTableName().getName().equalsIgnoreCase(tableName)) {
85                 return table.getTableName().getName();
86             }
87         }
88         // TODO Auto-generated method stub
89         return null;
90     }
91
92     /**
93      * Create a Row
94      *
95      * @param tableName name of the ovsdb table
96      * @param row the {@link OVSDBRow} Row that is being inserted
97      *
98      * @return Response as dictated by the HTTP Response Status code
99      *
100      *         <pre>
101      * Example:
102      *
103      * Request URL:
104      * https://localhost/controller/nb/v2/ovsdb/tables/bridge/rows
105      * </pre>
106      */
107
108     @Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows")
109     @POST
110     @StatusCodes({ @ResponseCode(code = 201, condition = "Row Inserted successfully"),
111         @ResponseCode(code = 400, condition = "Invalid data passed"),
112         @ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
113     @Consumes({ MediaType.APPLICATION_JSON})
114     public Response addRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
115                            @PathParam("tableName") String tableName, @TypeHint(OVSDBRow.class) OVSDBRow row) {
116
117         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
118             throw new UnauthorizedException("User is not authorized to perform this operation");
119         }
120
121         String ovsTableName = getOVSTableName(tableName);
122         if (ovsTableName == null) {
123             Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
124             return NorthboundUtils.getResponse(status);
125         }
126
127         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
128                                                                                             this);
129         if (ovsdbTable == null) {
130             throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
131         }
132
133         if (row != null && row.getRow() != null) {
134             handleNameMismatch(tableName, row.getRow().getTableName().getName());
135             Node node = Node.fromString(nodeType, nodeId);
136             Status statusWithUUID = ovsdbTable.insertRow(node, ovsTableName, row.getParent_uuid(), row.getRow());
137
138             if (statusWithUUID.isSuccess()) {
139                 return Response.status(Response.Status.CREATED)
140                         .header("Location", String.format("%s/%s", _uriInfo.getAbsolutePath().toString(),
141                                                                     statusWithUUID.getDescription()))
142                         .entity(statusWithUUID.getDescription())
143                         .build();
144             } else {
145                 return NorthboundUtils.getResponse(statusWithUUID);
146             }
147         }
148         return Response.status(Response.Status.BAD_REQUEST).build();
149     }
150
151     /**
152      * Read a Row
153      *
154      * @param node OVSDB Node identifier
155      * @param tableName name of the ovsdb table
156      * @param rowUuid UUID of the row being read
157      *
158      * @return Row corresponding to the UUID.
159      *
160      * <pre>
161      * Example:
162      *
163      * Request URL:
164      * https://localhost/controller/nb/v2/ovsdb/tables/bridge/rows/6f4c602c-026f-4390-beea-d50d6d448100
165      * </pre>
166      */
167
168     @Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows/{rowUuid}")
169     @GET
170     @StatusCodes({ @ResponseCode(code = 200, condition = "Row Updated successfully"),
171         @ResponseCode(code = 400, condition = "Invalid data passed"),
172         @ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
173     @Consumes({ MediaType.APPLICATION_JSON})
174     @TypeHint(String.class)
175     public String getRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
176                            @PathParam("tableName") String tableName, @PathParam("rowUuid") String rowUuid) {
177
178         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
179             throw new UnauthorizedException("User is not authorized to perform this operation");
180         }
181
182         String ovsTableName = getOVSTableName(tableName);
183         if (ovsTableName == null) return null;
184
185         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
186                                                                                             this);
187         if (ovsdbTable == null) {
188             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
189         }
190
191         Node node = Node.fromString(nodeType, nodeId);
192         //Table<?> row = null;
193         String row = null;
194         try {
195             row = ovsdbTable.getSerializedRow(node, ovsTableName, rowUuid);
196         } catch (Exception e) {
197             throw new BadRequestException(e.getMessage());
198         }
199         //return new OVSDBRow(null, row);
200         return row;
201     }
202
203     /**
204      * Read all Rows of a table
205      *
206      * @param node OVSDB Node identifier
207      * @param tableName name of the ovsdb table
208      *
209      * @return All the Rows of a table
210      *
211      * <pre>
212      * Example:
213      *
214      * Request URL:
215      * https://localhost/controller/nb/v2/ovsdb/tables/bridge/rows
216      * </pre>
217      */
218
219     @Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows")
220     @GET
221     @StatusCodes({ @ResponseCode(code = 200, condition = "Row Updated successfully"),
222         @ResponseCode(code = 400, condition = "Invalid data passed"),
223         @ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
224     @Consumes({ MediaType.APPLICATION_JSON})
225     @TypeHint(String.class)
226     public String getAllRows(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
227                                @PathParam("tableName") String tableName) {
228         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
229             throw new UnauthorizedException("User is not authorized to perform this operation");
230         }
231
232         String ovsTableName = getOVSTableName(tableName);
233         if (ovsTableName == null) return null;
234
235         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
236                                                                                             this);
237         if (ovsdbTable == null) {
238             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
239         }
240
241         Node node = Node.fromString(nodeType, nodeId);
242         //Map<String, Table<?>> rows = null;
243         String rows = null;
244         try {
245             rows = ovsdbTable.getSerializedRows(node, ovsTableName);
246         } catch (Exception e) {
247             throw new BadRequestException(e.getMessage());
248         }
249         //return new OVSDBRows(rows);
250         return rows;
251     }
252
253     /**
254      * Update a Row
255      *
256      * @param node OVSDB Node identifier
257      * @param tableName name of the ovsdb table
258      * @param rowUuid UUID of the row being updated
259      * @param row the {@link OVSDBRow} Row that is being inserted
260      *
261      * @return Response as dictated by the HTTP Response Status code
262      *
263      * <pre>
264      * Example:
265      *
266      * Request URL:
267      * PUT https://localhost/controller/nb/v2/ovsdb/tables/bridge/rows/6f4c602c-026f-4390-beea-d50d6d448100
268      * BODY
269      * {
270      *    "row":{
271      *       "Bridge":{
272      *          "datapath_type":"OPENFLOWv1.3",
273      *          "stp_enable":true
274      *        }
275      *     }
276      * }
277      * </pre>
278      */
279
280     @Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows/{rowUuid}")
281     @PUT
282     @StatusCodes({ @ResponseCode(code = 200, condition = "Row Updated successfully"),
283         @ResponseCode(code = 400, condition = "Invalid data passed"),
284         @ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
285     @Consumes({ MediaType.APPLICATION_JSON})
286     public Response updateRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
287                            @PathParam("tableName") String tableName, @PathParam("rowUuid") String rowUuid,
288                            @TypeHint(OVSDBRow.class) OVSDBRow row) {
289
290         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
291             throw new UnauthorizedException("User is not authorized to perform this operation");
292         }
293
294         String ovsTableName = getOVSTableName(tableName);
295         if (ovsTableName == null) {
296             Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
297             return NorthboundUtils.getResponse(status);
298         }
299
300         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
301                                                                                             this);
302         if (ovsdbTable == null) {
303             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
304         }
305
306         if (row != null && row.getRow() != null) {
307             handleNameMismatch(tableName, row.getRow().getTableName().getName());
308             Node node = Node.fromString(nodeType, nodeId);
309             Status status = ovsdbTable.updateRow(node, ovsTableName, row.getParent_uuid(), rowUuid, row.getRow());
310             return NorthboundUtils.getResponse(status);
311         }
312         return Response.status(Response.Status.BAD_REQUEST).build();
313     }
314
315     /**
316      * Delete a row
317      *
318      * @param tableName name of the ovsdb table
319      * @param uuid UUID of the Row to be removed
320      * @return Response as dictated by the HTTP Response Status code
321      *
322      * <pre>
323      * Example:
324      *
325      * Request URL:
326      * https://localhost/controller/nb/v2/ovsdb/tables/bridge/rows/41ab15a9-0dab-4675-a579-63019d4bcbec
327      *
328      * </pre>
329      */
330     @Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows/{uuid}")
331     @DELETE
332     @StatusCodes({ @ResponseCode(code = 204, condition = "User Deleted Successfully"),
333         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
334         @ResponseCode(code = 404, condition = "The userName passed was not found"),
335         @ResponseCode(code = 500, condition = "Internal Server Error : Removal of user failed"),
336         @ResponseCode(code = 503, condition = "Service unavailable") })
337     public Response removeRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
338                               @PathParam("tableName") String tableName, @PathParam("uuid") String uuid) {
339         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
340             throw new UnauthorizedException("User is not authorized to perform this operation");
341         }
342
343         String ovsTableName = getOVSTableName(tableName);
344         if (ovsTableName == null) {
345             Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
346             return NorthboundUtils.getResponse(status);
347         }
348
349         OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
350         if (ovsdbTable == null) {
351             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
352         }
353         Node node = Node.fromString(nodeType, nodeId);
354         Status status = ovsdbTable.deleteRow(node, ovsTableName, uuid);
355         if (status.isSuccess()) {
356             return Response.noContent().build();
357         }
358         return NorthboundUtils.getResponse(status);
359     }
360 }