383009b9d519366d9ffd3efe17783ad0be7624ad
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronNetworksNorthbound.java
1 /*\r
2  * Copyright IBM Corporation, 2013.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.controller.networkconfig.neutron.northbound;\r
10 \r
11 import java.util.ArrayList;\r
12 import java.util.HashMap;\r
13 import java.util.Iterator;\r
14 import java.util.List;\r
15 import javax.ws.rs.Consumes;\r
16 import javax.ws.rs.DELETE;\r
17 import javax.ws.rs.GET;\r
18 import javax.ws.rs.POST;\r
19 import javax.ws.rs.PUT;\r
20 import javax.ws.rs.Path;\r
21 import javax.ws.rs.PathParam;\r
22 import javax.ws.rs.Produces;\r
23 import javax.ws.rs.QueryParam;\r
24 import javax.ws.rs.core.MediaType;\r
25 import javax.ws.rs.core.Response;\r
26 \r
27 import org.codehaus.enunciate.jaxrs.ResponseCode;\r
28 import org.codehaus.enunciate.jaxrs.StatusCodes;\r
29 import org.codehaus.enunciate.jaxrs.TypeHint;\r
30 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;\r
31 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
32 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
33 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
34 import org.opendaylight.controller.northbound.commons.RestMessages;\r
35 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
36 import org.opendaylight.controller.sal.utils.ServiceHelper;\r
37 \r
38 /**\r
39  * Open DOVE Northbound REST APIs for Network.<br>\r
40  * This class provides REST APIs for managing open DOVE internals related to Networks\r
41  *\r
42  * <br>\r
43  * <br>\r
44  * Authentication scheme : <b>HTTP Basic</b><br>\r
45  * Authentication realm : <b>opendaylight</b><br>\r
46  * Transport : <b>HTTP and HTTPS</b><br>\r
47  * <br>\r
48  * HTTPS Authentication is disabled by default. Administrator can enable it in\r
49  * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
50  * trusted authority.<br>\r
51  * More info :\r
52  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
53  *\r
54  */\r
55 \r
56 @Path("/networks")\r
57 public class NeutronNetworksNorthbound {\r
58 \r
59     private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {\r
60         return o.extractFields(fields);\r
61     }\r
62 \r
63     /**\r
64      * Returns a list of all Networks */\r
65 \r
66     @GET\r
67     @Produces({ MediaType.APPLICATION_JSON })\r
68     //@TypeHint(OpenStackNetworks.class)\r
69     @StatusCodes({\r
70             @ResponseCode(code = 200, condition = "Operation successful"),\r
71             @ResponseCode(code = 401, condition = "Unauthorized") })\r
72     public Response listNetworks(\r
73             // return fields\r
74             @QueryParam("fields") List<String> fields,\r
75             // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
76             @QueryParam("id") String queryID,\r
77             @QueryParam("name") String queryName,\r
78             @QueryParam("admin_state_up") String queryAdminStateUp,\r
79             @QueryParam("status") String queryStatus,\r
80             @QueryParam("shared") String queryShared,\r
81             @QueryParam("tenant_id") String queryTenantID,\r
82             @QueryParam("router_external") String queryRouterExternal,\r
83             @QueryParam("provider_network_type") String queryProviderNetworkType,\r
84             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,\r
85             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,\r
86             // pagination\r
87             @QueryParam("limit") String limit,\r
88             @QueryParam("marker") String marker,\r
89             @QueryParam("page_reverse") String pageReverse\r
90             // sorting not supported\r
91         ) {\r
92         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
93         if (networkInterface == null) {\r
94             throw new ServiceUnavailableException("Network CRUD Interface "\r
95                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
96         }\r
97         List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();\r
98         List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
99         Iterator<NeutronNetwork> i = allNetworks.iterator();\r
100         while (i.hasNext()) {\r
101             NeutronNetwork oSN = i.next();\r
102             //match filters: TODO provider extension\r
103             Boolean bAdminStateUp = null;\r
104             Boolean bShared = null;\r
105             Boolean bRouterExternal = null;\r
106             if (queryAdminStateUp != null)\r
107                 bAdminStateUp = Boolean.valueOf(queryAdminStateUp);\r
108             if (queryShared != null)\r
109                 bShared = Boolean.valueOf(queryShared);\r
110             if (queryRouterExternal != null)\r
111                 bRouterExternal = Boolean.valueOf(queryRouterExternal);\r
112             if ((queryID == null || queryID.equals(oSN.getID())) &&\r
113                     (queryName == null || queryName.equals(oSN.getNetworkName())) &&\r
114                     (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&\r
115                     (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&\r
116                     (bShared == null || bShared.booleanValue() == oSN.isShared()) &&\r
117                     (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&\r
118                     (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {\r
119                 if (fields.size() > 0)\r
120                     ans.add(extractFields(oSN,fields));\r
121                 else\r
122                     ans.add(oSN);\r
123             }\r
124         }\r
125         //TODO: apply pagination to results\r
126         return Response.status(200).entity(\r
127                 new NeutronNetworkRequest(ans)).build();\r
128     }\r
129 \r
130     /**\r
131      * Returns a specific Network */\r
132 \r
133     @Path("{netUUID}")\r
134     @GET\r
135     @Produces({ MediaType.APPLICATION_JSON })\r
136     //@TypeHint(OpenStackNetworks.class)\r
137     @StatusCodes({\r
138             @ResponseCode(code = 200, condition = "Operation successful"),\r
139             @ResponseCode(code = 401, condition = "Unauthorized"),\r
140             @ResponseCode(code = 404, condition = "Not Found") })\r
141     public Response showNetwork(\r
142             @PathParam("netUUID") String netUUID,\r
143             // return fields\r
144             @QueryParam("fields") List<String> fields\r
145             ) {\r
146         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
147         if (networkInterface == null) {\r
148             throw new ServiceUnavailableException("Network CRUD Interface "\r
149                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
150         }\r
151         if (!networkInterface.networkExists(netUUID))\r
152             return Response.status(404).build();\r
153         if (fields.size() > 0) {\r
154             NeutronNetwork ans = networkInterface.getNetwork(netUUID);\r
155             return Response.status(200).entity(\r
156                     new NeutronNetworkRequest(extractFields(ans, fields))).build();\r
157         } else\r
158             return Response.status(200).entity(\r
159                     new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
160     }\r
161 \r
162     /**\r
163      * Creates new Networks */\r
164     @POST\r
165     @Produces({ MediaType.APPLICATION_JSON })\r
166     @Consumes({ MediaType.APPLICATION_JSON })\r
167     @TypeHint(NeutronNetwork.class)\r
168     @StatusCodes({\r
169             @ResponseCode(code = 201, condition = "Created"),\r
170             @ResponseCode(code = 400, condition = "Bad Request"),\r
171             @ResponseCode(code = 401, condition = "Unauthorized") })\r
172     public Response createNetworks(final NeutronNetworkRequest input) {\r
173         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
174         if (networkInterface == null) {\r
175             throw new ServiceUnavailableException("Network CRUD Interface "\r
176                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
177         }\r
178         if (input.isSingleton()) {\r
179             NeutronNetwork singleton = input.getSingleton();\r
180 \r
181             /*\r
182              * network ID can't already exist\r
183              */\r
184             if (networkInterface.networkExists(singleton.getID()))\r
185                 return Response.status(400).build();\r
186 \r
187             Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
188             if (instances != null) {\r
189                 for (Object instance : instances) {\r
190                     INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
191                     int status = service.canCreateNetwork(singleton);\r
192                     if (status < 200 || status > 299)\r
193                         return Response.status(status).build();\r
194                 }\r
195             }\r
196 \r
197             // add network to cache\r
198             networkInterface.addNetwork(singleton);\r
199             if (instances != null) {\r
200                 for (Object instance : instances) {\r
201                     INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
202                     service.neutronNetworkCreated(singleton);\r
203                 }\r
204             }\r
205 \r
206         } else {\r
207             List<NeutronNetwork> bulk = input.getBulk();\r
208             Iterator<NeutronNetwork> i = bulk.iterator();\r
209             HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();\r
210             Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
211             while (i.hasNext()) {\r
212                 NeutronNetwork test = i.next();\r
213 \r
214                 /*\r
215                  * network ID can't already exist, nor can there be an entry for this UUID\r
216                  * already in this bulk request\r
217                  */\r
218                 if (networkInterface.networkExists(test.getID()))\r
219                     return Response.status(400).build();\r
220                 if (testMap.containsKey(test.getID()))\r
221                     return Response.status(400).build();\r
222                 if (instances != null) {\r
223                     for (Object instance: instances) {\r
224                         INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
225                         int status = service.canCreateNetwork(test);\r
226                         if (status < 200 || status > 299)\r
227                             return Response.status(status).build();\r
228                     }\r
229                 }\r
230                 testMap.put(test.getID(),test);\r
231             }\r
232 \r
233             // now that everything passed, add items to the cache\r
234             i = bulk.iterator();\r
235             while (i.hasNext()) {\r
236                 NeutronNetwork test = i.next();\r
237                 test.initDefaults();\r
238                 networkInterface.addNetwork(test);\r
239                 if (instances != null) {\r
240                     for (Object instance: instances) {\r
241                         INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
242                         service.neutronNetworkCreated(test);\r
243                     }\r
244                 }\r
245             }\r
246         }\r
247         return Response.status(201).entity(input).build();\r
248     }\r
249 \r
250     /**\r
251      * Updates a Network */\r
252     @Path("{netUUID}")\r
253     @PUT\r
254     @Produces({ MediaType.APPLICATION_JSON })\r
255     @Consumes({ MediaType.APPLICATION_JSON })\r
256     //@TypeHint(OpenStackNetworks.class)\r
257     @StatusCodes({\r
258             @ResponseCode(code = 200, condition = "Operation successful"),\r
259             @ResponseCode(code = 400, condition = "Bad Request"),\r
260             @ResponseCode(code = 403, condition = "Forbidden"),\r
261             @ResponseCode(code = 404, condition = "Not Found"), })\r
262     public Response updateNetwork(\r
263             @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input\r
264             ) {\r
265         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
266         if (networkInterface == null) {\r
267             throw new ServiceUnavailableException("Network CRUD Interface "\r
268                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
269         }\r
270 \r
271         /*\r
272          * network has to exist and only a single delta is supported\r
273          */\r
274         if (!networkInterface.networkExists(netUUID))\r
275             return Response.status(404).build();\r
276         if (!input.isSingleton())\r
277             return Response.status(400).build();\r
278         NeutronNetwork delta = input.getSingleton();\r
279 \r
280         /*\r
281          * transitions forbidden by Neutron\r
282          */\r
283         if (delta.getID() != null || delta.getTenantID() != null ||\r
284                 delta.getStatus() != null)\r
285             return Response.status(400).build();\r
286 \r
287         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
288         if (instances != null) {\r
289             for (Object instance : instances) {\r
290                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
291                 NeutronNetwork original = networkInterface.getNetwork(netUUID);\r
292                 int status = service.canUpdateNetwork(delta, original);\r
293                 if (status < 200 || status > 299)\r
294                     return Response.status(status).build();\r
295             }\r
296         }\r
297 \r
298         // update network object and return the modified object\r
299         networkInterface.updateNetwork(netUUID, delta);\r
300         NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);\r
301         if (instances != null) {\r
302             for (Object instance : instances) {\r
303                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
304                 service.neutronNetworkUpdated(updatedSingleton);\r
305             }\r
306         }\r
307         return Response.status(200).entity(\r
308                 new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
309     }\r
310 \r
311     /**\r
312      * Deletes a Network */\r
313 \r
314     @Path("{netUUID}")\r
315     @DELETE\r
316     @StatusCodes({\r
317             @ResponseCode(code = 204, condition = "No Content"),\r
318             @ResponseCode(code = 401, condition = "Unauthorized"),\r
319             @ResponseCode(code = 404, condition = "Not Found"),\r
320             @ResponseCode(code = 409, condition = "Network In Use") })\r
321     public Response deleteNetwork(\r
322             @PathParam("netUUID") String netUUID) {\r
323         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
324         if (networkInterface == null) {\r
325             throw new ServiceUnavailableException("Network CRUD Interface "\r
326                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
327         }\r
328 \r
329         /*\r
330          * network has to exist and not be in use before it can be removed\r
331          */\r
332         if (!networkInterface.networkExists(netUUID))\r
333             return Response.status(404).build();\r
334         if (networkInterface.networkInUse(netUUID))\r
335             return Response.status(409).build();\r
336 \r
337         NeutronNetwork singleton = networkInterface.getNetwork(netUUID);\r
338         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
339         if (instances != null) {\r
340             for (Object instance : instances) {\r
341                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
342                 int status = service.canDeleteNetwork(singleton);\r
343                 if (status < 200 || status > 299)\r
344                     return Response.status(status).build();\r
345             }\r
346         }\r
347         networkInterface.removeNetwork(netUUID);\r
348         if (instances != null) {\r
349             for (Object instance : instances) {\r
350                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
351                 service.neutronNetworkDeleted(singleton);\r
352             }\r
353         }\r
354         return Response.status(204).build();\r
355     }\r
356 }\r