Merge "Updating features archetype to talk about user-facing features."
[controller.git] / opendaylight / adsal / northbound / connectionmanager / src / main / java / org / opendaylight / controller / connectionmanager / northbound / ConnectionManagerNorthbound.java
1
2 /*
3  * Copyright (c) 2013 Red Hat, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.connectionmanager.northbound;
11
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.HashMap;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.DefaultValue;
20 import javax.ws.rs.GET;
21 import javax.ws.rs.PUT;
22 import javax.ws.rs.Path;
23 import javax.ws.rs.PathParam;
24 import javax.ws.rs.Produces;
25 import javax.ws.rs.QueryParam;
26 import javax.ws.rs.core.Context;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
29 import javax.ws.rs.core.SecurityContext;
30 import javax.ws.rs.ext.ContextResolver;
31
32 import org.codehaus.enunciate.jaxrs.ResponseCode;
33 import org.codehaus.enunciate.jaxrs.StatusCodes;
34 import org.codehaus.enunciate.jaxrs.TypeHint;
35 import org.opendaylight.controller.connectionmanager.IConnectionManager;
36 import org.opendaylight.controller.northbound.commons.exception.NotAcceptableException;
37 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
38 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
39 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
40 import org.opendaylight.controller.northbound.commons.query.QueryContext;
41 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
42 import org.opendaylight.controller.sal.authorization.Privilege;
43 import org.opendaylight.controller.sal.connection.ConnectionConstants;
44 import org.opendaylight.controller.sal.core.Node;
45 import org.opendaylight.controller.sal.utils.NetUtils;
46 import org.opendaylight.controller.sal.utils.ServiceHelper;
47 import org.opendaylight.controller.sal.utils.Status;
48
49 /**
50  * Connection Manager Northbound APIs
51  */
52 @Path("/")
53 public class ConnectionManagerNorthbound {
54     private String username;
55     private QueryContext queryContext;
56
57     @Context
58     public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
59       if (queryCtxResolver != null) {
60         queryContext = queryCtxResolver.getContext(QueryContext.class);
61       }
62     }
63     @Context
64     public void setSecurityContext(SecurityContext context) {
65         if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
66     }
67     protected String getUserName() {
68         return username;
69     }
70
71     private IConnectionManager getConnectionManager() {
72         return (IConnectionManager) ServiceHelper
73                 .getGlobalInstance(IConnectionManager.class, this);
74     }
75
76     /**
77      *
78      * Retrieve a list of all the nodes connected to a given controller in the cluster.
79      *
80      * @param controllerAddress Optional parameter to retrieve the nodes connected to another
81      *        controller in the cluster
82      * @return A list of Nodes {@link org.opendaylight.controller.sal.core.Node}
83      *
84      * <pre>
85      *
86      * Example:
87      *
88      * Request URL:
89      * http://localhost:8080/controller/nb/v2/connectionmanager/nodes?controller=1.1.1.1
90      *
91      * Response body in XML:
92      *  &lt;list&gt;
93      *       &lt;node&gt;
94      *           &lt;id&gt;00:00:00:00:00:00:00:52&lt;/id&gt;
95      *           &lt;type&gt;OF&lt;/type&gt;
96      *       &lt;/node&gt;
97      *       &lt;node&gt;
98      *           &lt;id&gt;00:00:00:00:00:00:00:3e&lt;/id&gt;
99      *           &lt;type&gt;OF&lt;/type&gt;
100      *       &lt;/node&gt;
101      *   &lt;/list&gt;
102      *
103      *  Response body in JSON:
104      *  {
105      *       "node": [
106      *           {
107      *               "type": "OF",
108      *               "id": "00:00:00:00:00:00:00:52"
109      *           },
110      *           {
111      *               "type": "OF",
112      *               "id": "00:00:00:00:00:00:00:3e"
113      *           }
114      *       ]
115      *   }
116      * </pre>
117      */
118     @Path("/nodes")
119     @GET
120     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
121     @TypeHint(Nodes.class)
122     @StatusCodes( {
123         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
124         @ResponseCode(code = 406, condition = "Invalid Controller IP Address passed."),
125         @ResponseCode(code = 503, condition = "Connection Manager Service not available")})
126
127     public Nodes getNodes(@DefaultValue("") @QueryParam("controller") String controllerAddress,
128         @QueryParam("_q") String queryString) {
129         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.READ, this)) {
130             throw new UnauthorizedException("User is not authorized to perform this operation on container");
131         }
132
133         IConnectionManager connectionManager = getConnectionManager();
134         if (connectionManager == null) {
135             throw new ServiceUnavailableException("IConnectionManager not available.");
136         }
137
138         if ((controllerAddress != null) && (controllerAddress.trim().length() > 0) &&
139             !NetUtils.isIPv4AddressValid(controllerAddress)) {
140             throw new NotAcceptableException("Invalid ip address "+controllerAddress);
141         }
142         Set<Node> nodeSet = null;
143
144         if (controllerAddress != null) {
145             try {
146                 nodeSet = connectionManager.getNodes(InetAddress.getByName(controllerAddress));
147             } catch (UnknownHostException e) {
148                 throw new NotAcceptableException("Invalid ip address "+controllerAddress);
149             }
150         } else {
151             nodeSet = connectionManager.getLocalNodes();
152         }
153         Nodes nodes = new Nodes(nodeSet);
154         if (queryString != null) {
155             queryContext.createQuery(queryString, Nodes.class)
156                 .filter(nodes, Node.class);
157         }
158         return nodes;
159     }
160
161     /**
162      * If a Network Configuration Service needs a Management Connection and if the
163      * Node Type is unknown, use this REST api to connect to the management session.
164      * <pre>
165      *
166      * Example :
167      *
168      * Request :
169      * PUT http://localhost:8080/controller/nb/v2/connectionmanager/node/mgmt1/address/1.1.1.1/port/6634
170      *
171      * Response :
172      * Node :
173      * xml :
174      * &lt;node&gt;
175      *    &lt;id&gt;mgmt1&lt;/id&gt;
176      *    &lt;type&gt;STUB&lt;/type&gt;
177      * &lt;/node&gt;
178      *
179      * json:
180      * {"id": "mgmt1","type": "STUB"}
181      *
182      *</pre>
183      * @param nodeId User-Defined name of the node to connect with. This can be any alpha numeric value
184      * @param ipAddress IP Address of the Node to connect with.
185      * @param port Layer4 Port of the management session to connect with.
186      * @return Node If the connection is successful, HTTP 404 otherwise.
187      */
188
189     @Path("/node/{nodeId}/address/{ipAddress}/port/{port}/")
190     @PUT
191     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
192     @TypeHint(Node.class)
193     @StatusCodes( {
194         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
195         @ResponseCode(code = 404, condition = "Could not connect to the Node with the specified parameters"),
196         @ResponseCode(code = 406, condition = "Invalid IP Address or Port parameter passed."),
197         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
198     public Node connect(
199             @PathParam(value = "nodeId") String nodeId,
200             @PathParam(value = "ipAddress") String ipAddress,
201             @PathParam(value = "port") String port) {
202
203         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
204             throw new UnauthorizedException("User is not authorized to perform this operation on container");
205         }
206
207         IConnectionManager connectionManager = getConnectionManager();
208         if (connectionManager == null) {
209             throw new ServiceUnavailableException("IConnectionManager not available.");
210         }
211
212         if (!NetUtils.isIPv4AddressValid(ipAddress)) {
213             throw new NotAcceptableException("Invalid ip address "+ipAddress);
214         }
215
216         try {
217             Integer.parseInt(port);
218         } catch (Exception e) {
219             throw new NotAcceptableException("Invalid Layer4 Port "+port);
220         }
221
222         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
223         params.put(ConnectionConstants.ADDRESS, ipAddress);
224         params.put(ConnectionConstants.PORT, port);
225
226         Node node = null;
227         try {
228             node = connectionManager.connect(nodeId, params);
229             if (node == null) {
230                 throw new ResourceNotFoundException("Failed to connect to Node at "+ipAddress+":"+port);
231             }
232             return node;
233         } catch (Exception e) {
234             throw new ResourceNotFoundException("Failed to connect to Node with Exception "+e.getMessage());
235         }
236     }
237
238     /**
239      * If a Network Configuration Service needs a Management Connection, and if the
240      * node Type is known, the user can choose to use this REST api to connect to the management session.
241      * <pre>
242      *
243      * Example :
244      *
245      * Request :
246      * PUT http://localhost:8080/controller/nb/v2/connectionmanager/node/STUB/mgmt1/address/1.1.1.1/port/6634
247      *
248      * Response : Node :
249      * xml :
250      * &lt;node&gt;
251      *    &lt;id&gt;mgmt1&lt;/id&gt;
252      *    &lt;type&gt;STUB&lt;/type&gt;
253      * &lt;/node&gt;
254      *
255      * json:
256      * {"id": "mgmt1","type": "STUB"}
257      *
258      *</pre>
259      * @param nodeType Type of the Node the connection is made for.
260      * @param nodeId User-Defined name of the node to connect with. This can be any alpha numeric value
261      * @param ipAddress IP Address of the Node to connect with.
262      * @param port Layer4 Port of the management session to connect with.
263      * @return Node If the connection is successful, HTTP 404 otherwise.
264      */
265
266     @Path("/node/{nodeType}/{nodeId}/address/{ipAddress}/port/{port}/")
267     @PUT
268     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
269     @TypeHint(Node.class)
270     @StatusCodes( {
271         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
272         @ResponseCode(code = 404, condition = "Could not connect to the Node with the specified parameters"),
273         @ResponseCode(code = 406, condition = "Invalid IP Address or Port parameter passed."),
274         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
275     public Node connect(
276             @PathParam(value = "nodeType") String nodeType,
277             @PathParam(value = "nodeId") String nodeId,
278             @PathParam(value = "ipAddress") String ipAddress,
279             @PathParam(value = "port") String port) {
280
281         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
282             throw new UnauthorizedException("User is not authorized to perform this operation on container");
283         }
284
285         IConnectionManager connectionManager = getConnectionManager();
286         if (connectionManager == null) {
287             throw new ServiceUnavailableException("IConnectionManager not available.");
288         }
289
290         if (!NetUtils.isIPv4AddressValid(ipAddress)) {
291             throw new NotAcceptableException("Invalid ip address "+ipAddress);
292         }
293
294         try {
295             Integer.parseInt(port);
296         } catch (Exception e) {
297             throw new NotAcceptableException("Invalid Layer4 Port "+port);
298         }
299
300         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
301         params.put(ConnectionConstants.ADDRESS, ipAddress);
302         params.put(ConnectionConstants.PORT, port);
303
304         Node node = null;
305         try {
306             node = connectionManager.connect(nodeType, nodeId, params);
307             if (node == null) {
308                 throw new ResourceNotFoundException("Failed to connect to Node at "+ipAddress+":"+port);
309             }
310             return node;
311         } catch (Exception e) {
312             throw new ResourceNotFoundException(e.getMessage());
313         }
314     }
315
316     /**
317      * Disconnect an existing Connection.
318      * <pre>
319      *
320      * Example :
321      *
322      * Request :
323      * DELETE http://localhost:8080/controller/nb/v2/connectionmanager/node/STUB/mgmt1
324      *
325      *</pre>
326      * @param nodeType Type of the Node
327      * @param nodeId Connection's NodeId.
328      */
329
330     @Path("/node/{nodeType}/{nodeId}/")
331     @DELETE
332     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
333     @TypeHint(Response.class)
334     @StatusCodes( {
335         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
336         @ResponseCode(code = 200, condition = "Node disconnected successfully"),
337         @ResponseCode(code = 404, condition = "Could not find a connection with the specified Node identifier"),
338         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
339     public Response disconnect(
340             @PathParam(value = "nodeType") String nodeType,
341             @PathParam(value = "nodeId") String nodeId) {
342
343         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
344             throw new UnauthorizedException("User is not authorized to perform this operation on container");
345         }
346         IConnectionManager connectionManager = getConnectionManager();
347         if (connectionManager == null) {
348             throw new ServiceUnavailableException("IConnectionManager not available.");
349         }
350
351         try {
352             Node node = Node.fromString(nodeType, nodeId);
353             Status status = connectionManager.disconnect(node);
354             if (status.isSuccess()) {
355                 return Response.ok().build();
356             }
357             return NorthboundUtils.getResponse(status);
358         } catch (Exception e) {
359             throw new ResourceNotFoundException(e.getMessage());
360         }
361     }
362 }