Merge "BUG-2288: DOMNotification API"
[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) {
66             username = context.getUserPrincipal().getName();
67         }
68     }
69     protected String getUserName() {
70         return username;
71     }
72
73     private IConnectionManager getConnectionManager() {
74         return (IConnectionManager) ServiceHelper
75                 .getGlobalInstance(IConnectionManager.class, this);
76     }
77
78     /**
79      *
80      * Retrieve a list of all the nodes connected to a given controller in the cluster.
81      *
82      * @param controllerAddress Optional parameter to retrieve the nodes connected to another
83      *        controller in the cluster
84      * @return A list of Nodes {@link org.opendaylight.controller.sal.core.Node}
85      *
86      * <pre>
87      *
88      * Example:
89      *
90      * Request URL:
91      * http://localhost:8080/controller/nb/v2/connectionmanager/nodes?controller=1.1.1.1
92      *
93      * Response body in XML:
94      *  &lt;list&gt;
95      *       &lt;node&gt;
96      *           &lt;id&gt;00:00:00:00:00:00:00:52&lt;/id&gt;
97      *           &lt;type&gt;OF&lt;/type&gt;
98      *       &lt;/node&gt;
99      *       &lt;node&gt;
100      *           &lt;id&gt;00:00:00:00:00:00:00:3e&lt;/id&gt;
101      *           &lt;type&gt;OF&lt;/type&gt;
102      *       &lt;/node&gt;
103      *   &lt;/list&gt;
104      *
105      *  Response body in JSON:
106      *  {
107      *       "node": [
108      *           {
109      *               "type": "OF",
110      *               "id": "00:00:00:00:00:00:00:52"
111      *           },
112      *           {
113      *               "type": "OF",
114      *               "id": "00:00:00:00:00:00:00:3e"
115      *           }
116      *       ]
117      *   }
118      * </pre>
119      */
120     @Path("/nodes")
121     @GET
122     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
123     @TypeHint(Nodes.class)
124     @StatusCodes( {
125         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
126         @ResponseCode(code = 406, condition = "Invalid Controller IP Address passed."),
127         @ResponseCode(code = 503, condition = "Connection Manager Service not available")})
128
129     public Nodes getNodes(@DefaultValue("") @QueryParam("controller") String controllerAddress,
130         @QueryParam("_q") String queryString) {
131         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.READ, this)) {
132             throw new UnauthorizedException("User is not authorized to perform this operation on container");
133         }
134
135         IConnectionManager connectionManager = getConnectionManager();
136         if (connectionManager == null) {
137             throw new ServiceUnavailableException("IConnectionManager not available.");
138         }
139
140         if ((controllerAddress != null) && (controllerAddress.trim().length() > 0) &&
141             !NetUtils.isIPv4AddressValid(controllerAddress)) {
142             throw new NotAcceptableException("Invalid ip address "+controllerAddress);
143         }
144         Set<Node> nodeSet = null;
145
146         if (controllerAddress != null) {
147             try {
148                 nodeSet = connectionManager.getNodes(InetAddress.getByName(controllerAddress));
149             } catch (UnknownHostException e) {
150                 throw new NotAcceptableException("Invalid ip address "+controllerAddress);
151             }
152         } else {
153             nodeSet = connectionManager.getLocalNodes();
154         }
155         Nodes nodes = new Nodes(nodeSet);
156         if (queryString != null) {
157             queryContext.createQuery(queryString, Nodes.class)
158                 .filter(nodes, Node.class);
159         }
160         return nodes;
161     }
162
163     /**
164      * If a Network Configuration Service needs a Management Connection and if the
165      * Node Type is unknown, use this REST api to connect to the management session.
166      * <pre>
167      *
168      * Example :
169      *
170      * Request :
171      * PUT http://localhost:8080/controller/nb/v2/connectionmanager/node/mgmt1/address/1.1.1.1/port/6634
172      *
173      * Response :
174      * Node :
175      * xml :
176      * &lt;node&gt;
177      *    &lt;id&gt;mgmt1&lt;/id&gt;
178      *    &lt;type&gt;STUB&lt;/type&gt;
179      * &lt;/node&gt;
180      *
181      * json:
182      * {"id": "mgmt1","type": "STUB"}
183      *
184      *</pre>
185      * @param nodeId User-Defined name of the node to connect with. This can be any alpha numeric value
186      * @param ipAddress IP Address of the Node to connect with.
187      * @param port Layer4 Port of the management session to connect with.
188      * @return Node If the connection is successful, HTTP 404 otherwise.
189      */
190
191     @Path("/node/{nodeId}/address/{ipAddress}/port/{port}/")
192     @PUT
193     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
194     @TypeHint(Node.class)
195     @StatusCodes( {
196         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
197         @ResponseCode(code = 404, condition = "Could not connect to the Node with the specified parameters"),
198         @ResponseCode(code = 406, condition = "Invalid IP Address or Port parameter passed."),
199         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
200     public Node connect(
201             @PathParam(value = "nodeId") String nodeId,
202             @PathParam(value = "ipAddress") String ipAddress,
203             @PathParam(value = "port") String port) {
204
205         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
206             throw new UnauthorizedException("User is not authorized to perform this operation on container");
207         }
208
209         IConnectionManager connectionManager = getConnectionManager();
210         if (connectionManager == null) {
211             throw new ServiceUnavailableException("IConnectionManager not available.");
212         }
213
214         if (!NetUtils.isIPv4AddressValid(ipAddress)) {
215             throw new NotAcceptableException("Invalid ip address "+ipAddress);
216         }
217
218         try {
219             Integer.parseInt(port);
220         } catch (Exception e) {
221             throw new NotAcceptableException("Invalid Layer4 Port "+port);
222         }
223
224         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
225         params.put(ConnectionConstants.ADDRESS, ipAddress);
226         params.put(ConnectionConstants.PORT, port);
227
228         Node node = null;
229         try {
230             node = connectionManager.connect(nodeId, params);
231             if (node == null) {
232                 throw new ResourceNotFoundException("Failed to connect to Node at "+ipAddress+":"+port);
233             }
234             return node;
235         } catch (Exception e) {
236             throw new ResourceNotFoundException("Failed to connect to Node with Exception "+e.getMessage());
237         }
238     }
239
240     /**
241      * If a Network Configuration Service needs a Management Connection, and if the
242      * node Type is known, the user can choose to use this REST api to connect to the management session.
243      * <pre>
244      *
245      * Example :
246      *
247      * Request :
248      * PUT http://localhost:8080/controller/nb/v2/connectionmanager/node/STUB/mgmt1/address/1.1.1.1/port/6634
249      *
250      * Response : Node :
251      * xml :
252      * &lt;node&gt;
253      *    &lt;id&gt;mgmt1&lt;/id&gt;
254      *    &lt;type&gt;STUB&lt;/type&gt;
255      * &lt;/node&gt;
256      *
257      * json:
258      * {"id": "mgmt1","type": "STUB"}
259      *
260      *</pre>
261      * @param nodeType Type of the Node the connection is made for.
262      * @param nodeId User-Defined name of the node to connect with. This can be any alpha numeric value
263      * @param ipAddress IP Address of the Node to connect with.
264      * @param port Layer4 Port of the management session to connect with.
265      * @return Node If the connection is successful, HTTP 404 otherwise.
266      */
267
268     @Path("/node/{nodeType}/{nodeId}/address/{ipAddress}/port/{port}/")
269     @PUT
270     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
271     @TypeHint(Node.class)
272     @StatusCodes( {
273         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
274         @ResponseCode(code = 404, condition = "Could not connect to the Node with the specified parameters"),
275         @ResponseCode(code = 406, condition = "Invalid IP Address or Port parameter passed."),
276         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
277     public Node connect(
278             @PathParam(value = "nodeType") String nodeType,
279             @PathParam(value = "nodeId") String nodeId,
280             @PathParam(value = "ipAddress") String ipAddress,
281             @PathParam(value = "port") String port) {
282
283         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
284             throw new UnauthorizedException("User is not authorized to perform this operation on container");
285         }
286
287         IConnectionManager connectionManager = getConnectionManager();
288         if (connectionManager == null) {
289             throw new ServiceUnavailableException("IConnectionManager not available.");
290         }
291
292         if (!NetUtils.isIPv4AddressValid(ipAddress)) {
293             throw new NotAcceptableException("Invalid ip address "+ipAddress);
294         }
295
296         try {
297             Integer.parseInt(port);
298         } catch (Exception e) {
299             throw new NotAcceptableException("Invalid Layer4 Port "+port);
300         }
301
302         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
303         params.put(ConnectionConstants.ADDRESS, ipAddress);
304         params.put(ConnectionConstants.PORT, port);
305
306         Node node = null;
307         try {
308             node = connectionManager.connect(nodeType, nodeId, params);
309             if (node == null) {
310                 throw new ResourceNotFoundException("Failed to connect to Node at "+ipAddress+":"+port);
311             }
312             return node;
313         } catch (Exception e) {
314             throw new ResourceNotFoundException(e.getMessage());
315         }
316     }
317
318     /**
319      * Disconnect an existing Connection.
320      * <pre>
321      *
322      * Example :
323      *
324      * Request :
325      * DELETE http://localhost:8080/controller/nb/v2/connectionmanager/node/STUB/mgmt1
326      *
327      *</pre>
328      * @param nodeType Type of the Node
329      * @param nodeId Connection's NodeId.
330      */
331
332     @Path("/node/{nodeType}/{nodeId}/")
333     @DELETE
334     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
335     @TypeHint(Response.class)
336     @StatusCodes( {
337         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
338         @ResponseCode(code = 200, condition = "Node disconnected successfully"),
339         @ResponseCode(code = 404, condition = "Could not find a connection with the specified Node identifier"),
340         @ResponseCode(code = 503, condition = "Connection Manager Service not available")} )
341     public Response disconnect(
342             @PathParam(value = "nodeType") String nodeType,
343             @PathParam(value = "nodeId") String nodeId) {
344
345         if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
346             throw new UnauthorizedException("User is not authorized to perform this operation on container");
347         }
348         IConnectionManager connectionManager = getConnectionManager();
349         if (connectionManager == null) {
350             throw new ServiceUnavailableException("IConnectionManager not available.");
351         }
352
353         try {
354             Node node = Node.fromString(nodeType, nodeId);
355             Status status = connectionManager.disconnect(node);
356             if (status.isSuccess()) {
357                 return Response.ok().build();
358             }
359             return NorthboundUtils.getResponse(status);
360         } catch (Exception e) {
361             throw new ResourceNotFoundException(e.getMessage());
362         }
363     }
364 }